Skip to content

Instantly share code, notes, and snippets.

@markwhi
Created August 30, 2013 10:36
Show Gist options
  • Save markwhi/6388557 to your computer and use it in GitHub Desktop.
Save markwhi/6388557 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use strict ;
use warnings ;
my $src = shift or die "usage: $0 <file>\n" ;
my $src_file = "${src}.src.lua" ;
my $out_file = "${src}.lua" ;
die ("Can't find source file ${src_file} for ${src}.\n") unless (-f $src_file) ;
my ($fh_in, $fh_out, $data) ;
open($fh_in, "<", $src_file) or die "Unable to open $src_file: $!\n" ;
while (<$fh_in>) {
if ($_ =~ /^##Include (\w+)##/) {
$data .= read_include($1) ;
} else {
$data .= $_ ;
}
}
close ($fh_in) ;
open($fh_out, ">", $out_file) or die "Unable to open $out_file: $!\n" ;
print $fh_out $data ;
close ($fh_out) ;
sub read_include {
my ($inc) = @_ ;
my ($file, $fh, $data) ;
$file = "${inc}.lib.lua" ;
open ($fh, "<", $file) or die "Unable to read file ${file} for include ${inc}: $!\n" ;
$data .= "-- ## Included ${inc} ## --\n" ;
while (<$fh>) {
$data .= $_ ;
}
$data .= "\n" ;
close ($fh) ;
return $data ;
}
----
---- Display Class
CCDisplay = {}
CCDisplay.__index = CCDisplay
function CCDisplay.create(options)
local display = {}
setmetatable(display, CCDisplay)
if type(options.side) ~= "string" then
error("required argument 'side' missing")
end
local textSize = 1
if (options.textSize) then
if type(options.textSize) == "number" then
textSize = options.textSize
if (textSize <= 0.5 and textSize >= 5) then
error("invalid textSize "..textSize.." (must be 0.5 to 5)")
end
else
error("invalid textSize (must be a number)")
end
end
local m = peripheral.wrap(options.side)
if m then
m.clear()
m.setTextScale(textSize)
local w, h = m.getSize()
display.monitor = m
display.line = 1
display.width = w
display.height = h
return display
else
error("Unable to find a monitor on side "..side)
end
return display
end
function CCDisplay:clear()
if self.monitor then
self.monitor.clear()
self.line = 1
end
end
-- Print a string with optional formatting
function CCDisplay:print(options)
local str
local center = false
local color = colors.white
if type(options) == "table" then
if type(options.str) ~= "string" then
error("required argument 'str' missing")
else
str = options.str
end
if type(options.color) == "number" then
color = options.color
end
if options.center then
center = true
end
else
str = options
end
local column = 1
if center then
column = self:getCenterStartColumn(#str)
end
self.monitor.setTextColor(color)
-- todo: support scrolling
self.monitor.setCursorPos(column, self.line)
self.monitor.write(str)
self.line = self.line + 1
end
-- Calculate the starting column to display a centered string on
-- the attached monitor
function CCDisplay:getCenterStartColumn(len)
local width = self.width
return 1 + ((width / 2) - (len / 2))
end
----
---- Formatted Text Class
----
---- Downloads text from a URL, splits it into strings with optional formatting
FormattedText = {}
FormattedText.__index = FormattedText
function FormattedText.create(url)
local ft = {}
setmetatable(ft, FormattedText)
ft.url = url
ft.lines = {}
ft.raw = nil
ft.curLine = 0
write("Downloading from "..url.."...")
local response = http.get(url)
if response then
print(" success.")
ft.raw = response.readAll()
response.close()
else
write(" failed.")
return ft
end
write("Parsing lines...")
local lines = {}
local function cb(line) table.insert(lines, line.."") return "" end
cb((ft.raw:gsub("(.-)\r?\n", cb)))
ft.lines = lines
print(" done. "..(#ft.lines).." lines read.")
ft.curLine = 1
return ft
end
function FormattedText:reset()
if self.lines then
self.curLine = 1
end
end
function FormattedText:lineCount()
if self.lines then
return #self.lines
else
error("Invalid FormattedText object")
end
end
-- Parses a string looking for: (formatting)#(string)
-- Formatting characters:
-- "-" - center text
-- number - color code
--
-- Returns a table with the keys:
-- center - if text should be centered
-- color - if a color was specified
-- string - the string value
function FormattedText:getNextLine()
local lineIndex
local data = {}
local format, str
if #self.lines then
lineIndex = self.curLine
if (lineIndex > self:lineCount()) then
return nil
end
else
error("no lines found")
end
s = self.lines[lineIndex]
if not s then
return nil
end
if s:sub(1,1) == "!" then
s = s:sub(2)
local sepIndex, ignore = string.find(s, "!", 1, true)
if sepIndex then
data["str"] = s:sub(sepIndex)
format = s:sub(1, sepIndex - 1)
local color = format:match("([a-z]+)")
if color then
if colors[color] then
data["color"] = colors[color]
else
print("Error on line "..lineIndex..": invalid color "..color)
data["color"] = colors.white
end
end
local center = format:find("-", 1, true)
if center then
data["center"] = true
end
else
data["str"] = s
end
else
data["str"] = s
end
self.curLine = self.curLine + 1
return data
end
# URL to retrieve display text from
url="http://whatever/foo.txt"
# Side for monitor
monitorSide="top"
##Include FormattedText##
##Include CCDisplay##
monitor = CCDisplay.create{side=monitorSide}
rules = FormattedText.create(url)
while true do
local line = rules:getNextLine()
if line then
monitor:print(line)
else
break
end
line = nil
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment