1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-11 18:00:29 +00:00

Reformat bracketed expressions in Lua

- Parenthesised expressions (function calls, arguments, etc...) should
   never have spaces in them.
 - Tables always will have spaces inside.
This commit is contained in:
SquidDev 2020-04-18 10:09:40 +01:00
parent f9f94b8304
commit 865fc239a0
78 changed files with 2168 additions and 2159 deletions

View File

@ -25,6 +25,8 @@
(at / (at /
(linters (linters
syntax:string-index
;; It'd be nice to avoid this, but right now there's a lot of instances of ;; It'd be nice to avoid this, but right now there's a lot of instances of
;; it. ;; it.
-var:set-loop -var:set-loop
@ -36,7 +38,14 @@
;; Suppress a couple of documentation comments warnings for now. We'll ;; Suppress a couple of documentation comments warnings for now. We'll
;; hopefully be able to remove them in the future. ;; hopefully be able to remove them in the future.
-doc:undocumented -doc:undocumented-arg -doc:unresolved-reference -doc:undocumented -doc:undocumented-arg -doc:unresolved-reference
-var:unresolved-member)) -var:unresolved-member)
(lint
(bracket-spaces
(call no-space)
(function-args no-space)
(parens no-space)
(table space)
(index no-space))))
;; We disable the unused global linter in bios.lua and the APIs. In the future ;; We disable the unused global linter in bios.lua and the APIs. In the future
;; hopefully we'll get illuaminate to handle this. ;; hopefully we'll get illuaminate to handle this.

View File

@ -33,41 +33,41 @@ if _VERSION == "Lua 5.1" then
end end
end end
function load( x, name, mode, env ) function load(x, name, mode, env)
expect(1, x, "function", "string") expect(1, x, "function", "string")
expect(2, name, "string", "nil") expect(2, name, "string", "nil")
expect(3, mode, "string", "nil") expect(3, mode, "string", "nil")
expect(4, env, "table", "nil") expect(4, env, "table", "nil")
local ok, p1, p2 = pcall( function() local ok, p1, p2 = pcall(function()
if type(x) == "string" then if type(x) == "string" then
local result, err = nativeloadstring( x, name ) local result, err = nativeloadstring(x, name)
if result then if result then
if env then if env then
env._ENV = env env._ENV = env
nativesetfenv( result, env ) nativesetfenv(result, env)
end end
return result return result
else else
return nil, err return nil, err
end end
else else
local result, err = nativeload( x, name ) local result, err = nativeload(x, name)
if result then if result then
if env then if env then
env._ENV = env env._ENV = env
nativesetfenv( result, env ) nativesetfenv(result, env)
end end
return result return result
else else
return nil, err return nil, err
end end
end end
end ) end)
if ok then if ok then
return p1, p2 return p1, p2
else else
error( p1, 2 ) error(p1, 2)
end end
end end
@ -81,7 +81,7 @@ if _VERSION == "Lua 5.1" then
math.log10 = nil math.log10 = nil
table.maxn = nil table.maxn = nil
else else
loadstring = function(string, chunkname) return nativeloadstring(string, prefix( chunkname )) end loadstring = function(string, chunkname) return nativeloadstring(string, prefix(chunkname)) end
-- Inject a stub for the old bit library -- Inject a stub for the old bit library
_G.bit = { _G.bit = {
@ -101,28 +101,28 @@ function os.version()
return "CraftOS 1.8" return "CraftOS 1.8"
end end
function os.pullEventRaw( sFilter ) function os.pullEventRaw(sFilter)
return coroutine.yield( sFilter ) return coroutine.yield(sFilter)
end end
function os.pullEvent( sFilter ) function os.pullEvent(sFilter)
local eventData = table.pack( os.pullEventRaw( sFilter ) ) local eventData = table.pack(os.pullEventRaw(sFilter))
if eventData[1] == "terminate" then if eventData[1] == "terminate" then
error( "Terminated", 0 ) error("Terminated", 0)
end end
return table.unpack( eventData, 1, eventData.n ) return table.unpack(eventData, 1, eventData.n)
end end
-- Install globals -- Install globals
function sleep( nTime ) function sleep(nTime)
expect(1, nTime, "number", "nil") expect(1, nTime, "number", "nil")
local timer = os.startTimer( nTime or 0 ) local timer = os.startTimer(nTime or 0)
repeat repeat
local _, param = os.pullEvent( "timer" ) local _, param = os.pullEvent("timer")
until param == timer until param == timer
end end
function write( sText ) function write(sText)
expect(1, sText, "string", "number") expect(1, sText, "string", "number")
local w, h = term.getSize() local w, h = term.getSize()
@ -143,32 +143,32 @@ function write( sText )
-- Print the line with proper word wrapping -- Print the line with proper word wrapping
sText = tostring(sText) sText = tostring(sText)
while #sText > 0 do while #sText > 0 do
local whitespace = string.match( sText, "^[ \t]+" ) local whitespace = string.match(sText, "^[ \t]+")
if whitespace then if whitespace then
-- Print whitespace -- Print whitespace
term.write( whitespace ) term.write(whitespace)
x, y = term.getCursorPos() x, y = term.getCursorPos()
sText = string.sub( sText, #whitespace + 1 ) sText = string.sub(sText, #whitespace + 1)
end end
local newline = string.match( sText, "^\n" ) local newline = string.match(sText, "^\n")
if newline then if newline then
-- Print newlines -- Print newlines
newLine() newLine()
sText = string.sub( sText, 2 ) sText = string.sub(sText, 2)
end end
local text = string.match( sText, "^[^ \t\n]+" ) local text = string.match(sText, "^[^ \t\n]+")
if text then if text then
sText = string.sub( sText, #text + 1 ) sText = string.sub(sText, #text + 1)
if #text > w then if #text > w then
-- Print a multiline word -- Print a multiline word
while #text > 0 do while #text > 0 do
if x > w then if x > w then
newLine() newLine()
end end
term.write( text ) term.write(text)
text = string.sub( text, w - x + 2 ) text = string.sub(text, w - x + 2)
x, y = term.getCursorPos() x, y = term.getCursorPos()
end end
else else
@ -176,7 +176,7 @@ function write( sText )
if x + #text - 1 > w then if x + #text - 1 > w then
newLine() newLine()
end end
term.write( text ) term.write(text)
x, y = term.getCursorPos() x, y = term.getCursorPos()
end end
end end
@ -185,42 +185,42 @@ function write( sText )
return nLinesPrinted return nLinesPrinted
end end
function print( ... ) function print(...)
local nLinesPrinted = 0 local nLinesPrinted = 0
local nLimit = select("#", ...) local nLimit = select("#", ...)
for n = 1, nLimit do for n = 1, nLimit do
local s = tostring( select( n, ... ) ) local s = tostring(select(n, ...))
if n < nLimit then if n < nLimit then
s = s .. "\t" s = s .. "\t"
end end
nLinesPrinted = nLinesPrinted + write( s ) nLinesPrinted = nLinesPrinted + write(s)
end end
nLinesPrinted = nLinesPrinted + write( "\n" ) nLinesPrinted = nLinesPrinted + write("\n")
return nLinesPrinted return nLinesPrinted
end end
function printError( ... ) function printError(...)
local oldColour local oldColour
if term.isColour() then if term.isColour() then
oldColour = term.getTextColour() oldColour = term.getTextColour()
term.setTextColour( colors.red ) term.setTextColour(colors.red)
end end
print( ... ) print(...)
if term.isColour() then if term.isColour() then
term.setTextColour( oldColour ) term.setTextColour(oldColour)
end end
end end
function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault ) function read(_sReplaceChar, _tHistory, _fnComplete, _sDefault)
expect(1, _sReplaceChar, "string", "nil") expect(1, _sReplaceChar, "string", "nil")
expect(2, _tHistory, "table", "nil") expect(2, _tHistory, "table", "nil")
expect(3, _fnComplete, "function", "nil") expect(3, _fnComplete, "function", "nil")
expect(4, _sDefault, "string", "nil") expect(4, _sDefault, "string", "nil")
term.setCursorBlink( true ) term.setCursorBlink(true)
local sLine local sLine
if type( _sDefault ) == "string" then if type(_sDefault) == "string" then
sLine = _sDefault sLine = _sDefault
else else
sLine = "" sLine = ""
@ -228,14 +228,14 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
local nHistoryPos local nHistoryPos
local nPos, nScroll = #sLine, 0 local nPos, nScroll = #sLine, 0
if _sReplaceChar then if _sReplaceChar then
_sReplaceChar = string.sub( _sReplaceChar, 1, 1 ) _sReplaceChar = string.sub(_sReplaceChar, 1, 1)
end end
local tCompletions local tCompletions
local nCompletion local nCompletion
local function recomplete() local function recomplete()
if _fnComplete and nPos == #sLine then if _fnComplete and nPos == #sLine then
tCompletions = _fnComplete( sLine ) tCompletions = _fnComplete(sLine)
if tCompletions and #tCompletions > 0 then if tCompletions and #tCompletions > 0 then
nCompletion = 1 nCompletion = 1
else else
@ -255,7 +255,7 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
local w = term.getSize() local w = term.getSize()
local sx = term.getCursorPos() local sx = term.getCursorPos()
local function redraw( _bClear ) local function redraw(_bClear)
local cursor_pos = nPos - nScroll local cursor_pos = nPos - nScroll
if sx + cursor_pos >= w then if sx + cursor_pos >= w then
-- We've moved beyond the RHS, ensure we're on the edge. -- We've moved beyond the RHS, ensure we're on the edge.
@ -266,39 +266,39 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
end end
local _, cy = term.getCursorPos() local _, cy = term.getCursorPos()
term.setCursorPos( sx, cy ) term.setCursorPos(sx, cy)
local sReplace = _bClear and " " or _sReplaceChar local sReplace = _bClear and " " or _sReplaceChar
if sReplace then if sReplace then
term.write( string.rep( sReplace, math.max( #sLine - nScroll, 0 ) ) ) term.write(string.rep(sReplace, math.max(#sLine - nScroll, 0)))
else else
term.write( string.sub( sLine, nScroll + 1 ) ) term.write(string.sub(sLine, nScroll + 1))
end end
if nCompletion then if nCompletion then
local sCompletion = tCompletions[ nCompletion ] local sCompletion = tCompletions[nCompletion]
local oldText, oldBg local oldText, oldBg
if not _bClear then if not _bClear then
oldText = term.getTextColor() oldText = term.getTextColor()
oldBg = term.getBackgroundColor() oldBg = term.getBackgroundColor()
term.setTextColor( colors.white ) term.setTextColor(colors.white)
term.setBackgroundColor( colors.gray ) term.setBackgroundColor(colors.gray)
end end
if sReplace then if sReplace then
term.write( string.rep( sReplace, #sCompletion ) ) term.write(string.rep(sReplace, #sCompletion))
else else
term.write( sCompletion ) term.write(sCompletion)
end end
if not _bClear then if not _bClear then
term.setTextColor( oldText ) term.setTextColor(oldText)
term.setBackgroundColor( oldBg ) term.setBackgroundColor(oldBg)
end end
end end
term.setCursorPos( sx + nPos - nScroll, cy ) term.setCursorPos(sx + nPos - nScroll, cy)
end end
local function clear() local function clear()
redraw( true ) redraw(true)
end end
recomplete() recomplete()
@ -310,7 +310,7 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
clear() clear()
-- Find the common prefix of all the other suggestions which start with the same letter as the current one -- Find the common prefix of all the other suggestions which start with the same letter as the current one
local sCompletion = tCompletions[ nCompletion ] local sCompletion = tCompletions[nCompletion]
sLine = sLine .. sCompletion sLine = sLine .. sCompletion
nPos = #sLine nPos = #sLine
@ -324,7 +324,7 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
if sEvent == "char" then if sEvent == "char" then
-- Typed key -- Typed key
clear() clear()
sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 ) sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
nPos = nPos + 1 nPos = nPos + 1
recomplete() recomplete()
redraw() redraw()
@ -332,7 +332,7 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
elseif sEvent == "paste" then elseif sEvent == "paste" then
-- Pasted text -- Pasted text
clear() clear()
sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 ) sLine = string.sub(sLine, 1, nPos) .. param .. string.sub(sLine, nPos + 1)
nPos = nPos + #param nPos = nPos + #param
recomplete() recomplete()
redraw() redraw()
@ -423,7 +423,7 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
-- Backspace -- Backspace
if nPos > 0 then if nPos > 0 then
clear() clear()
sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 ) sLine = string.sub(sLine, 1, nPos - 1) .. string.sub(sLine, nPos + 1)
nPos = nPos - 1 nPos = nPos - 1
if nScroll > 0 then nScroll = nScroll - 1 end if nScroll > 0 then nScroll = nScroll - 1 end
recomplete() recomplete()
@ -443,7 +443,7 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
-- Delete -- Delete
if nPos < #sLine then if nPos < #sLine then
clear() clear()
sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 ) sLine = string.sub(sLine, 1, nPos) .. string.sub(sLine, nPos + 2)
recomplete() recomplete()
redraw() redraw()
end end
@ -480,14 +480,14 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
end end
local _, cy = term.getCursorPos() local _, cy = term.getCursorPos()
term.setCursorBlink( false ) term.setCursorBlink(false)
term.setCursorPos( w + 1, cy ) term.setCursorPos(w + 1, cy)
print() print()
return sLine return sLine
end end
function loadfile( filename, mode, env ) function loadfile(filename, mode, env)
-- Support the previous `loadfile(filename, env)` form instead. -- Support the previous `loadfile(filename, env)` form instead.
if type(mode) == "table" and env == nil then if type(mode) == "table" and env == nil then
mode, env = nil, mode mode, env = nil, mode
@ -497,81 +497,81 @@ function loadfile( filename, mode, env )
expect(2, mode, "string", "nil") expect(2, mode, "string", "nil")
expect(3, env, "table", "nil") expect(3, env, "table", "nil")
local file = fs.open( filename, "r" ) local file = fs.open(filename, "r")
if not file then return nil, "File not found" end if not file then return nil, "File not found" end
local func, err = load( file.readAll(), "@" .. fs.getName( filename ), mode, env ) local func, err = load(file.readAll(), "@" .. fs.getName(filename), mode, env)
file.close() file.close()
return func, err return func, err
end end
function dofile( _sFile ) function dofile(_sFile)
expect(1, _sFile, "string") expect(1, _sFile, "string")
local fnFile, e = loadfile( _sFile, nil, _G ) local fnFile, e = loadfile(_sFile, nil, _G)
if fnFile then if fnFile then
return fnFile() return fnFile()
else else
error( e, 2 ) error(e, 2)
end end
end end
-- Install the rest of the OS api -- Install the rest of the OS api
function os.run( _tEnv, _sPath, ... ) function os.run(_tEnv, _sPath, ...)
expect(1, _tEnv, "table") expect(1, _tEnv, "table")
expect(2, _sPath, "string") expect(2, _sPath, "string")
local tArgs = table.pack( ... ) local tArgs = table.pack(...)
local tEnv = _tEnv local tEnv = _tEnv
setmetatable( tEnv, { __index = _G } ) setmetatable(tEnv, { __index = _G })
local fnFile, err = loadfile( _sPath, nil, tEnv ) local fnFile, err = loadfile(_sPath, nil, tEnv)
if fnFile then if fnFile then
local ok, err = pcall( function() local ok, err = pcall(function()
fnFile( table.unpack( tArgs, 1, tArgs.n ) ) fnFile(table.unpack(tArgs, 1, tArgs.n))
end ) end)
if not ok then if not ok then
if err and err ~= "" then if err and err ~= "" then
printError( err ) printError(err)
end end
return false return false
end end
return true return true
end end
if err and err ~= "" then if err and err ~= "" then
printError( err ) printError(err)
end end
return false return false
end end
local tAPIsLoading = {} local tAPIsLoading = {}
function os.loadAPI( _sPath ) function os.loadAPI(_sPath)
expect(1, _sPath, "string") expect(1, _sPath, "string")
local sName = fs.getName( _sPath ) local sName = fs.getName(_sPath)
if sName:sub(-4) == ".lua" then if sName:sub(-4) == ".lua" then
sName = sName:sub(1, -5) sName = sName:sub(1, -5)
end end
if tAPIsLoading[sName] == true then if tAPIsLoading[sName] == true then
printError( "API " .. sName .. " is already being loaded" ) printError("API " .. sName .. " is already being loaded")
return false return false
end end
tAPIsLoading[sName] = true tAPIsLoading[sName] = true
local tEnv = {} local tEnv = {}
setmetatable( tEnv, { __index = _G } ) setmetatable(tEnv, { __index = _G })
local fnAPI, err = loadfile( _sPath, nil, tEnv ) local fnAPI, err = loadfile(_sPath, nil, tEnv)
if fnAPI then if fnAPI then
local ok, err = pcall( fnAPI ) local ok, err = pcall(fnAPI)
if not ok then if not ok then
tAPIsLoading[sName] = nil tAPIsLoading[sName] = nil
return error( "Failed to load API " .. sName .. " due to " .. err, 1 ) return error("Failed to load API " .. sName .. " due to " .. err, 1)
end end
else else
tAPIsLoading[sName] = nil tAPIsLoading[sName] = nil
return error( "Failed to load API " .. sName .. " due to " .. err, 1 ) return error("Failed to load API " .. sName .. " due to " .. err, 1)
end end
local tAPI = {} local tAPI = {}
for k, v in pairs( tEnv ) do for k, v in pairs(tEnv) do
if k ~= "_ENV" then if k ~= "_ENV" then
tAPI[k] = v tAPI[k] = v
end end
@ -582,15 +582,15 @@ function os.loadAPI( _sPath )
return true return true
end end
function os.unloadAPI( _sName ) function os.unloadAPI(_sName)
expect(1, _sName, "string") expect(1, _sName, "string")
if _sName ~= "_G" and type(_G[_sName]) == "table" then if _sName ~= "_G" and type(_G[_sName]) == "table" then
_G[_sName] = nil _G[_sName] = nil
end end
end end
function os.sleep( nTime ) function os.sleep(nTime)
sleep( nTime ) sleep(nTime)
end end
local nativeShutdown = os.shutdown local nativeShutdown = os.shutdown
@ -619,7 +619,7 @@ if http then
PATCH = true, TRACE = true, PATCH = true, TRACE = true,
} }
local function checkKey( options, key, ty, opt ) local function checkKey(options, key, ty, opt)
local value = options[key] local value = options[key]
local valueTy = type(value) local valueTy = type(value)
@ -628,24 +628,24 @@ if http then
end end
end end
local function checkOptions( options, body ) local function checkOptions(options, body)
checkKey( options, "url", "string" ) checkKey(options, "url", "string")
if body == false then if body == false then
checkKey( options, "body", "nil" ) checkKey(options, "body", "nil")
else else
checkKey( options, "body", "string", not body ) checkKey(options, "body", "string", not body)
end end
checkKey( options, "headers", "table", true ) checkKey(options, "headers", "table", true)
checkKey( options, "method", "string", true ) checkKey(options, "method", "string", true)
checkKey( options, "redirect", "boolean", true ) checkKey(options, "redirect", "boolean", true)
if options.method and not methods[options.method] then if options.method and not methods[options.method] then
error( "Unsupported HTTP method", 3 ) error("Unsupported HTTP method", 3)
end end
end end
local function wrapRequest( _url, ... ) local function wrapRequest(_url, ...)
local ok, err = nativeHTTPRequest( ... ) local ok, err = nativeHTTPRequest(...)
if ok then if ok then
while true do while true do
local event, param1, param2, param3 = os.pullEvent() local event, param1, param2, param3 = os.pullEvent()
@ -660,34 +660,34 @@ if http then
end end
http.get = function(_url, _headers, _binary) http.get = function(_url, _headers, _binary)
if type( _url ) == "table" then if type(_url) == "table" then
checkOptions( _url, false ) checkOptions(_url, false)
return wrapRequest( _url.url, _url ) return wrapRequest(_url.url, _url)
end end
expect(1, _url, "string") expect(1, _url, "string")
expect(2, _headers, "table", "nil") expect(2, _headers, "table", "nil")
expect(3, _binary, "boolean", "nil") expect(3, _binary, "boolean", "nil")
return wrapRequest( _url, _url, nil, _headers, _binary ) return wrapRequest(_url, _url, nil, _headers, _binary)
end end
http.post = function(_url, _post, _headers, _binary) http.post = function(_url, _post, _headers, _binary)
if type( _url ) == "table" then if type(_url) == "table" then
checkOptions( _url, true ) checkOptions(_url, true)
return wrapRequest( _url.url, _url ) return wrapRequest(_url.url, _url)
end end
expect(1, _url, "string") expect(1, _url, "string")
expect(2, _post, "string") expect(2, _post, "string")
expect(3, _headers, "table", "nil") expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil") expect(4, _binary, "boolean", "nil")
return wrapRequest( _url, _url, _post, _headers, _binary ) return wrapRequest(_url, _url, _post, _headers, _binary)
end end
http.request = function( _url, _post, _headers, _binary ) http.request = function(_url, _post, _headers, _binary)
local url local url
if type( _url ) == "table" then if type(_url) == "table" then
checkOptions( _url ) checkOptions(_url)
url = _url.url url = _url.url
else else
expect(1, _url, "string") expect(1, _url, "string")
@ -697,32 +697,32 @@ if http then
url = _url.url url = _url.url
end end
local ok, err = nativeHTTPRequest( _url, _post, _headers, _binary ) local ok, err = nativeHTTPRequest(_url, _post, _headers, _binary)
if not ok then if not ok then
os.queueEvent( "http_failure", url, err ) os.queueEvent("http_failure", url, err)
end end
return ok, err return ok, err
end end
local nativeCheckURL = http.checkURL local nativeCheckURL = http.checkURL
http.checkURLAsync = nativeCheckURL http.checkURLAsync = nativeCheckURL
http.checkURL = function( _url ) http.checkURL = function(_url)
local ok, err = nativeCheckURL( _url ) local ok, err = nativeCheckURL(_url)
if not ok then return ok, err end if not ok then return ok, err end
while true do while true do
local _, url, ok, err = os.pullEvent( "http_check" ) local _, url, ok, err = os.pullEvent("http_check")
if url == _url then return ok, err end if url == _url then return ok, err end
end end
end end
local nativeWebsocket = http.websocket local nativeWebsocket = http.websocket
http.websocketAsync = nativeWebsocket http.websocketAsync = nativeWebsocket
http.websocket = function( _url, _headers ) http.websocket = function(_url, _headers)
expect(1, _url, "string") expect(1, _url, "string")
expect(2, _headers, "table", "nil") expect(2, _headers, "table", "nil")
local ok, err = nativeWebsocket( _url, _headers ) local ok, err = nativeWebsocket(_url, _headers)
if not ok then return ok, err end if not ok then return ok, err end
while true do while true do
@ -738,7 +738,7 @@ end
-- Install the lua part of the FS api -- Install the lua part of the FS api
local tEmpty = {} local tEmpty = {}
function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs ) function fs.complete(sPath, sLocation, bIncludeFiles, bIncludeDirs)
expect(1, sPath, "string") expect(1, sPath, "string")
expect(2, sLocation, "string") expect(2, sLocation, "string")
expect(3, bIncludeFiles, "boolean", "nil") expect(3, bIncludeFiles, "boolean", "nil")
@ -748,49 +748,49 @@ function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs )
bIncludeDirs = bIncludeDirs ~= false bIncludeDirs = bIncludeDirs ~= false
local sDir = sLocation local sDir = sLocation
local nStart = 1 local nStart = 1
local nSlash = string.find( sPath, "[/\\]", nStart ) local nSlash = string.find(sPath, "[/\\]", nStart)
if nSlash == 1 then if nSlash == 1 then
sDir = "" sDir = ""
nStart = 2 nStart = 2
end end
local sName local sName
while not sName do while not sName do
local nSlash = string.find( sPath, "[/\\]", nStart ) local nSlash = string.find(sPath, "[/\\]", nStart)
if nSlash then if nSlash then
local sPart = string.sub( sPath, nStart, nSlash - 1 ) local sPart = string.sub(sPath, nStart, nSlash - 1)
sDir = fs.combine( sDir, sPart ) sDir = fs.combine(sDir, sPart)
nStart = nSlash + 1 nStart = nSlash + 1
else else
sName = string.sub( sPath, nStart ) sName = string.sub(sPath, nStart)
end end
end end
if fs.isDir( sDir ) then if fs.isDir(sDir) then
local tResults = {} local tResults = {}
if bIncludeDirs and sPath == "" then if bIncludeDirs and sPath == "" then
table.insert( tResults, "." ) table.insert(tResults, ".")
end end
if sDir ~= "" then if sDir ~= "" then
if sPath == "" then if sPath == "" then
table.insert( tResults, bIncludeDirs and ".." or "../" ) table.insert(tResults, bIncludeDirs and ".." or "../")
elseif sPath == "." then elseif sPath == "." then
table.insert( tResults, bIncludeDirs and "." or "./" ) table.insert(tResults, bIncludeDirs and "." or "./")
end end
end end
local tFiles = fs.list( sDir ) local tFiles = fs.list(sDir)
for n = 1, #tFiles do for n = 1, #tFiles do
local sFile = tFiles[n] local sFile = tFiles[n]
if #sFile >= #sName and string.sub( sFile, 1, #sName ) == sName then if #sFile >= #sName and string.sub(sFile, 1, #sName) == sName then
local bIsDir = fs.isDir( fs.combine( sDir, sFile ) ) local bIsDir = fs.isDir(fs.combine(sDir, sFile))
local sResult = string.sub( sFile, #sName + 1 ) local sResult = string.sub(sFile, #sName + 1)
if bIsDir then if bIsDir then
table.insert( tResults, sResult .. "/" ) table.insert(tResults, sResult .. "/")
if bIncludeDirs and #sResult > 0 then if bIncludeDirs and #sResult > 0 then
table.insert( tResults, sResult ) table.insert(tResults, sResult)
end end
else else
if bIncludeFiles and #sResult > 0 then if bIncludeFiles and #sResult > 0 then
table.insert( tResults, sResult ) table.insert(tResults, sResult)
end end
end end
end end
@ -802,26 +802,26 @@ end
-- Load APIs -- Load APIs
local bAPIError = false local bAPIError = false
local tApis = fs.list( "rom/apis" ) local tApis = fs.list("rom/apis")
for _, sFile in ipairs( tApis ) do for _, sFile in ipairs(tApis) do
if string.sub( sFile, 1, 1 ) ~= "." then if string.sub(sFile, 1, 1) ~= "." then
local sPath = fs.combine( "rom/apis", sFile ) local sPath = fs.combine("rom/apis", sFile)
if not fs.isDir( sPath ) then if not fs.isDir(sPath) then
if not os.loadAPI( sPath ) then if not os.loadAPI(sPath) then
bAPIError = true bAPIError = true
end end
end end
end end
end end
if turtle and fs.isDir( "rom/apis/turtle" ) then if turtle and fs.isDir("rom/apis/turtle") then
-- Load turtle APIs -- Load turtle APIs
local tApis = fs.list( "rom/apis/turtle" ) local tApis = fs.list("rom/apis/turtle")
for _, sFile in ipairs( tApis ) do for _, sFile in ipairs(tApis) do
if string.sub( sFile, 1, 1 ) ~= "." then if string.sub(sFile, 1, 1) ~= "." then
local sPath = fs.combine( "rom/apis/turtle", sFile ) local sPath = fs.combine("rom/apis/turtle", sFile)
if not fs.isDir( sPath ) then if not fs.isDir(sPath) then
if not os.loadAPI( sPath ) then if not os.loadAPI(sPath) then
bAPIError = true bAPIError = true
end end
end end
@ -829,14 +829,14 @@ if turtle and fs.isDir( "rom/apis/turtle" ) then
end end
end end
if pocket and fs.isDir( "rom/apis/pocket" ) then if pocket and fs.isDir("rom/apis/pocket") then
-- Load pocket APIs -- Load pocket APIs
local tApis = fs.list( "rom/apis/pocket" ) local tApis = fs.list("rom/apis/pocket")
for _, sFile in ipairs( tApis ) do for _, sFile in ipairs(tApis) do
if string.sub( sFile, 1, 1 ) ~= "." then if string.sub(sFile, 1, 1) ~= "." then
local sPath = fs.combine( "rom/apis/pocket", sFile ) local sPath = fs.combine("rom/apis/pocket", sFile)
if not fs.isDir( sPath ) then if not fs.isDir(sPath) then
if not os.loadAPI( sPath ) then if not os.loadAPI(sPath) then
bAPIError = true bAPIError = true
end end
end end
@ -844,18 +844,18 @@ if pocket and fs.isDir( "rom/apis/pocket" ) then
end end
end end
if commands and fs.isDir( "rom/apis/command" ) then if commands and fs.isDir("rom/apis/command") then
-- Load command APIs -- Load command APIs
if os.loadAPI( "rom/apis/command/commands.lua" ) then if os.loadAPI("rom/apis/command/commands.lua") then
-- Add a special case-insensitive metatable to the commands api -- Add a special case-insensitive metatable to the commands api
local tCaseInsensitiveMetatable = { local tCaseInsensitiveMetatable = {
__index = function( table, key ) __index = function(table, key)
local value = rawget( table, key ) local value = rawget(table, key)
if value ~= nil then if value ~= nil then
return value return value
end end
if type(key) == "string" then if type(key) == "string" then
local value = rawget( table, string.lower(key) ) local value = rawget(table, string.lower(key))
if value ~= nil then if value ~= nil then
return value return value
end end
@ -863,8 +863,8 @@ if commands and fs.isDir( "rom/apis/command" ) then
return nil return nil
end, end,
} }
setmetatable( commands, tCaseInsensitiveMetatable ) setmetatable(commands, tCaseInsensitiveMetatable)
setmetatable( commands.async, tCaseInsensitiveMetatable ) setmetatable(commands.async, tCaseInsensitiveMetatable)
-- Add global "exec" function -- Add global "exec" function
exec = commands.exec exec = commands.exec
@ -874,29 +874,29 @@ if commands and fs.isDir( "rom/apis/command" ) then
end end
if bAPIError then if bAPIError then
print( "Press any key to continue" ) print("Press any key to continue")
os.pullEvent( "key" ) os.pullEvent("key")
term.clear() term.clear()
term.setCursorPos( 1, 1 ) term.setCursorPos(1, 1)
end end
-- Set default settings -- Set default settings
settings.set( "shell.allow_startup", true ) settings.set("shell.allow_startup", true)
settings.set( "shell.allow_disk_startup", commands == nil ) settings.set("shell.allow_disk_startup", commands == nil)
settings.set( "shell.autocomplete", true ) settings.set("shell.autocomplete", true)
settings.set( "edit.autocomplete", true ) settings.set("edit.autocomplete", true)
settings.set( "edit.default_extension", "lua" ) settings.set("edit.default_extension", "lua")
settings.set( "paint.default_extension", "nfp" ) settings.set("paint.default_extension", "nfp")
settings.set( "lua.autocomplete", true ) settings.set("lua.autocomplete", true)
settings.set( "list.show_hidden", false ) settings.set("list.show_hidden", false)
settings.set( "motd.enable", false ) settings.set("motd.enable", false)
settings.set( "motd.path", "/rom/motd.txt:/motd.txt" ) settings.set("motd.path", "/rom/motd.txt:/motd.txt")
if term.isColour() then if term.isColour() then
settings.set( "bios.use_multishell", true ) settings.set("bios.use_multishell", true)
end end
if _CC_DEFAULT_SETTINGS then if _CC_DEFAULT_SETTINGS then
for sPair in string.gmatch( _CC_DEFAULT_SETTINGS, "[^,]+" ) do for sPair in string.gmatch(_CC_DEFAULT_SETTINGS, "[^,]+") do
local sName, sValue = string.match( sPair, "([^=]*)=(.*)" ) local sName, sValue = string.match(sPair, "([^=]*)=(.*)")
if sName and sValue then if sName and sValue then
local value local value
if sValue == "true" then if sValue == "true" then
@ -911,43 +911,43 @@ if _CC_DEFAULT_SETTINGS then
value = sValue value = sValue
end end
if value ~= nil then if value ~= nil then
settings.set( sName, value ) settings.set(sName, value)
else else
settings.unset( sName ) settings.unset(sName)
end end
end end
end end
end end
-- Load user settings -- Load user settings
if fs.exists( ".settings" ) then if fs.exists(".settings") then
settings.load( ".settings" ) settings.load(".settings")
end end
-- Run the shell -- Run the shell
local ok, err = pcall(parallel.waitForAny, local ok, err = pcall(parallel.waitForAny,
function() function()
local sShell local sShell
if term.isColour() and settings.get( "bios.use_multishell" ) then if term.isColour() and settings.get("bios.use_multishell") then
sShell = "rom/programs/advanced/multishell.lua" sShell = "rom/programs/advanced/multishell.lua"
else else
sShell = "rom/programs/shell.lua" sShell = "rom/programs/shell.lua"
end end
os.run( {}, sShell ) os.run({}, sShell)
os.run( {}, "rom/programs/shutdown.lua" ) os.run({}, "rom/programs/shutdown.lua")
end, end,
rednet.run rednet.run
) )
-- If the shell errored, let the user read it. -- If the shell errored, let the user read it.
term.redirect( term.native() ) term.redirect(term.native())
if not ok then if not ok then
printError( err ) printError(err)
pcall( function() pcall(function()
term.setCursorBlink( false ) term.setCursorBlink(false)
print( "Press any key to continue" ) print("Press any key to continue")
os.pullEvent( "key" ) os.pullEvent("key")
end ) end)
end end
-- End -- End

View File

@ -86,7 +86,7 @@ black = 0x8000
-- colors.combine(colors.white, colors.magenta, colours.lightBlue) -- colors.combine(colors.white, colors.magenta, colours.lightBlue)
-- -- => 13 -- -- => 13
-- ``` -- ```
function combine( ... ) function combine(...)
local r = 0 local r = 0
for i = 1, select('#', ...) do for i = 1, select('#', ...) do
local c = select(i, ...) local c = select(i, ...)
@ -110,7 +110,7 @@ end
-- colours.subtract(colours.lime, colours.orange, colours.white) -- colours.subtract(colours.lime, colours.orange, colours.white)
-- -- => 32 -- -- => 32
-- ``` -- ```
function subtract( colors, ... ) function subtract(colors, ...)
expect(1, colors, "number") expect(1, colors, "number")
local r = colors local r = colors
for i = 1, select('#', ...) do for i = 1, select('#', ...) do
@ -131,7 +131,7 @@ end
-- colors.test(colors.combine(colors.white, colors.magenta, colours.lightBlue), colors.lightBlue) -- colors.test(colors.combine(colors.white, colors.magenta, colours.lightBlue), colors.lightBlue)
-- -- => true -- -- => true
-- ``` -- ```
function test( colors, color ) function test(colors, color)
expect(1, colors, "number") expect(1, colors, "number")
expect(2, color, "number") expect(2, color, "number")
return bit32.band(colors, color) == color return bit32.band(colors, color) == color
@ -148,14 +148,14 @@ end
-- colors.rgb(0.7, 0.2, 0.6) -- colors.rgb(0.7, 0.2, 0.6)
-- -- => 0xb23399 -- -- => 0xb23399
-- ``` -- ```
function packRGB( r, g, b ) function packRGB(r, g, b)
expect(1, r, "number") expect(1, r, "number")
expect(2, g, "number") expect(2, g, "number")
expect(3, b, "number") expect(3, b, "number")
return return
bit32.band( r * 255, 0xFF ) * 2 ^ 16 + bit32.band(r * 255, 0xFF) * 2 ^ 16 +
bit32.band( g * 255, 0xFF ) * 2 ^ 8 + bit32.band(g * 255, 0xFF) * 2 ^ 8 +
bit32.band( b * 255, 0xFF ) bit32.band(b * 255, 0xFF)
end end
--- Separate a hexadecimal RGB colour into its three constituent channels. --- Separate a hexadecimal RGB colour into its three constituent channels.
@ -170,12 +170,12 @@ end
-- -- => 0.7, 0.2, 0.6 -- -- => 0.7, 0.2, 0.6
-- ``` -- ```
-- @see colors.packRGB -- @see colors.packRGB
function unpackRGB( rgb ) function unpackRGB(rgb)
expect(1, rgb, "number") expect(1, rgb, "number")
return return
bit32.band( bit32.rshift( rgb, 16 ), 0xFF ) / 255, bit32.band(bit32.rshift(rgb, 16), 0xFF) / 255,
bit32.band( bit32.rshift( rgb, 8 ), 0xFF ) / 255, bit32.band(bit32.rshift(rgb, 8), 0xFF) / 255,
bit32.band( rgb, 0xFF ) / 255 bit32.band(rgb, 0xFF) / 255
end end
--- Either calls @{colors.packRGB} or @{colors.unpackRGB}, depending on how many --- Either calls @{colors.packRGB} or @{colors.unpackRGB}, depending on how many
@ -202,10 +202,10 @@ end
-- colors.rgb(0.7, 0.2, 0.6) -- colors.rgb(0.7, 0.2, 0.6)
-- -- => 0xb23399 -- -- => 0xb23399
-- ``` -- ```
function rgb8( r, g, b ) function rgb8(r, g, b)
if g == nil and b == nil then if g == nil and b == nil then
return unpackRGB( r ) return unpackRGB(r)
else else
return packRGB( r, g, b ) return packRGB(r, g, b)
end end
end end

View File

@ -14,7 +14,7 @@
-- @module commands -- @module commands
if not commands then if not commands then
error( "Cannot load command API on normal computer", 2 ) error("Cannot load command API on normal computer", 2)
end end
--- The builtin commands API, without any generated command helper functions --- The builtin commands API, without any generated command helper functions
@ -23,16 +23,16 @@ end
-- overwritten by a command. -- overwritten by a command.
native = commands.native or commands native = commands.native or commands
local function collapseArgs( bJSONIsNBT, ... ) local function collapseArgs(bJSONIsNBT, ...)
local args = table.pack(...) local args = table.pack(...)
for i = 1, #args do for i = 1, #args do
local arg = args[i] local arg = args[i]
if type(arg) == "boolean" or type(arg) == "number" or type(arg) == "string" then if type(arg) == "boolean" or type(arg) == "number" or type(arg) == "string" then
args[i] = tostring(arg) args[i] = tostring(arg)
elseif type(arg) == "table" then elseif type(arg) == "table" then
args[i] = textutils.serialiseJSON( arg, bJSONIsNBT ) args[i] = textutils.serialiseJSON(arg, bJSONIsNBT)
else else
error( "Expected string, number, boolean or table", 3 ) error("Expected string, number, boolean or table", 3)
end end
end end
@ -41,27 +41,27 @@ end
-- Put native functions into the environment -- Put native functions into the environment
local env = _ENV local env = _ENV
for k, v in pairs( native ) do for k, v in pairs(native) do
env[k] = v env[k] = v
end end
-- Create wrapper functions for all the commands -- Create wrapper functions for all the commands
local tAsync = {} local tAsync = {}
local tNonNBTJSONCommands = { local tNonNBTJSONCommands = {
[ "tellraw" ] = true, ["tellraw"] = true,
[ "title" ] = true, ["title"] = true,
} }
local tCommands = native.list() local tCommands = native.list()
for _, sCommandName in ipairs(tCommands) do for _, sCommandName in ipairs(tCommands) do
if env[ sCommandName ] == nil then if env[sCommandName] == nil then
local bJSONIsNBT = tNonNBTJSONCommands[ sCommandName ] == nil local bJSONIsNBT = tNonNBTJSONCommands[sCommandName] == nil
env[ sCommandName ] = function( ... ) env[sCommandName] = function(...)
local sCommand = collapseArgs( bJSONIsNBT, sCommandName, ... ) local sCommand = collapseArgs(bJSONIsNBT, sCommandName, ...)
return native.exec( sCommand ) return native.exec(sCommand)
end end
tAsync[ sCommandName ] = function( ... ) tAsync[sCommandName] = function(...)
local sCommand = collapseArgs( bJSONIsNBT, sCommandName, ... ) local sCommand = collapseArgs(bJSONIsNBT, sCommandName, ...)
return native.execAsync( sCommand ) return native.execAsync(sCommand)
end end
end end
end end

View File

@ -11,11 +11,11 @@
-- --
-- @module disk -- @module disk
local function isDrive( name ) local function isDrive(name)
if type( name ) ~= "string" then if type(name) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( name ) .. ")", 3 ) error("bad argument #1 (expected string, got " .. type(name) .. ")", 3)
end end
return peripheral.getType( name ) == "drive" return peripheral.getType(name) == "drive"
end end
--- Checks whether any item at all is in the disk drive --- Checks whether any item at all is in the disk drive
@ -23,9 +23,9 @@ end
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @treturn boolean If something is in the disk drive. -- @treturn boolean If something is in the disk drive.
-- @usage disk.isPresent(false) -- @usage disk.isPresent(false)
function isPresent( name ) function isPresent(name)
if isDrive( name ) then if isDrive(name) then
return peripheral.call( name, "isDiskPresent" ) return peripheral.call(name, "isDiskPresent")
end end
return false return false
end end
@ -40,9 +40,9 @@ end
-- @treturn string|nil The name of the current media, or `nil` if the drive is -- @treturn string|nil The name of the current media, or `nil` if the drive is
-- not present or empty. -- not present or empty.
-- @see disk.setLabel -- @see disk.setLabel
function getLabel( name ) function getLabel(name)
if isDrive( name ) then if isDrive(name) then
return peripheral.call( name, "getDiskLabel" ) return peripheral.call(name, "getDiskLabel")
end end
return nil return nil
end end
@ -51,9 +51,9 @@ end
-- --
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @tparam string|nil label The new label of the disk -- @tparam string|nil label The new label of the disk
function setLabel( name, label ) function setLabel(name, label)
if isDrive( name ) then if isDrive(name) then
peripheral.call( name, "setDiskLabel", label ) peripheral.call(name, "setDiskLabel", label)
end end
end end
@ -64,9 +64,9 @@ end
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @treturn boolean If the disk is present and provides a mount. -- @treturn boolean If the disk is present and provides a mount.
-- @see disk.getMountPath -- @see disk.getMountPath
function hasData( name ) function hasData(name)
if isDrive( name ) then if isDrive(name) then
return peripheral.call( name, "hasData" ) return peripheral.call(name, "hasData")
end end
return false return false
end end
@ -78,9 +78,9 @@ end
-- @treturn string|nil The mount's directory, or `nil` if the drive does not -- @treturn string|nil The mount's directory, or `nil` if the drive does not
-- contain a floppy or computer. -- contain a floppy or computer.
-- @see disk.hasData -- @see disk.hasData
function getMountPath( name ) function getMountPath(name)
if isDrive( name ) then if isDrive(name) then
return peripheral.call( name, "getMountPath" ) return peripheral.call(name, "getMountPath")
end end
return nil return nil
end end
@ -94,9 +94,9 @@ end
-- --
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @treturn boolean If the disk is present and has audio saved on it. -- @treturn boolean If the disk is present and has audio saved on it.
function hasAudio( name ) function hasAudio(name)
if isDrive( name ) then if isDrive(name) then
return peripheral.call( name, "hasAudio" ) return peripheral.call(name, "hasAudio")
end end
return false return false
end end
@ -108,9 +108,9 @@ end
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @treturn string|false|nil The track title, `false` if there is not a music -- @treturn string|false|nil The track title, `false` if there is not a music
-- record in the drive or `nil` if no drive is present. -- record in the drive or `nil` if no drive is present.
function getAudioTitle( name ) function getAudioTitle(name)
if isDrive( name ) then if isDrive(name) then
return peripheral.call( name, "getAudioTitle" ) return peripheral.call(name, "getAudioTitle")
end end
return nil return nil
end end
@ -124,9 +124,9 @@ end
-- --
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @usage disk.playAudio("bottom") -- @usage disk.playAudio("bottom")
function playAudio( name ) function playAudio(name)
if isDrive( name ) then if isDrive(name) then
peripheral.call( name, "playAudio" ) peripheral.call(name, "playAudio")
end end
end end
@ -134,14 +134,14 @@ end
-- @{disk.playAudio}. -- @{disk.playAudio}.
-- --
-- @tparam string name The name o the disk drive. -- @tparam string name The name o the disk drive.
function stopAudio( name ) function stopAudio(name)
if not name then if not name then
for _, sName in ipairs( peripheral.getNames() ) do for _, sName in ipairs(peripheral.getNames()) do
stopAudio( sName ) stopAudio(sName)
end end
else else
if isDrive( name ) then if isDrive(name) then
peripheral.call( name, "stopAudio" ) peripheral.call(name, "stopAudio")
end end
end end
end end
@ -150,9 +150,9 @@ end
-- --
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @usage disk.eject("bottom") -- @usage disk.eject("bottom")
function eject( name ) function eject(name)
if isDrive( name ) then if isDrive(name) then
peripheral.call( name, "ejectDisk" ) peripheral.call(name, "ejectDisk")
end end
end end
@ -163,9 +163,9 @@ end
-- --
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @treturn string|nil The disk ID, or `nil` if the drive does not contain a floppy disk. -- @treturn string|nil The disk ID, or `nil` if the drive does not contain a floppy disk.
function getID( name ) function getID(name)
if isDrive( name ) then if isDrive(name) then
return peripheral.call( name, "getDiskID" ) return peripheral.call(name, "getDiskID")
end end
return nil return nil
end end

View File

@ -27,20 +27,20 @@ local expect = dofile("rom/modules/main/cc/expect.lua").expect
--- The channel which GPS requests and responses are broadcast on. --- The channel which GPS requests and responses are broadcast on.
CHANNEL_GPS = 65534 CHANNEL_GPS = 65534
local function trilaterate( A, B, C ) local function trilaterate(A, B, C)
local a2b = B.vPosition - A.vPosition local a2b = B.vPosition - A.vPosition
local a2c = C.vPosition - A.vPosition local a2c = C.vPosition - A.vPosition
if math.abs( a2b:normalize():dot( a2c:normalize() ) ) > 0.999 then if math.abs(a2b:normalize():dot(a2c:normalize())) > 0.999 then
return nil return nil
end end
local d = a2b:length() local d = a2b:length()
local ex = a2b:normalize( ) local ex = a2b:normalize( )
local i = ex:dot( a2c ) local i = ex:dot(a2c)
local ey = (a2c - ex * i):normalize() local ey = (a2c - ex * i):normalize()
local j = ey:dot( a2c ) local j = ey:dot(a2c)
local ez = ex:cross( ey ) local ez = ex:cross(ey)
local r1 = A.nDistance local r1 = A.nDistance
local r2 = B.nDistance local r2 = B.nDistance
@ -53,31 +53,31 @@ local function trilaterate( A, B, C )
local zSquared = r1 * r1 - x * x - y * y local zSquared = r1 * r1 - x * x - y * y
if zSquared > 0 then if zSquared > 0 then
local z = math.sqrt( zSquared ) local z = math.sqrt(zSquared)
local result1 = result + ez * z local result1 = result + ez * z
local result2 = result - ez * z local result2 = result - ez * z
local rounded1, rounded2 = result1:round( 0.01 ), result2:round( 0.01 ) local rounded1, rounded2 = result1:round(0.01), result2:round(0.01)
if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then
return rounded1, rounded2 return rounded1, rounded2
else else
return rounded1 return rounded1
end end
end end
return result:round( 0.01 ) return result:round(0.01)
end end
local function narrow( p1, p2, fix ) local function narrow(p1, p2, fix)
local dist1 = math.abs( (p1 - fix.vPosition):length() - fix.nDistance ) local dist1 = math.abs((p1 - fix.vPosition):length() - fix.nDistance)
local dist2 = math.abs( (p2 - fix.vPosition):length() - fix.nDistance ) local dist2 = math.abs((p2 - fix.vPosition):length() - fix.nDistance)
if math.abs(dist1 - dist2) < 0.01 then if math.abs(dist1 - dist2) < 0.01 then
return p1, p2 return p1, p2
elseif dist1 < dist2 then elseif dist1 < dist2 then
return p1:round( 0.01 ) return p1:round(0.01)
else else
return p2:round( 0.01 ) return p2:round(0.01)
end end
end end
@ -90,7 +90,7 @@ end
-- @treturn[1] number This computer's `y` position. -- @treturn[1] number This computer's `y` position.
-- @treturn[1] number This computer's `z` position. -- @treturn[1] number This computer's `z` position.
-- @treturn[2] nil If the position could not be established. -- @treturn[2] nil If the position could not be established.
function locate( _nTimeout, _bDebug ) function locate(_nTimeout, _bDebug)
expect(1, _nTimeout, "number", "nil") expect(1, _nTimeout, "number", "nil")
expect(2, _bDebug, "boolean", "nil") expect(2, _bDebug, "boolean", "nil")
-- Let command computers use their magic fourth-wall-breaking special abilities -- Let command computers use their magic fourth-wall-breaking special abilities
@ -100,8 +100,8 @@ function locate( _nTimeout, _bDebug )
-- Find a modem -- Find a modem
local sModemSide = nil local sModemSide = nil
for _, sSide in ipairs( rs.getSides() ) do for _, sSide in ipairs(rs.getSides()) do
if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then if peripheral.getType(sSide) == "modem" and peripheral.call(sSide, "isWireless") then
sModemSide = sSide sModemSide = sSide
break break
end end
@ -109,30 +109,30 @@ function locate( _nTimeout, _bDebug )
if sModemSide == nil then if sModemSide == nil then
if _bDebug then if _bDebug then
print( "No wireless modem attached" ) print("No wireless modem attached")
end end
return nil return nil
end end
if _bDebug then if _bDebug then
print( "Finding position..." ) print("Finding position...")
end end
-- Open GPS channel to listen for ping responses -- Open GPS channel to listen for ping responses
local modem = peripheral.wrap( sModemSide ) local modem = peripheral.wrap(sModemSide)
local bCloseChannel = false local bCloseChannel = false
if not modem.isOpen( CHANNEL_GPS ) then if not modem.isOpen(CHANNEL_GPS) then
modem.open( CHANNEL_GPS ) modem.open(CHANNEL_GPS)
bCloseChannel = true bCloseChannel = true
end end
-- Send a ping to listening GPS hosts -- Send a ping to listening GPS hosts
modem.transmit( CHANNEL_GPS, CHANNEL_GPS, "PING" ) modem.transmit(CHANNEL_GPS, CHANNEL_GPS, "PING")
-- Wait for the responses -- Wait for the responses
local tFixes = {} local tFixes = {}
local pos1, pos2 = nil, nil local pos1, pos2 = nil, nil
local timeout = os.startTimer( _nTimeout or 2 ) local timeout = os.startTimer(_nTimeout or 2)
while true do while true do
local e, p1, p2, p3, p4, p5 = os.pullEvent() local e, p1, p2, p3, p4, p5 = os.pullEvent()
if e == "modem_message" then if e == "modem_message" then
@ -141,19 +141,19 @@ function locate( _nTimeout, _bDebug )
if sSide == sModemSide and sChannel == CHANNEL_GPS and sReplyChannel == CHANNEL_GPS and nDistance then if sSide == sModemSide and sChannel == CHANNEL_GPS and sReplyChannel == CHANNEL_GPS and nDistance then
-- Received the correct message from the correct modem: use it to determine position -- Received the correct message from the correct modem: use it to determine position
if type(tMessage) == "table" and #tMessage == 3 and tonumber(tMessage[1]) and tonumber(tMessage[2]) and tonumber(tMessage[3]) then if type(tMessage) == "table" and #tMessage == 3 and tonumber(tMessage[1]) and tonumber(tMessage[2]) and tonumber(tMessage[3]) then
local tFix = { vPosition = vector.new( tMessage[1], tMessage[2], tMessage[3] ), nDistance = nDistance } local tFix = { vPosition = vector.new(tMessage[1], tMessage[2], tMessage[3]), nDistance = nDistance }
if _bDebug then if _bDebug then
print( tFix.nDistance .. " metres from " .. tostring( tFix.vPosition ) ) print(tFix.nDistance .. " metres from " .. tostring(tFix.vPosition))
end end
if tFix.nDistance == 0 then if tFix.nDistance == 0 then
pos1, pos2 = tFix.vPosition, nil pos1, pos2 = tFix.vPosition, nil
else else
table.insert( tFixes, tFix ) table.insert(tFixes, tFix)
if #tFixes >= 3 then if #tFixes >= 3 then
if not pos1 then if not pos1 then
pos1, pos2 = trilaterate( tFixes[1], tFixes[2], tFixes[#tFixes] ) pos1, pos2 = trilaterate(tFixes[1], tFixes[2], tFixes[#tFixes])
else else
pos1, pos2 = narrow( pos1, pos2, tFixes[#tFixes] ) pos1, pos2 = narrow(pos1, pos2, tFixes[#tFixes])
end end
end end
end end
@ -175,24 +175,24 @@ function locate( _nTimeout, _bDebug )
-- Close the channel, if we opened one -- Close the channel, if we opened one
if bCloseChannel then if bCloseChannel then
modem.close( CHANNEL_GPS ) modem.close(CHANNEL_GPS)
end end
-- Return the response -- Return the response
if pos1 and pos2 then if pos1 and pos2 then
if _bDebug then if _bDebug then
print( "Ambiguous position" ) print("Ambiguous position")
print( "Could be " .. pos1.x .. "," .. pos1.y .. "," .. pos1.z .. " or " .. pos2.x .. "," .. pos2.y .. "," .. pos2.z ) print("Could be " .. pos1.x .. "," .. pos1.y .. "," .. pos1.z .. " or " .. pos2.x .. "," .. pos2.y .. "," .. pos2.z)
end end
return nil return nil
elseif pos1 then elseif pos1 then
if _bDebug then if _bDebug then
print( "Position is " .. pos1.x .. "," .. pos1.y .. "," .. pos1.z ) print("Position is " .. pos1.x .. "," .. pos1.y .. "," .. pos1.z)
end end
return pos1.x, pos1.y, pos1.z return pos1.x, pos1.y, pos1.z
else else
if _bDebug then if _bDebug then
print( "Could not determine position" ) print("Could not determine position")
end end
return nil return nil
end end

View File

@ -22,7 +22,7 @@ end
-- @usage help.setPath( "/disk/help/" ) -- @usage help.setPath( "/disk/help/" )
-- @usage help.setPath( help.path() .. ":/myfolder/help/" ) -- @usage help.setPath( help.path() .. ":/myfolder/help/" )
-- @see help.path -- @see help.path
function setPath( _sPath ) function setPath(_sPath)
expect(1, _sPath, "string") expect(1, _sPath, "string")
sPath = _sPath sPath = _sPath
end end
@ -33,14 +33,14 @@ end
-- @treturn string|nil The path to the given topic's help file, or `nil` if it -- @treturn string|nil The path to the given topic's help file, or `nil` if it
-- cannot be found. -- cannot be found.
-- @usage print(help.lookup("disk")) -- @usage print(help.lookup("disk"))
function lookup( _sTopic ) function lookup(_sTopic)
expect(1, _sTopic, "string") expect(1, _sTopic, "string")
-- Look on the path variable -- Look on the path variable
for sPath in string.gmatch(sPath, "[^:]+") do for sPath in string.gmatch(sPath, "[^:]+") do
sPath = fs.combine( sPath, _sTopic ) sPath = fs.combine(sPath, _sTopic)
if fs.exists( sPath ) and not fs.isDir( sPath ) then if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath return sPath
elseif fs.exists( sPath .. ".txt" ) and not fs.isDir( sPath .. ".txt" ) then elseif fs.exists(sPath .. ".txt") and not fs.isDir(sPath .. ".txt") then
return sPath .. ".txt" return sPath .. ".txt"
end end
end end
@ -55,20 +55,20 @@ end
function topics() function topics()
-- Add index -- Add index
local tItems = { local tItems = {
[ "index" ] = true, ["index"] = true,
} }
-- Add topics from the path -- Add topics from the path
for sPath in string.gmatch(sPath, "[^:]+") do for sPath in string.gmatch(sPath, "[^:]+") do
if fs.isDir( sPath ) then if fs.isDir(sPath) then
local tList = fs.list( sPath ) local tList = fs.list(sPath)
for _, sFile in pairs( tList ) do for _, sFile in pairs(tList) do
if string.sub( sFile, 1, 1 ) ~= "." then if string.sub(sFile, 1, 1) ~= "." then
if not fs.isDir( fs.combine( sPath, sFile ) ) then if not fs.isDir(fs.combine(sPath, sFile)) then
if #sFile > 4 and sFile:sub(-4) == ".txt" then if #sFile > 4 and sFile:sub(-4) == ".txt" then
sFile = sFile:sub(1, -5) sFile = sFile:sub(1, -5)
end end
tItems[ sFile ] = true tItems[sFile] = true
end end
end end
end end
@ -77,10 +77,10 @@ function topics()
-- Sort and return -- Sort and return
local tItemList = {} local tItemList = {}
for sItem in pairs( tItems ) do for sItem in pairs(tItems) do
table.insert( tItemList, sItem ) table.insert(tItemList, sItem)
end end
table.sort( tItemList ) table.sort(tItemList)
return tItemList return tItemList
end end
@ -89,14 +89,14 @@ end
-- --
-- @tparam string prefix The prefix to match -- @tparam string prefix The prefix to match
-- @treturn table A list of matching topics. -- @treturn table A list of matching topics.
function completeTopic( sText ) function completeTopic(sText)
expect(1, sText, "string") expect(1, sText, "string")
local tTopics = topics() local tTopics = topics()
local tResults = {} local tResults = {}
for n = 1, #tTopics do for n = 1, #tTopics do
local sTopic = tTopics[n] local sTopic = tTopics[n]
if #sTopic > #sText and string.sub( sTopic, 1, #sText ) == sText then if #sTopic > #sText and string.sub(sTopic, 1, #sText) == sText then
table.insert( tResults, string.sub( sTopic, #sText + 1 ) ) table.insert(tResults, string.sub(sTopic, #sText + 1))
end end
end end
return tResults return tResults

View File

@ -57,7 +57,7 @@ local tKeys = {
} }
local keys = _ENV local keys = _ENV
for nKey, sKey in pairs( tKeys ) do for nKey, sKey in pairs(tKeys) do
keys[sKey] = nKey keys[sKey] = nKey
end end
@ -71,7 +71,7 @@ keys.cimcumflex = keys.circumflex --- @local
-- --
-- @tparam number code The key code to look up. -- @tparam number code The key code to look up.
-- @treturn string|nil The name of the key, or `nil` if not a valid key code. -- @treturn string|nil The name of the key, or `nil` if not a valid key code.
function getName( code ) function getName(code)
expect(1, code, "number") expect(1, code, "number")
return tKeys[ code ] return tKeys[code]
end end

View File

@ -5,22 +5,22 @@
local expect = dofile("rom/modules/main/cc/expect.lua").expect local expect = dofile("rom/modules/main/cc/expect.lua").expect
local function drawPixelInternal( xPos, yPos ) local function drawPixelInternal(xPos, yPos)
term.setCursorPos( xPos, yPos ) term.setCursorPos(xPos, yPos)
term.write(" ") term.write(" ")
end end
local tColourLookup = {} local tColourLookup = {}
for n = 1, 16 do for n = 1, 16 do
tColourLookup[ string.byte( "0123456789abcdef", n, n ) ] = 2 ^ (n - 1) tColourLookup[string.byte("0123456789abcdef", n, n)] = 2 ^ (n - 1)
end end
local function parseLine( tImageArg, sLine ) local function parseLine(tImageArg, sLine)
local tLine = {} local tLine = {}
for x = 1, sLine:len() do for x = 1, sLine:len() do
tLine[x] = tColourLookup[ string.byte(sLine, x, x) ] or 0 tLine[x] = tColourLookup[string.byte(sLine, x, x)] or 0
end end
table.insert( tImageArg, tLine ) table.insert(tImageArg, tLine)
end end
--- Parses an image from a multi-line string --- Parses an image from a multi-line string
@ -28,11 +28,11 @@ end
-- @tparam string image The string containing the raw-image data. -- @tparam string image The string containing the raw-image data.
-- @treturn table The parsed image data, suitable for use with -- @treturn table The parsed image data, suitable for use with
-- @{paintutils.drawImage}. -- @{paintutils.drawImage}.
function parseImage( image ) function parseImage(image)
expect(1, image, "string") expect(1, image, "string")
local tImage = {} local tImage = {}
for sLine in ( image .. "\n" ):gmatch( "(.-)\n" ) do for sLine in (image .. "\n"):gmatch("(.-)\n") do
parseLine( tImage, sLine ) parseLine(tImage, sLine)
end end
return tImage return tImage
end end
@ -45,14 +45,14 @@ end
-- --
-- @treturn table|nil The parsed image data, suitable for use with -- @treturn table|nil The parsed image data, suitable for use with
-- @{paintutils.drawImage}, or `nil` if the file does not exist. -- @{paintutils.drawImage}, or `nil` if the file does not exist.
function loadImage( path ) function loadImage(path)
expect(1, path, "string") expect(1, path, "string")
if fs.exists( path ) then if fs.exists(path) then
local file = io.open( path, "r" ) local file = io.open(path, "r")
local sContent = file:read("*a") local sContent = file:read("*a")
file:close() file:close()
return parseImage( sContent ) return parseImage(sContent)
end end
return nil return nil
end end
@ -66,18 +66,18 @@ end
-- @tparam number yPos The y position to draw at, where 1 is the very top. -- @tparam number yPos The y position to draw at, where 1 is the very top.
-- @tparam[opt] number colour The @{colors|color} of this pixel. This will be -- @tparam[opt] number colour The @{colors|color} of this pixel. This will be
-- the current background colour if not specified. -- the current background colour if not specified.
function drawPixel( xPos, yPos, colour ) function drawPixel(xPos, yPos, colour)
expect(1, xPos, "number") expect(1, xPos, "number")
expect(2, yPos, "number") expect(2, yPos, "number")
expect(3, colour, "number", "nil") expect(3, colour, "number", "nil")
if type( xPos ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( xPos ) .. ")", 2 ) end if type(xPos) ~= "number" then error("bad argument #1 (expected number, got " .. type(xPos) .. ")", 2) end
if type( yPos ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( yPos ) .. ")", 2 ) end if type(yPos) ~= "number" then error("bad argument #2 (expected number, got " .. type(yPos) .. ")", 2) end
if colour ~= nil and type( colour ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( colour ) .. ")", 2 ) end if colour ~= nil and type(colour) ~= "number" then error("bad argument #3 (expected number, got " .. type(colour) .. ")", 2) end
if colour then if colour then
term.setBackgroundColor( colour ) term.setBackgroundColor(colour)
end end
return drawPixelInternal( xPos, yPos ) return drawPixelInternal(xPos, yPos)
end end
--- Draws a straight line from the start to end position. --- Draws a straight line from the start to end position.
@ -91,7 +91,7 @@ end
-- @tparam number endY The end y position of the line. -- @tparam number endY The end y position of the line.
-- @tparam[opt] number colour The @{colors|color} of this pixel. This will be -- @tparam[opt] number colour The @{colors|color} of this pixel. This will be
-- the current background colour if not specified. -- the current background colour if not specified.
function drawLine( startX, startY, endX, endY, colour ) function drawLine(startX, startY, endX, endY, colour)
expect(1, startX, "number") expect(1, startX, "number")
expect(2, startY, "number") expect(2, startY, "number")
expect(3, endX, "number") expect(3, endX, "number")
@ -104,14 +104,14 @@ function drawLine( startX, startY, endX, endY, colour )
endY = math.floor(endY) endY = math.floor(endY)
if colour then if colour then
term.setBackgroundColor( colour ) term.setBackgroundColor(colour)
end end
if startX == endX and startY == endY then if startX == endX and startY == endY then
drawPixelInternal( startX, startY ) drawPixelInternal(startX, startY)
return return
end end
local minX = math.min( startX, endX ) local minX = math.min(startX, endX)
local maxX, minY, maxY local maxX, minY, maxY
if minX == startX then if minX == startX then
minY = startY minY = startY
@ -132,7 +132,7 @@ function drawLine( startX, startY, endX, endY, colour )
local y = minY local y = minY
local dy = yDiff / xDiff local dy = yDiff / xDiff
for x = minX, maxX do for x = minX, maxX do
drawPixelInternal( x, math.floor( y + 0.5 ) ) drawPixelInternal(x, math.floor(y + 0.5))
y = y + dy y = y + dy
end end
else else
@ -140,12 +140,12 @@ function drawLine( startX, startY, endX, endY, colour )
local dx = xDiff / yDiff local dx = xDiff / yDiff
if maxY >= minY then if maxY >= minY then
for y = minY, maxY do for y = minY, maxY do
drawPixelInternal( math.floor( x + 0.5 ), y ) drawPixelInternal(math.floor(x + 0.5), y)
x = x + dx x = x + dx
end end
else else
for y = minY, maxY, -1 do for y = minY, maxY, -1 do
drawPixelInternal( math.floor( x + 0.5 ), y ) drawPixelInternal(math.floor(x + 0.5), y)
x = x - dx x = x - dx
end end
end end
@ -164,7 +164,7 @@ end
-- @tparam number endY The end y position of the line. -- @tparam number endY The end y position of the line.
-- @tparam[opt] number colour The @{colors|color} of this pixel. This will be -- @tparam[opt] number colour The @{colors|color} of this pixel. This will be
-- the current background colour if not specified. -- the current background colour if not specified.
function drawBox( startX, startY, endX, endY, nColour ) function drawBox(startX, startY, endX, endY, nColour)
expect(1, startX, "number") expect(1, startX, "number")
expect(2, startY, "number") expect(2, startY, "number")
expect(3, endX, "number") expect(3, endX, "number")
@ -177,14 +177,14 @@ function drawBox( startX, startY, endX, endY, nColour )
endY = math.floor(endY) endY = math.floor(endY)
if nColour then if nColour then
term.setBackgroundColor( nColour ) term.setBackgroundColor(nColour)
end end
if startX == endX and startY == endY then if startX == endX and startY == endY then
drawPixelInternal( startX, startY ) drawPixelInternal(startX, startY)
return return
end end
local minX = math.min( startX, endX ) local minX = math.min(startX, endX)
local maxX, minY, maxY local maxX, minY, maxY
if minX == startX then if minX == startX then
minY = startY minY = startY
@ -197,14 +197,14 @@ function drawBox( startX, startY, endX, endY, nColour )
end end
for x = minX, maxX do for x = minX, maxX do
drawPixelInternal( x, minY ) drawPixelInternal(x, minY)
drawPixelInternal( x, maxY ) drawPixelInternal(x, maxY)
end end
if maxY - minY >= 2 then if maxY - minY >= 2 then
for y = minY + 1, maxY - 1 do for y = minY + 1, maxY - 1 do
drawPixelInternal( minX, y ) drawPixelInternal(minX, y)
drawPixelInternal( maxX, y ) drawPixelInternal(maxX, y)
end end
end end
end end
@ -220,7 +220,7 @@ end
-- @tparam number endY The end y position of the line. -- @tparam number endY The end y position of the line.
-- @tparam[opt] number colour The @{colors|color} of this pixel. This will be -- @tparam[opt] number colour The @{colors|color} of this pixel. This will be
-- the current background colour if not specified. -- the current background colour if not specified.
function drawFilledBox( startX, startY, endX, endY, nColour ) function drawFilledBox(startX, startY, endX, endY, nColour)
expect(1, startX, "number") expect(1, startX, "number")
expect(2, startY, "number") expect(2, startY, "number")
expect(3, endX, "number") expect(3, endX, "number")
@ -233,14 +233,14 @@ function drawFilledBox( startX, startY, endX, endY, nColour )
endY = math.floor(endY) endY = math.floor(endY)
if nColour then if nColour then
term.setBackgroundColor( nColour ) term.setBackgroundColor(nColour)
end end
if startX == endX and startY == endY then if startX == endX and startY == endY then
drawPixelInternal( startX, startY ) drawPixelInternal(startX, startY)
return return
end end
local minX = math.min( startX, endX ) local minX = math.min(startX, endX)
local maxX, minY, maxY local maxX, minY, maxY
if minX == startX then if minX == startX then
minY = startY minY = startY
@ -254,7 +254,7 @@ function drawFilledBox( startX, startY, endX, endY, nColour )
for x = minX, maxX do for x = minX, maxX do
for y = minY, maxY do for y = minY, maxY do
drawPixelInternal( x, y ) drawPixelInternal(x, y)
end end
end end
end end
@ -264,7 +264,7 @@ end
-- @tparam table image The parsed image data. -- @tparam table image The parsed image data.
-- @tparam number xPos The x position to start drawing at. -- @tparam number xPos The x position to start drawing at.
-- @tparam number xPos The y position to start drawing at. -- @tparam number xPos The y position to start drawing at.
function drawImage( image, xPos, yPos ) function drawImage(image, xPos, yPos)
expect(1, image, "table") expect(1, image, "table")
expect(2, xPos, "number") expect(2, xPos, "number")
expect(3, yPos, "number") expect(3, yPos, "number")
@ -272,8 +272,8 @@ function drawImage( image, xPos, yPos )
local tLine = image[y] local tLine = image[y]
for x = 1, #tLine do for x = 1, #tLine do
if tLine[x] > 0 then if tLine[x] > 0 then
term.setBackgroundColor( tLine[x] ) term.setBackgroundColor(tLine[x])
drawPixelInternal( x + xPos - 1, y + yPos - 1 ) drawPixelInternal(x + xPos - 1, y + yPos - 1)
end end
end end
end end

View File

@ -14,13 +14,13 @@
-- --
-- @module parallel -- @module parallel
local function create( ... ) local function create(...)
local tFns = table.pack(...) local tFns = table.pack(...)
local tCos = {} local tCos = {}
for i = 1, tFns.n, 1 do for i = 1, tFns.n, 1 do
local fn = tFns[i] local fn = tFns[i]
if type( fn ) ~= "function" then if type(fn) ~= "function" then
error( "bad argument #" .. i .. " (expected function, got " .. type( fn ) .. ")", 3 ) error("bad argument #" .. i .. " (expected function, got " .. type(fn) .. ")", 3)
end end
tCos[i] = coroutine.create(fn) tCos[i] = coroutine.create(fn)
@ -29,7 +29,7 @@ local function create( ... )
return tCos return tCos
end end
local function runUntilLimit( _routines, _limit ) local function runUntilLimit(_routines, _limit)
local count = #_routines local count = #_routines
local living = count local living = count
@ -40,13 +40,13 @@ local function runUntilLimit( _routines, _limit )
local r = _routines[n] local r = _routines[n]
if r then if r then
if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == "terminate" then if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == "terminate" then
local ok, param = coroutine.resume( r, table.unpack( eventData, 1, eventData.n ) ) local ok, param = coroutine.resume(r, table.unpack(eventData, 1, eventData.n))
if not ok then if not ok then
error( param, 0 ) error(param, 0)
else else
tFilters[r] = param tFilters[r] = param
end end
if coroutine.status( r ) == "dead" then if coroutine.status(r) == "dead" then
_routines[n] = nil _routines[n] = nil
living = living - 1 living = living - 1
if living <= _limit then if living <= _limit then
@ -58,7 +58,7 @@ local function runUntilLimit( _routines, _limit )
end end
for n = 1, count do for n = 1, count do
local r = _routines[n] local r = _routines[n]
if r and coroutine.status( r ) == "dead" then if r and coroutine.status(r) == "dead" then
_routines[n] = nil _routines[n] = nil
living = living - 1 living = living - 1
if living <= _limit then if living <= _limit then
@ -66,7 +66,7 @@ local function runUntilLimit( _routines, _limit )
end end
end end
end end
eventData = table.pack( os.pullEventRaw() ) eventData = table.pack(os.pullEventRaw())
end end
end end
@ -75,9 +75,9 @@ end
-- from the @{parallel.waitForAny} call. -- from the @{parallel.waitForAny} call.
-- --
-- @tparam function ... The functions this task will run -- @tparam function ... The functions this task will run
function waitForAny( ... ) function waitForAny(...)
local routines = create( ... ) local routines = create(...)
return runUntilLimit( routines, #routines - 1 ) return runUntilLimit(routines, #routines - 1)
end end
--- Switches between execution of the functions, until all of them are --- Switches between execution of the functions, until all of them are
@ -85,7 +85,7 @@ end
-- from the @{parallel.waitForAll} call. -- from the @{parallel.waitForAll} call.
-- --
-- @tparam function ... The functions this task will run -- @tparam function ... The functions this task will run
function waitForAll( ... ) function waitForAll(...)
local routines = create( ... ) local routines = create(...)
return runUntilLimit( routines, 0 ) return runUntilLimit(routines, 0)
end end

View File

@ -37,13 +37,13 @@ local tHostnames = {}
-- --
-- @tparam string modem The name of the modem to open. -- @tparam string modem The name of the modem to open.
-- @throws If there is no such modem with the given name -- @throws If there is no such modem with the given name
function open( modem ) function open(modem)
expect(1, modem, "string") expect(1, modem, "string")
if peripheral.getType( modem ) ~= "modem" then if peripheral.getType(modem) ~= "modem" then
error( "No such modem: " .. modem, 2 ) error("No such modem: " .. modem, 2)
end end
peripheral.call( modem, "open", os.getComputerID() ) peripheral.call(modem, "open", os.getComputerID())
peripheral.call( modem, "open", CHANNEL_BROADCAST ) peripheral.call(modem, "open", CHANNEL_BROADCAST)
end end
--- Close a modem with the given @{peripheral} name, meaning it can no longer --- Close a modem with the given @{peripheral} name, meaning it can no longer
@ -52,20 +52,20 @@ end
-- @tparam[opt] string modem The side the modem exists on. If not given, all -- @tparam[opt] string modem The side the modem exists on. If not given, all
-- open modems will be closed. -- open modems will be closed.
-- @throws If there is no such modem with the given name -- @throws If there is no such modem with the given name
function close( modem ) function close(modem)
expect(1, modem, "string", "nil") expect(1, modem, "string", "nil")
if modem then if modem then
-- Close a specific modem -- Close a specific modem
if peripheral.getType( modem ) ~= "modem" then if peripheral.getType(modem) ~= "modem" then
error( "No such modem: " .. modem, 2 ) error("No such modem: " .. modem, 2)
end end
peripheral.call( modem, "close", os.getComputerID() ) peripheral.call(modem, "close", os.getComputerID())
peripheral.call( modem, "close", CHANNEL_BROADCAST ) peripheral.call(modem, "close", CHANNEL_BROADCAST)
else else
-- Close all modems -- Close all modems
for _, modem in ipairs( peripheral.getNames() ) do for _, modem in ipairs(peripheral.getNames()) do
if isOpen( modem ) then if isOpen(modem) then
close( modem ) close(modem)
end end
end end
end end
@ -76,17 +76,17 @@ end
-- @tparam[opt] string modem Which modem to check. If not given, all connected -- @tparam[opt] string modem Which modem to check. If not given, all connected
-- modems will be checked. -- modems will be checked.
-- @treturn boolean If the given modem is open. -- @treturn boolean If the given modem is open.
function isOpen( modem ) function isOpen(modem)
expect(1, modem, "string", "nil") expect(1, modem, "string", "nil")
if modem then if modem then
-- Check if a specific modem is open -- Check if a specific modem is open
if peripheral.getType( modem ) == "modem" then if peripheral.getType(modem) == "modem" then
return peripheral.call( modem, "isOpen", os.getComputerID() ) and peripheral.call( modem, "isOpen", CHANNEL_BROADCAST ) return peripheral.call(modem, "isOpen", os.getComputerID()) and peripheral.call(modem, "isOpen", CHANNEL_BROADCAST)
end end
else else
-- Check if any modem is open -- Check if any modem is open
for _, modem in ipairs( peripheral.getNames() ) do for _, modem in ipairs(peripheral.getNames()) do
if isOpen( modem ) then if isOpen(modem) then
return true return true
end end
end end
@ -111,15 +111,15 @@ end
-- currently @{rednet.open|open}). Note, this does not guarantee the message was -- currently @{rednet.open|open}). Note, this does not guarantee the message was
-- actually _received_. -- actually _received_.
-- @see rednet.receive -- @see rednet.receive
function send( nRecipient, message, sProtocol ) function send(nRecipient, message, sProtocol)
expect(1, nRecipient, "number") expect(1, nRecipient, "number")
expect(3, sProtocol, "string", "nil") expect(3, sProtocol, "string", "nil")
-- Generate a (probably) unique message ID -- Generate a (probably) unique message ID
-- We could do other things to guarantee uniqueness, but we really don't need to -- We could do other things to guarantee uniqueness, but we really don't need to
-- Store it to ensure we don't get our own messages back -- Store it to ensure we don't get our own messages back
local nMessageID = math.random( 1, 2147483647 ) local nMessageID = math.random(1, 2147483647)
tReceivedMessages[ nMessageID ] = true tReceivedMessages[nMessageID] = true
tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = nMessageID tReceivedMessageTimeouts[os.startTimer(30)] = nMessageID
-- Create the message -- Create the message
local nReplyChannel = os.getComputerID() local nReplyChannel = os.getComputerID()
@ -133,14 +133,14 @@ function send( nRecipient, message, sProtocol )
local sent = false local sent = false
if nRecipient == os.getComputerID() then if nRecipient == os.getComputerID() then
-- Loopback to ourselves -- Loopback to ourselves
os.queueEvent( "rednet_message", nReplyChannel, message, sProtocol ) os.queueEvent("rednet_message", nReplyChannel, message, sProtocol)
sent = true sent = true
else else
-- Send on all open modems, to the target and to repeaters -- Send on all open modems, to the target and to repeaters
for _, sModem in ipairs( peripheral.getNames() ) do for _, sModem in ipairs(peripheral.getNames()) do
if isOpen( sModem ) then if isOpen(sModem) then
peripheral.call( sModem, "transmit", nRecipient, nReplyChannel, tMessage ) peripheral.call(sModem, "transmit", nRecipient, nReplyChannel, tMessage)
peripheral.call( sModem, "transmit", CHANNEL_REPEAT, nReplyChannel, tMessage ) peripheral.call(sModem, "transmit", CHANNEL_REPEAT, nReplyChannel, tMessage)
sent = true sent = true
end end
end end
@ -158,9 +158,9 @@ end
-- using @{rednet.receive} one can filter to only receive messages sent under a -- using @{rednet.receive} one can filter to only receive messages sent under a
-- particular protocol. -- particular protocol.
-- @see rednet.receive -- @see rednet.receive
function broadcast( message, sProtocol ) function broadcast(message, sProtocol)
expect(2, sProtocol, "string", "nil") expect(2, sProtocol, "string", "nil")
send( CHANNEL_BROADCAST, message, sProtocol ) send(CHANNEL_BROADCAST, message, sProtocol)
end end
--- Wait for a rednet message to be received, or until `nTimeout` seconds have --- Wait for a rednet message to be received, or until `nTimeout` seconds have
@ -177,7 +177,7 @@ end
-- @treturn[2] nil If the timeout elapsed and no message was received. -- @treturn[2] nil If the timeout elapsed and no message was received.
-- @see rednet.broadcast -- @see rednet.broadcast
-- @see rednet.send -- @see rednet.send
function receive( sProtocolFilter, nTimeout ) function receive(sProtocolFilter, nTimeout)
-- The parameters used to be ( nTimeout ), detect this case for backwards compatibility -- The parameters used to be ( nTimeout ), detect this case for backwards compatibility
if type(sProtocolFilter) == "number" and nTimeout == nil then if type(sProtocolFilter) == "number" and nTimeout == nil then
sProtocolFilter, nTimeout = nil, sProtocolFilter sProtocolFilter, nTimeout = nil, sProtocolFilter
@ -189,7 +189,7 @@ function receive( sProtocolFilter, nTimeout )
local timer = nil local timer = nil
local sFilter = nil local sFilter = nil
if nTimeout then if nTimeout then
timer = os.startTimer( nTimeout ) timer = os.startTimer(nTimeout)
sFilter = nil sFilter = nil
else else
sFilter = "rednet_message" sFilter = "rednet_message"
@ -197,7 +197,7 @@ function receive( sProtocolFilter, nTimeout )
-- Wait for events -- Wait for events
while true do while true do
local sEvent, p1, p2, p3 = os.pullEvent( sFilter ) local sEvent, p1, p2, p3 = os.pullEvent(sFilter)
if sEvent == "rednet_message" then if sEvent == "rednet_message" then
-- Return the first matching rednet_message -- Return the first matching rednet_message
local nSenderID, message, sProtocol = p1, p2, p3 local nSenderID, message, sProtocol = p1, p2, p3
@ -231,17 +231,17 @@ end
-- @throws If trying to register a hostname which is reserved, or currently in use. -- @throws If trying to register a hostname which is reserved, or currently in use.
-- @see rednet.unhost -- @see rednet.unhost
-- @see rednet.lookup -- @see rednet.lookup
function host( sProtocol, sHostname ) function host(sProtocol, sHostname)
expect(1, sProtocol, "string") expect(1, sProtocol, "string")
expect(2, sHostname, "string") expect(2, sHostname, "string")
if sHostname == "localhost" then if sHostname == "localhost" then
error( "Reserved hostname", 2 ) error("Reserved hostname", 2)
end end
if tHostnames[ sProtocol ] ~= sHostname then if tHostnames[sProtocol] ~= sHostname then
if lookup( sProtocol, sHostname ) ~= nil then if lookup(sProtocol, sHostname) ~= nil then
error( "Hostname in use", 2 ) error("Hostname in use", 2)
end end
tHostnames[ sProtocol ] = sHostname tHostnames[sProtocol] = sHostname
end end
end end
@ -249,9 +249,9 @@ end
--- respond to @{rednet.lookup} requests. --- respond to @{rednet.lookup} requests.
-- --
-- @tparam string sProtocol The protocol to unregister your self from. -- @tparam string sProtocol The protocol to unregister your self from.
function unhost( sProtocol ) function unhost(sProtocol)
expect(1, sProtocol, "string") expect(1, sProtocol, "string")
tHostnames[ sProtocol ] = nil tHostnames[sProtocol] = nil
end end
--- Search the local rednet network for systems @{rednet.host|hosting} the --- Search the local rednet network for systems @{rednet.host|hosting} the
@ -268,7 +268,7 @@ end
-- protocol, or @{nil} if none exist. -- protocol, or @{nil} if none exist.
-- @treturn[2] number|nil The computer ID with the provided hostname and protocol, -- @treturn[2] number|nil The computer ID with the provided hostname and protocol,
-- or @{nil} if none exists. -- or @{nil} if none exists.
function lookup( sProtocol, sHostname ) function lookup(sProtocol, sHostname)
expect(1, sProtocol, "string") expect(1, sProtocol, "string")
expect(2, sHostname, "string", "nil") expect(2, sHostname, "string", "nil")
@ -279,30 +279,30 @@ function lookup( sProtocol, sHostname )
end end
-- Check localhost first -- Check localhost first
if tHostnames[ sProtocol ] then if tHostnames[sProtocol] then
if sHostname == nil then if sHostname == nil then
table.insert( tResults, os.getComputerID() ) table.insert(tResults, os.getComputerID())
elseif sHostname == "localhost" or sHostname == tHostnames[ sProtocol ] then elseif sHostname == "localhost" or sHostname == tHostnames[sProtocol] then
return os.getComputerID() return os.getComputerID()
end end
end end
if not isOpen() then if not isOpen() then
if tResults then if tResults then
return table.unpack( tResults ) return table.unpack(tResults)
end end
return nil return nil
end end
-- Broadcast a lookup packet -- Broadcast a lookup packet
broadcast( { broadcast({
sType = "lookup", sType = "lookup",
sProtocol = sProtocol, sProtocol = sProtocol,
sHostname = sHostname, sHostname = sHostname,
}, "dns" ) }, "dns")
-- Start a timer -- Start a timer
local timer = os.startTimer( 2 ) local timer = os.startTimer(2)
-- Wait for events -- Wait for events
while true do while true do
@ -313,7 +313,7 @@ function lookup( sProtocol, sHostname )
if sMessageProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup response" then if sMessageProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup response" then
if tMessage.sProtocol == sProtocol then if tMessage.sProtocol == sProtocol then
if sHostname == nil then if sHostname == nil then
table.insert( tResults, nSenderID ) table.insert(tResults, nSenderID)
elseif tMessage.sHostname == sHostname then elseif tMessage.sHostname == sHostname then
return nSenderID return nSenderID
end end
@ -327,7 +327,7 @@ function lookup( sProtocol, sHostname )
end end
end end
if tResults then if tResults then
return table.unpack( tResults ) return table.unpack(tResults)
end end
return nil return nil
end end
@ -337,7 +337,7 @@ local bRunning = false
--- @local --- @local
function run() function run()
if bRunning then if bRunning then
error( "rednet is already running", 2 ) error("rednet is already running", 2)
end end
bRunning = true bRunning = true
@ -346,12 +346,12 @@ function run()
if sEvent == "modem_message" then if sEvent == "modem_message" then
-- Got a modem message, process it and add it to the rednet event queue -- Got a modem message, process it and add it to the rednet event queue
local sModem, nChannel, nReplyChannel, tMessage = p1, p2, p3, p4 local sModem, nChannel, nReplyChannel, tMessage = p1, p2, p3, p4
if isOpen( sModem ) and ( nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST ) then if isOpen(sModem) and (nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST) then
if type( tMessage ) == "table" and tMessage.nMessageID then if type(tMessage) == "table" and tMessage.nMessageID then
if not tReceivedMessages[ tMessage.nMessageID ] then if not tReceivedMessages[tMessage.nMessageID] then
tReceivedMessages[ tMessage.nMessageID ] = true tReceivedMessages[tMessage.nMessageID] = true
tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = tMessage.nMessageID tReceivedMessageTimeouts[os.startTimer(30)] = tMessage.nMessageID
os.queueEvent( "rednet_message", nReplyChannel, tMessage.message, tMessage.sProtocol ) os.queueEvent("rednet_message", nReplyChannel, tMessage.message, tMessage.sProtocol)
end end
end end
end end
@ -360,23 +360,23 @@ function run()
-- Got a rednet message (queued from above), respond to dns lookup -- Got a rednet message (queued from above), respond to dns lookup
local nSenderID, tMessage, sProtocol = p1, p2, p3 local nSenderID, tMessage, sProtocol = p1, p2, p3
if sProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup" then if sProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup" then
local sHostname = tHostnames[ tMessage.sProtocol ] local sHostname = tHostnames[tMessage.sProtocol]
if sHostname ~= nil and (tMessage.sHostname == nil or tMessage.sHostname == sHostname) then if sHostname ~= nil and (tMessage.sHostname == nil or tMessage.sHostname == sHostname) then
rednet.send( nSenderID, { rednet.send(nSenderID, {
sType = "lookup response", sType = "lookup response",
sHostname = sHostname, sHostname = sHostname,
sProtocol = tMessage.sProtocol, sProtocol = tMessage.sProtocol,
}, "dns" ) }, "dns")
end end
end end
elseif sEvent == "timer" then elseif sEvent == "timer" then
-- Got a timer event, use it to clear the event queue -- Got a timer event, use it to clear the event queue
local nTimer = p1 local nTimer = p1
local nMessage = tReceivedMessageTimeouts[ nTimer ] local nMessage = tReceivedMessageTimeouts[nTimer]
if nMessage then if nMessage then
tReceivedMessageTimeouts[ nTimer ] = nil tReceivedMessageTimeouts[nTimer] = nil
tReceivedMessages[ nMessage ] = nil tReceivedMessages[nMessage] = nil
end end
end end
end end

View File

@ -17,19 +17,19 @@ local tSettings = {}
-- serialisable by @{textutils.serialize}. -- serialisable by @{textutils.serialize}.
-- @throws If this value cannot be serialised -- @throws If this value cannot be serialised
-- @see settings.unset -- @see settings.unset
function set( name, value ) function set(name, value)
expect(1, name, "string") expect(1, name, "string")
expect(2, value, "number", "string", "boolean", "table") expect(2, value, "number", "string", "boolean", "table")
if type(value) == "table" then if type(value) == "table" then
-- Ensure value is serializeable -- Ensure value is serializeable
value = textutils.unserialize( textutils.serialize(value) ) value = textutils.unserialize(textutils.serialize(value))
end end
tSettings[ name ] = value tSettings[name] = value
end end
local copy local copy
function copy( value ) function copy(value)
if type(value) == "table" then if type(value) == "table" then
local result = {} local result = {}
for k, v in pairs(value) do for k, v in pairs(value) do
@ -47,9 +47,9 @@ end
-- @param[opt] default The value to use should there be pre-existing value for -- @param[opt] default The value to use should there be pre-existing value for
-- this setting. Defaults to `nil`. -- this setting. Defaults to `nil`.
-- @return The setting's, or `default` if the setting has not been set. -- @return The setting's, or `default` if the setting has not been set.
function get( name, default ) function get(name, default)
expect(1, name, "string") expect(1, name, "string")
local result = tSettings[ name ] local result = tSettings[name]
if result ~= nil then if result ~= nil then
return copy(result) return copy(result)
else else
@ -65,9 +65,9 @@ end
-- @tparam string name The name of the setting to unset. -- @tparam string name The name of the setting to unset.
-- @see settings.set -- @see settings.set
-- @see settings.clear -- @see settings.clear
function unset( name ) function unset(name)
expect(1, name, "string") expect(1, name, "string")
tSettings[ name ] = nil tSettings[name] = nil
end end
--- Removes the value of all settings. Equivalent to calling @{settings.unset} --- Removes the value of all settings. Equivalent to calling @{settings.unset}
@ -84,8 +84,8 @@ end
-- settings. -- settings.
function getNames() function getNames()
local result = {} local result = {}
for k in pairs( tSettings ) do for k in pairs(tSettings) do
result[ #result + 1 ] = k result[#result + 1] = k
end end
table.sort(result) table.sort(result)
return result return result
@ -102,9 +102,9 @@ end
-- corrupted. -- corrupted.
-- --
-- @see settings.save -- @see settings.save
function load( sPath ) function load(sPath)
expect(1, sPath, "string") expect(1, sPath, "string")
local file = fs.open( sPath, "r" ) local file = fs.open(sPath, "r")
if not file then if not file then
return false return false
end end
@ -112,7 +112,7 @@ function load( sPath )
local sText = file.readAll() local sText = file.readAll()
file.close() file.close()
local tFile = textutils.unserialize( sText ) local tFile = textutils.unserialize(sText)
if type(tFile) ~= "table" then if type(tFile) ~= "table" then
return false return false
end end
@ -120,7 +120,7 @@ function load( sPath )
for k, v in pairs(tFile) do for k, v in pairs(tFile) do
if type(k) == "string" and if type(k) == "string" and
(type(v) == "string" or type(v) == "number" or type(v) == "boolean" or type(v) == "table") then (type(v) == "string" or type(v) == "number" or type(v) == "boolean" or type(v) == "table") then
set( k, v ) set(k, v)
end end
end end
@ -136,14 +136,14 @@ end
-- @treturn boolean If the settings were successfully saved. -- @treturn boolean If the settings were successfully saved.
-- --
-- @see settings.load -- @see settings.load
function save( sPath ) function save(sPath)
expect(1, sPath, "string") expect(1, sPath, "string")
local file = fs.open( sPath, "w" ) local file = fs.open(sPath, "w")
if not file then if not file then
return false return false
end end
file.write( textutils.serialize( tSettings ) ) file.write(textutils.serialize(tSettings))
file.close() file.close()
return true return true

View File

@ -8,9 +8,9 @@ local expect = dofile("rom/modules/main/cc/expect.lua").expect
local native = term.native and term.native() or term local native = term.native and term.native() or term
local redirectTarget = native local redirectTarget = native
local function wrap( _sFunction ) local function wrap(_sFunction)
return function( ... ) return function(...)
return redirectTarget[ _sFunction ]( ... ) return redirectTarget[_sFunction](...)
end end
end end
@ -34,16 +34,16 @@ local term = _ENV
-- @usage -- @usage
-- Redirect to a monitor on the right of the computer. -- Redirect to a monitor on the right of the computer.
-- term.redirect(peripheral.wrap("right")) -- term.redirect(peripheral.wrap("right"))
term.redirect = function( target ) term.redirect = function(target)
expect(1, target, "table") expect(1, target, "table")
if target == term or target == _G.term then if target == term or target == _G.term then
error( "term is not a recommended redirect target, try term.current() instead", 2 ) error("term is not a recommended redirect target, try term.current() instead", 2)
end end
for k, v in pairs( native ) do for k, v in pairs(native) do
if type( k ) == "string" and type( v ) == "function" then if type(k) == "string" and type(v) == "function" then
if type( target[k] ) ~= "function" then if type(target[k]) ~= "function" then
target[k] = function() target[k] = function()
error( "Redirect object is missing method " .. k .. ".", 2 ) error("Redirect object is missing method " .. k .. ".", 2)
end end
end end
end end
@ -81,8 +81,8 @@ for _, method in ipairs { "nativePaletteColor", "nativePaletteColour" } do
native[method] = nil native[method] = nil
end end
for k, v in pairs( native ) do for k, v in pairs(native) do
if type( k ) == "string" and type( v ) == "function" and rawget(term, k) == nil then if type(k) == "string" and type(v) == "function" and rawget(term, k) == nil then
term[k] = wrap( k ) term[k] = wrap(k)
end end
end end

View File

@ -15,22 +15,22 @@ local expect = dofile("rom/modules/main/cc/expect.lua").expect
-- Defaults to 20. -- Defaults to 20.
-- @usage textutils.slowWrite("Hello, world!") -- @usage textutils.slowWrite("Hello, world!")
-- @usage textutils.slowWrite("Hello, world!", 5) -- @usage textutils.slowWrite("Hello, world!", 5)
function slowWrite( sText, nRate ) function slowWrite(sText, nRate)
expect(2, nRate, "number", "nil") expect(2, nRate, "number", "nil")
nRate = nRate or 20 nRate = nRate or 20
if nRate < 0 then if nRate < 0 then
error( "Rate must be positive", 2 ) error("Rate must be positive", 2)
end end
local nSleep = 1 / nRate local nSleep = 1 / nRate
sText = tostring( sText ) sText = tostring(sText)
local x, y = term.getCursorPos() local x, y = term.getCursorPos()
local len = #sText local len = #sText
for n = 1, len do for n = 1, len do
term.setCursorPos( x, y ) term.setCursorPos(x, y)
sleep( nSleep ) sleep(nSleep)
local nLines = write( string.sub( sText, 1, n ) ) local nLines = write(string.sub(sText, 1, n))
local _, newY = term.getCursorPos() local _, newY = term.getCursorPos()
y = newY - nLines y = newY - nLines
end end
@ -46,8 +46,8 @@ end
-- Defaults to 20. -- Defaults to 20.
-- @usage textutils.slowPrint("Hello, world!") -- @usage textutils.slowPrint("Hello, world!")
-- @usage textutils.slowPrint("Hello, world!", 5) -- @usage textutils.slowPrint("Hello, world!", 5)
function slowPrint( sText, nRate ) function slowPrint(sText, nRate)
slowWrite( sText, nRate ) slowWrite(sText, nRate)
print() print()
end end
@ -58,7 +58,7 @@ end
-- clock (`18:30`) rather than a 12-hour one (`6:30 AM`) -- clock (`18:30`) rather than a 12-hour one (`6:30 AM`)
-- @treturn string The formatted time -- @treturn string The formatted time
-- @usage textutils.formatTime(os.time()) -- @usage textutils.formatTime(os.time())
function formatTime( nTime, bTwentyFourHour ) function formatTime(nTime, bTwentyFourHour)
expect(1, nTime, "number") expect(1, nTime, "number")
expect(2, bTwentyFourHour, "boolean", "nil") expect(2, bTwentyFourHour, "boolean", "nil")
local sTOD = nil local sTOD = nil
@ -76,26 +76,26 @@ function formatTime( nTime, bTwentyFourHour )
local nHour = math.floor(nTime) local nHour = math.floor(nTime)
local nMinute = math.floor((nTime - nHour) * 60) local nMinute = math.floor((nTime - nHour) * 60)
if sTOD then if sTOD then
return string.format( "%d:%02d %s", nHour, nMinute, sTOD ) return string.format("%d:%02d %s", nHour, nMinute, sTOD)
else else
return string.format( "%d:%02d", nHour, nMinute ) return string.format("%d:%02d", nHour, nMinute)
end end
end end
local function makePagedScroll( _term, _nFreeLines ) local function makePagedScroll(_term, _nFreeLines)
local nativeScroll = _term.scroll local nativeScroll = _term.scroll
local nFreeLines = _nFreeLines or 0 local nFreeLines = _nFreeLines or 0
return function( _n ) return function(_n)
for _ = 1, _n do for _ = 1, _n do
nativeScroll( 1 ) nativeScroll(1)
if nFreeLines <= 0 then if nFreeLines <= 0 then
local _, h = _term.getSize() local _, h = _term.getSize()
_term.setCursorPos( 1, h ) _term.setCursorPos(1, h)
_term.write( "Press any key to continue" ) _term.write("Press any key to continue")
os.pullEvent( "key" ) os.pullEvent("key")
_term.clearLine() _term.clearLine()
_term.setCursorPos( 1, h ) _term.setCursorPos(1, h)
else else
nFreeLines = nFreeLines - 1 nFreeLines = nFreeLines - 1
end end
@ -120,38 +120,38 @@ end
-- @usage -- @usage
-- local width, height = term.getSize() -- local width, height = term.getSize()
-- textutils.pagedPrint(("This is a rather verbose dose of repetition.\n"):rep(30), height - 2) -- textutils.pagedPrint(("This is a rather verbose dose of repetition.\n"):rep(30), height - 2)
function pagedPrint( _sText, _nFreeLines ) function pagedPrint(_sText, _nFreeLines)
expect(2, _nFreeLines, "number", "nil") expect(2, _nFreeLines, "number", "nil")
-- Setup a redirector -- Setup a redirector
local oldTerm = term.current() local oldTerm = term.current()
local newTerm = {} local newTerm = {}
for k, v in pairs( oldTerm ) do for k, v in pairs(oldTerm) do
newTerm[k] = v newTerm[k] = v
end end
newTerm.scroll = makePagedScroll( oldTerm, _nFreeLines ) newTerm.scroll = makePagedScroll(oldTerm, _nFreeLines)
term.redirect( newTerm ) term.redirect(newTerm)
-- Print the text -- Print the text
local result local result
local ok, err = pcall( function() local ok, err = pcall(function()
if _sText ~= nil then if _sText ~= nil then
result = print( _sText ) result = print(_sText)
else else
result = print() result = print()
end end
end ) end)
-- Removed the redirector -- Removed the redirector
term.redirect( oldTerm ) term.redirect(oldTerm)
-- Propogate errors -- Propogate errors
if not ok then if not ok then
error( err, 0 ) error(err, 0)
end end
return result return result
end end
local function tabulateCommon( bPaged, ... ) local function tabulateCommon(bPaged, ...)
local tAll = table.pack(...) local tAll = table.pack(...)
for i = 1, tAll.n do for i = 1, tAll.n do
expect(i, tAll[i], "number", "table") expect(i, tAll[i], "number", "table")
@ -159,17 +159,17 @@ local function tabulateCommon( bPaged, ... )
local w, h = term.getSize() local w, h = term.getSize()
local nMaxLen = w / 8 local nMaxLen = w / 8
for n, t in ipairs( tAll ) do for n, t in ipairs(tAll) do
if type(t) == "table" then if type(t) == "table" then
for nu, sItem in pairs(t) do for nu, sItem in pairs(t) do
if type( sItem ) ~= "string" then if type(sItem) ~= "string" then
error( "bad argument #" .. n .. "." .. nu .. " (expected string, got " .. type( sItem ) .. ")", 3 ) error("bad argument #" .. n .. "." .. nu .. " (expected string, got " .. type(sItem) .. ")", 3)
end end
nMaxLen = math.max( #sItem + 1, nMaxLen ) nMaxLen = math.max(#sItem + 1, nMaxLen)
end end
end end
end end
local nCols = math.floor( w / nMaxLen ) local nCols = math.floor(w / nMaxLen)
local nLines = 0 local nLines = 0
local function newLine() local function newLine()
if bPaged and nLines >= h - 3 then if bPaged and nLines >= h - 3 then
@ -180,9 +180,9 @@ local function tabulateCommon( bPaged, ... )
nLines = nLines + 1 nLines = nLines + 1
end end
local function drawCols( _t ) local function drawCols(_t)
local nCol = 1 local nCol = 1
for _, s in ipairs( _t ) do for _, s in ipairs(_t) do
if nCol > nCols then if nCol > nCols then
nCol = 1 nCol = 1
newLine() newLine()
@ -190,20 +190,20 @@ local function tabulateCommon( bPaged, ... )
local cx, cy = term.getCursorPos() local cx, cy = term.getCursorPos()
cx = 1 + (nCol - 1) * nMaxLen cx = 1 + (nCol - 1) * nMaxLen
term.setCursorPos( cx, cy ) term.setCursorPos(cx, cy)
term.write( s ) term.write(s)
nCol = nCol + 1 nCol = nCol + 1
end end
print() print()
end end
for _, t in ipairs( tAll ) do for _, t in ipairs(tAll) do
if type(t) == "table" then if type(t) == "table" then
if #t > 0 then if #t > 0 then
drawCols( t ) drawCols(t)
end end
elseif type(t) == "number" then elseif type(t) == "number" then
term.setTextColor( t ) term.setTextColor(t)
end end
end end
end end
@ -218,8 +218,8 @@ end
-- --
-- @tparam {string...}|number ... The rows and text colors to display. -- @tparam {string...}|number ... The rows and text colors to display.
-- @usage textutils.tabulate(colors.orange, { "1", "2", "3" }, colors.lightBlue, { "A", "B", "C" }) -- @usage textutils.tabulate(colors.orange, { "1", "2", "3" }, colors.lightBlue, { "A", "B", "C" })
function tabulate( ... ) function tabulate(...)
return tabulateCommon( false, ... ) return tabulateCommon(false, ...)
end end
--- Prints tables in a structured form, stopping and prompting for input should --- Prints tables in a structured form, stopping and prompting for input should
@ -232,39 +232,39 @@ end
-- @usage textutils.tabulate(colors.orange, { "1", "2", "3" }, colors.lightBlue, { "A", "B", "C" }) -- @usage textutils.tabulate(colors.orange, { "1", "2", "3" }, colors.lightBlue, { "A", "B", "C" })
-- @see textutils.tabulate -- @see textutils.tabulate
-- @see textutils.pagedPrint -- @see textutils.pagedPrint
function pagedTabulate( ... ) function pagedTabulate(...)
return tabulateCommon( true, ... ) return tabulateCommon(true, ...)
end end
local g_tLuaKeywords = { local g_tLuaKeywords = {
[ "and" ] = true, ["and"] = true,
[ "break" ] = true, ["break"] = true,
[ "do" ] = true, ["do"] = true,
[ "else" ] = true, ["else"] = true,
[ "elseif" ] = true, ["elseif"] = true,
[ "end" ] = true, ["end"] = true,
[ "false" ] = true, ["false"] = true,
[ "for" ] = true, ["for"] = true,
[ "function" ] = true, ["function"] = true,
[ "if" ] = true, ["if"] = true,
[ "in" ] = true, ["in"] = true,
[ "local" ] = true, ["local"] = true,
[ "nil" ] = true, ["nil"] = true,
[ "not" ] = true, ["not"] = true,
[ "or" ] = true, ["or"] = true,
[ "repeat" ] = true, ["repeat"] = true,
[ "return" ] = true, ["return"] = true,
[ "then" ] = true, ["then"] = true,
[ "true" ] = true, ["true"] = true,
[ "until" ] = true, ["until"] = true,
[ "while" ] = true, ["while"] = true,
} }
local function serializeImpl( t, tTracking, sIndent ) local function serializeImpl(t, tTracking, sIndent)
local sType = type(t) local sType = type(t)
if sType == "table" then if sType == "table" then
if tTracking[t] ~= nil then if tTracking[t] ~= nil then
error( "Cannot serialize table with recursive entries", 0 ) error("Cannot serialize table with recursive entries", 0)
end end
tTracking[t] = true tTracking[t] = true
@ -278,15 +278,15 @@ local function serializeImpl( t, tTracking, sIndent )
local tSeen = {} local tSeen = {}
for k, v in ipairs(t) do for k, v in ipairs(t) do
tSeen[k] = true tSeen[k] = true
sResult = sResult .. sSubIndent .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n" sResult = sResult .. sSubIndent .. serializeImpl(v, tTracking, sSubIndent) .. ",\n"
end end
for k, v in pairs(t) do for k, v in pairs(t) do
if not tSeen[k] then if not tSeen[k] then
local sEntry local sEntry
if type(k) == "string" and not g_tLuaKeywords[k] and string.match( k, "^[%a_][%a%d_]*$" ) then if type(k) == "string" and not g_tLuaKeywords[k] and string.match(k, "^[%a_][%a%d_]*$") then
sEntry = k .. " = " .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n" sEntry = k .. " = " .. serializeImpl(v, tTracking, sSubIndent) .. ",\n"
else else
sEntry = "[ " .. serializeImpl( k, tTracking, sSubIndent ) .. " ] = " .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n" sEntry = "[ " .. serializeImpl(k, tTracking, sSubIndent) .. " ] = " .. serializeImpl(v, tTracking, sSubIndent) .. ",\n"
end end
sResult = sResult .. sSubIndent .. sEntry sResult = sResult .. sSubIndent .. sEntry
end end
@ -296,13 +296,13 @@ local function serializeImpl( t, tTracking, sIndent )
end end
elseif sType == "string" then elseif sType == "string" then
return string.format( "%q", t ) return string.format("%q", t)
elseif sType == "number" or sType == "boolean" or sType == "nil" then elseif sType == "number" or sType == "boolean" or sType == "nil" then
return tostring(t) return tostring(t)
else else
error( "Cannot serialize type " .. sType, 0 ) error("Cannot serialize type " .. sType, 0)
end end
end end
@ -320,14 +320,14 @@ empty_json_array = setmetatable({}, {
end, end,
}) })
local function serializeJSONImpl( t, tTracking, bNBTStyle ) local function serializeJSONImpl(t, tTracking, bNBTStyle)
local sType = type(t) local sType = type(t)
if t == empty_json_array then if t == empty_json_array then
return "[]" return "[]"
elseif sType == "table" then elseif sType == "table" then
if tTracking[t] ~= nil then if tTracking[t] ~= nil then
error( "Cannot serialize table with recursive entries", 0 ) error("Cannot serialize table with recursive entries", 0)
end end
tTracking[t] = true tTracking[t] = true
@ -344,9 +344,9 @@ local function serializeJSONImpl( t, tTracking, bNBTStyle )
if type(k) == "string" then if type(k) == "string" then
local sEntry local sEntry
if bNBTStyle then if bNBTStyle then
sEntry = tostring(k) .. ":" .. serializeJSONImpl( v, tTracking, bNBTStyle ) sEntry = tostring(k) .. ":" .. serializeJSONImpl(v, tTracking, bNBTStyle)
else else
sEntry = string.format( "%q", k ) .. ":" .. serializeJSONImpl( v, tTracking, bNBTStyle ) sEntry = string.format("%q", k) .. ":" .. serializeJSONImpl(v, tTracking, bNBTStyle)
end end
if nObjectSize == 0 then if nObjectSize == 0 then
sObjectResult = sObjectResult .. sEntry sObjectResult = sObjectResult .. sEntry
@ -357,7 +357,7 @@ local function serializeJSONImpl( t, tTracking, bNBTStyle )
end end
end end
for _, v in ipairs(t) do for _, v in ipairs(t) do
local sEntry = serializeJSONImpl( v, tTracking, bNBTStyle ) local sEntry = serializeJSONImpl(v, tTracking, bNBTStyle)
if nArraySize == 0 then if nArraySize == 0 then
sArrayResult = sArrayResult .. sEntry sArrayResult = sArrayResult .. sEntry
else else
@ -375,13 +375,13 @@ local function serializeJSONImpl( t, tTracking, bNBTStyle )
end end
elseif sType == "string" then elseif sType == "string" then
return string.format( "%q", t ) return string.format("%q", t)
elseif sType == "number" or sType == "boolean" then elseif sType == "number" or sType == "boolean" then
return tostring(t) return tostring(t)
else else
error( "Cannot serialize type " .. sType, 0 ) error("Cannot serialize type " .. sType, 0)
end end
end end
@ -394,9 +394,9 @@ end
-- @throws If the object contains a value which cannot be -- @throws If the object contains a value which cannot be
-- serialised. This includes functions and tables which appear multiple -- serialised. This includes functions and tables which appear multiple
-- times. -- times.
function serialize( t ) function serialize(t)
local tTracking = {} local tTracking = {}
return serializeImpl( t, tTracking, "" ) return serializeImpl(t, tTracking, "")
end end
serialise = serialize -- GB version serialise = serialize -- GB version
@ -408,11 +408,11 @@ serialise = serialize -- GB version
-- @tparam string s The serialised string to deserialise. -- @tparam string s The serialised string to deserialise.
-- @return[1] The deserialised object -- @return[1] The deserialised object
-- @treturn[2] nil If the object could not be deserialised. -- @treturn[2] nil If the object could not be deserialised.
function unserialize( s ) function unserialize(s)
expect(1, s, "string") expect(1, s, "string")
local func = load( "return " .. s, "unserialize", "t", {} ) local func = load("return " .. s, "unserialize", "t", {})
if func then if func then
local ok, result = pcall( func ) local ok, result = pcall(func)
if ok then if ok then
return result return result
end end
@ -440,11 +440,11 @@ unserialise = unserialize -- GB version
-- serialised. This includes functions and tables which appear multiple -- serialised. This includes functions and tables which appear multiple
-- times. -- times.
-- @usage textutils.serializeJSON({ values = { 1, "2", true } }) -- @usage textutils.serializeJSON({ values = { 1, "2", true } })
function serializeJSON( t, bNBTStyle ) function serializeJSON(t, bNBTStyle)
expect(1, t, "table", "string", "number", "boolean") expect(1, t, "table", "string", "number", "boolean")
expect(2, bNBTStyle, "boolean", "nil") expect(2, bNBTStyle, "boolean", "nil")
local tTracking = {} local tTracking = {}
return serializeJSONImpl( t, tTracking, bNBTStyle or false ) return serializeJSONImpl(t, tTracking, bNBTStyle or false)
end end
serialiseJSON = serializeJSON -- GB version serialiseJSON = serializeJSON -- GB version
@ -454,7 +454,7 @@ serialiseJSON = serializeJSON -- GB version
-- @tparam string str The string to encode -- @tparam string str The string to encode
-- @treturn string The encoded string. -- @treturn string The encoded string.
-- @usage print("https://example.com/?view=" .. textutils.urlEncode(read())) -- @usage print("https://example.com/?view=" .. textutils.urlEncode(read()))
function urlEncode( str ) function urlEncode(str)
expect(1, str, "string") expect(1, str, "string")
if str then if str then
str = string.gsub(str, "\n", "\r\n") str = string.gsub(str, "\n", "\r\n")
@ -466,8 +466,8 @@ function urlEncode( str )
else else
-- Non-ASCII (encode as UTF-8) -- Non-ASCII (encode as UTF-8)
return return
string.format("%%%02X", 192 + bit32.band( bit32.arshift(n, 6), 31 )) .. string.format("%%%02X", 192 + bit32.band(bit32.arshift(n, 6), 31)) ..
string.format("%%%02X", 128 + bit32.band( n, 63 )) string.format("%%%02X", 128 + bit32.band(n, 63))
end end
end) end)
str = string.gsub(str, " ", "+") str = string.gsub(str, " ", "+")
@ -493,30 +493,30 @@ local tEmpty = {}
-- @see shell.setCompletionFunction -- @see shell.setCompletionFunction
-- @see read -- @see read
-- @usage textutils.complete( "pa", getfenv() ) -- @usage textutils.complete( "pa", getfenv() )
function complete( sSearchText, tSearchTable ) function complete(sSearchText, tSearchTable)
expect(1, sSearchText, "string") expect(1, sSearchText, "string")
expect(2, tSearchTable, "table", "nil") expect(2, tSearchTable, "table", "nil")
if g_tLuaKeywords[sSearchText] then return tEmpty end if g_tLuaKeywords[sSearchText] then return tEmpty end
local nStart = 1 local nStart = 1
local nDot = string.find( sSearchText, ".", nStart, true ) local nDot = string.find(sSearchText, ".", nStart, true)
local tTable = tSearchTable or _ENV local tTable = tSearchTable or _ENV
while nDot do while nDot do
local sPart = string.sub( sSearchText, nStart, nDot - 1 ) local sPart = string.sub(sSearchText, nStart, nDot - 1)
local value = tTable[ sPart ] local value = tTable[sPart]
if type( value ) == "table" then if type(value) == "table" then
tTable = value tTable = value
nStart = nDot + 1 nStart = nDot + 1
nDot = string.find( sSearchText, ".", nStart, true ) nDot = string.find(sSearchText, ".", nStart, true)
else else
return tEmpty return tEmpty
end end
end end
local nColon = string.find( sSearchText, ":", nStart, true ) local nColon = string.find(sSearchText, ":", nStart, true)
if nColon then if nColon then
local sPart = string.sub( sSearchText, nStart, nColon - 1 ) local sPart = string.sub(sSearchText, nStart, nColon - 1)
local value = tTable[ sPart ] local value = tTable[sPart]
if type( value ) == "table" then if type(value) == "table" then
tTable = value tTable = value
nStart = nColon + 1 nStart = nColon + 1
else else
@ -524,24 +524,24 @@ function complete( sSearchText, tSearchTable )
end end
end end
local sPart = string.sub( sSearchText, nStart ) local sPart = string.sub(sSearchText, nStart)
local nPartLength = #sPart local nPartLength = #sPart
local tResults = {} local tResults = {}
local tSeen = {} local tSeen = {}
while tTable do while tTable do
for k, v in pairs( tTable ) do for k, v in pairs(tTable) do
if not tSeen[k] and type(k) == "string" then if not tSeen[k] and type(k) == "string" then
if string.find( k, sPart, 1, true ) == 1 then if string.find(k, sPart, 1, true) == 1 then
if not g_tLuaKeywords[k] and string.match( k, "^[%a_][%a%d_]*$" ) then if not g_tLuaKeywords[k] and string.match(k, "^[%a_][%a%d_]*$") then
local sResult = string.sub( k, nPartLength + 1 ) local sResult = string.sub(k, nPartLength + 1)
if nColon then if nColon then
if type(v) == "function" then if type(v) == "function" then
table.insert( tResults, sResult .. "(" ) table.insert(tResults, sResult .. "(")
elseif type(v) == "table" then elseif type(v) == "table" then
local tMetatable = getmetatable( v ) local tMetatable = getmetatable(v)
if tMetatable and ( type( tMetatable.__call ) == "function" or type( tMetatable.__call ) == "table" ) then if tMetatable and (type(tMetatable.__call) == "function" or type(tMetatable.__call) == "table") then
table.insert( tResults, sResult .. "(" ) table.insert(tResults, sResult .. "(")
end end
end end
else else
@ -550,21 +550,21 @@ function complete( sSearchText, tSearchTable )
elseif type(v) == "table" and next(v) ~= nil then elseif type(v) == "table" and next(v) ~= nil then
sResult = sResult .. "." sResult = sResult .. "."
end end
table.insert( tResults, sResult ) table.insert(tResults, sResult)
end end
end end
end end
end end
tSeen[k] = true tSeen[k] = true
end end
local tMetatable = getmetatable( tTable ) local tMetatable = getmetatable(tTable)
if tMetatable and type( tMetatable.__index ) == "table" then if tMetatable and type(tMetatable.__index) == "table" then
tTable = tMetatable.__index tTable = tMetatable.__index
else else
tTable = nil tTable = nil
end end
end end
table.sort( tResults ) table.sort(tResults)
return tResults return tResults
end end

View File

@ -3,18 +3,18 @@
-- @module turtle -- @module turtle
if not turtle then if not turtle then
error( "Cannot load turtle API on computer", 2 ) error("Cannot load turtle API on computer", 2)
end end
native = turtle.native or turtle native = turtle.native or turtle
local function addCraftMethod( object ) local function addCraftMethod(object)
if peripheral.getType( "left" ) == "workbench" then if peripheral.getType("left") == "workbench" then
object.craft = function( ... ) object.craft = function(...)
return peripheral.call( "left", "craft", ... ) return peripheral.call("left", "craft", ...)
end end
elseif peripheral.getType( "right" ) == "workbench" then elseif peripheral.getType("right") == "workbench" then
object.craft = function( ... ) object.craft = function(...)
return peripheral.call( "right", "craft", ... ) return peripheral.call("right", "craft", ...)
end end
else else
object.craft = nil object.craft = nil
@ -23,15 +23,15 @@ end
-- Put commands into environment table -- Put commands into environment table
local env = _ENV local env = _ENV
for k, v in pairs( native ) do for k, v in pairs(native) do
if k == "equipLeft" or k == "equipRight" then if k == "equipLeft" or k == "equipRight" then
env[k] = function( ... ) env[k] = function(...)
local result, err = v( ... ) local result, err = v(...)
addCraftMethod( turtle ) addCraftMethod(turtle)
return result, err return result, err
end end
else else
env[k] = v env[k] = v
end end
end end
addCraftMethod( env ) addCraftMethod(env)

View File

@ -113,7 +113,7 @@ local vector = {
-- @tparam Vector self This vector. -- @tparam Vector self This vector.
-- @treturn number The length of this vector. -- @treturn number The length of this vector.
length = function(self) length = function(self)
return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z ) return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
end, end,
--- Divide this vector by its length, producing with the same direction, but --- Divide this vector by its length, producing with the same direction, but
@ -123,7 +123,7 @@ local vector = {
-- @treturn Vector The normalised vector -- @treturn Vector The normalised vector
-- @usage v:normalize() -- @usage v:normalize()
normalize = function(self) normalize = function(self)
return self:mul( 1 / self:length() ) return self:mul(1 / self:length())
end, end,
--- Construct a vector with each dimension rounded to the nearest value. --- Construct a vector with each dimension rounded to the nearest value.

View File

@ -30,22 +30,22 @@
local expect = dofile("rom/modules/main/cc/expect.lua").expect local expect = dofile("rom/modules/main/cc/expect.lua").expect
local tHex = { local tHex = {
[ colors.white ] = "0", [colors.white] = "0",
[ colors.orange ] = "1", [colors.orange] = "1",
[ colors.magenta ] = "2", [colors.magenta] = "2",
[ colors.lightBlue ] = "3", [colors.lightBlue] = "3",
[ colors.yellow ] = "4", [colors.yellow] = "4",
[ colors.lime ] = "5", [colors.lime] = "5",
[ colors.pink ] = "6", [colors.pink] = "6",
[ colors.gray ] = "7", [colors.gray] = "7",
[ colors.lightGray ] = "8", [colors.lightGray] = "8",
[ colors.cyan ] = "9", [colors.cyan] = "9",
[ colors.purple ] = "a", [colors.purple] = "a",
[ colors.blue ] = "b", [colors.blue] = "b",
[ colors.brown ] = "c", [colors.brown] = "c",
[ colors.green ] = "d", [colors.green] = "d",
[ colors.red ] = "e", [colors.red] = "e",
[ colors.black ] = "f", [colors.black] = "f",
} }
local type = type local type = type
@ -70,7 +70,7 @@ local string_sub = string.sub
-- @tparam[opt] boolean bStartVisible Whether this window is visible by -- @tparam[opt] boolean bStartVisible Whether this window is visible by
-- default. Defaults to `true`. -- default. Defaults to `true`.
-- @treturn Window The constructed window -- @treturn Window The constructed window
function create( parent, nX, nY, nWidth, nHeight, bStartVisible ) function create(parent, nX, nY, nWidth, nHeight, bStartVisible)
expect(1, parent, "table") expect(1, parent, "table")
expect(2, nX, "number") expect(2, nX, "number")
expect(3, nY, "number") expect(3, nY, "number")
@ -79,21 +79,21 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
expect(6, bStartVisible, "boolean", "nil") expect(6, bStartVisible, "boolean", "nil")
if parent == term then if parent == term then
error( "term is not a recommended window parent, try term.current() instead", 2 ) error("term is not a recommended window parent, try term.current() instead", 2)
end end
local sEmptySpaceLine local sEmptySpaceLine
local tEmptyColorLines = {} local tEmptyColorLines = {}
local function createEmptyLines( nWidth ) local function createEmptyLines(nWidth)
sEmptySpaceLine = string_rep( " ", nWidth ) sEmptySpaceLine = string_rep(" ", nWidth)
for n = 0, 15 do for n = 0, 15 do
local nColor = 2 ^ n local nColor = 2 ^ n
local sHex = tHex[nColor] local sHex = tHex[nColor]
tEmptyColorLines[nColor] = string_rep( sHex, nWidth ) tEmptyColorLines[nColor] = string_rep(sHex, nWidth)
end end
end end
createEmptyLines( nWidth ) createEmptyLines(nWidth)
-- Setup -- Setup
local bVisible = bStartVisible ~= false local bVisible = bStartVisible ~= false
@ -106,8 +106,8 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
local tPalette = {} local tPalette = {}
do do
local sEmptyText = sEmptySpaceLine local sEmptyText = sEmptySpaceLine
local sEmptyTextColor = tEmptyColorLines[ nTextColor ] local sEmptyTextColor = tEmptyColorLines[nTextColor]
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
for y = 1, nHeight do for y = 1, nHeight do
tLines[y] = { tLines[y] = {
text = sEmptyText, text = sEmptyText,
@ -118,7 +118,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
for i = 0, 15 do for i = 0, 15 do
local c = 2 ^ i local c = 2 ^ i
tPalette[c] = { parent.getPaletteColour( c ) } tPalette[c] = { parent.getPaletteColour(c) }
end end
end end
@ -126,45 +126,45 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
local function updateCursorPos() local function updateCursorPos()
if nCursorX >= 1 and nCursorY >= 1 and if nCursorX >= 1 and nCursorY >= 1 and
nCursorX <= nWidth and nCursorY <= nHeight then nCursorX <= nWidth and nCursorY <= nHeight then
parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 ) parent.setCursorPos(nX + nCursorX - 1, nY + nCursorY - 1)
else else
parent.setCursorPos( 0, 0 ) parent.setCursorPos(0, 0)
end end
end end
local function updateCursorBlink() local function updateCursorBlink()
parent.setCursorBlink( bCursorBlink ) parent.setCursorBlink(bCursorBlink)
end end
local function updateCursorColor() local function updateCursorColor()
parent.setTextColor( nTextColor ) parent.setTextColor(nTextColor)
end end
local function redrawLine( n ) local function redrawLine(n)
local tLine = tLines[ n ] local tLine = tLines[n]
parent.setCursorPos( nX, nY + n - 1 ) parent.setCursorPos(nX, nY + n - 1)
parent.blit( tLine.text, tLine.textColor, tLine.backgroundColor ) parent.blit(tLine.text, tLine.textColor, tLine.backgroundColor)
end end
local function redraw() local function redraw()
for n = 1, nHeight do for n = 1, nHeight do
redrawLine( n ) redrawLine(n)
end end
end end
local function updatePalette() local function updatePalette()
for k, v in pairs( tPalette ) do for k, v in pairs(tPalette) do
parent.setPaletteColour( k, v[1], v[2], v[3] ) parent.setPaletteColour(k, v[1], v[2], v[3])
end end
end end
local function internalBlit( sText, sTextColor, sBackgroundColor ) local function internalBlit(sText, sTextColor, sBackgroundColor)
local nStart = nCursorX local nStart = nCursorX
local nEnd = nStart + #sText - 1 local nEnd = nStart + #sText - 1
if nCursorY >= 1 and nCursorY <= nHeight then if nCursorY >= 1 and nCursorY <= nHeight then
if nStart <= nWidth and nEnd >= 1 then if nStart <= nWidth and nEnd >= 1 then
-- Modify line -- Modify line
local tLine = tLines[ nCursorY ] local tLine = tLines[nCursorY]
if nStart == 1 and nEnd == nWidth then if nStart == 1 and nEnd == nWidth then
tLine.text = sText tLine.text = sText
tLine.textColor = sTextColor tLine.textColor = sTextColor
@ -174,14 +174,14 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
if nStart < 1 then if nStart < 1 then
local nClipStart = 1 - nStart + 1 local nClipStart = 1 - nStart + 1
local nClipEnd = nWidth - nStart + 1 local nClipEnd = nWidth - nStart + 1
sClippedText = string_sub( sText, nClipStart, nClipEnd ) sClippedText = string_sub(sText, nClipStart, nClipEnd)
sClippedTextColor = string_sub( sTextColor, nClipStart, nClipEnd ) sClippedTextColor = string_sub(sTextColor, nClipStart, nClipEnd)
sClippedBackgroundColor = string_sub( sBackgroundColor, nClipStart, nClipEnd ) sClippedBackgroundColor = string_sub(sBackgroundColor, nClipStart, nClipEnd)
elseif nEnd > nWidth then elseif nEnd > nWidth then
local nClipEnd = nWidth - nStart + 1 local nClipEnd = nWidth - nStart + 1
sClippedText = string_sub( sText, 1, nClipEnd ) sClippedText = string_sub(sText, 1, nClipEnd)
sClippedTextColor = string_sub( sTextColor, 1, nClipEnd ) sClippedTextColor = string_sub(sTextColor, 1, nClipEnd)
sClippedBackgroundColor = string_sub( sBackgroundColor, 1, nClipEnd ) sClippedBackgroundColor = string_sub(sBackgroundColor, 1, nClipEnd)
else else
sClippedText = sText sClippedText = sText
sClippedTextColor = sTextColor sClippedTextColor = sTextColor
@ -194,9 +194,9 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
local sNewText, sNewTextColor, sNewBackgroundColor local sNewText, sNewTextColor, sNewBackgroundColor
if nStart > 1 then if nStart > 1 then
local nOldEnd = nStart - 1 local nOldEnd = nStart - 1
sNewText = string_sub( sOldText, 1, nOldEnd ) .. sClippedText sNewText = string_sub(sOldText, 1, nOldEnd) .. sClippedText
sNewTextColor = string_sub( sOldTextColor, 1, nOldEnd ) .. sClippedTextColor sNewTextColor = string_sub(sOldTextColor, 1, nOldEnd) .. sClippedTextColor
sNewBackgroundColor = string_sub( sOldBackgroundColor, 1, nOldEnd ) .. sClippedBackgroundColor sNewBackgroundColor = string_sub(sOldBackgroundColor, 1, nOldEnd) .. sClippedBackgroundColor
else else
sNewText = sClippedText sNewText = sClippedText
sNewTextColor = sClippedTextColor sNewTextColor = sClippedTextColor
@ -204,9 +204,9 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end end
if nEnd < nWidth then if nEnd < nWidth then
local nOldStart = nEnd + 1 local nOldStart = nEnd + 1
sNewText = sNewText .. string_sub( sOldText, nOldStart, nWidth ) sNewText = sNewText .. string_sub(sOldText, nOldStart, nWidth)
sNewTextColor = sNewTextColor .. string_sub( sOldTextColor, nOldStart, nWidth ) sNewTextColor = sNewTextColor .. string_sub(sOldTextColor, nOldStart, nWidth)
sNewBackgroundColor = sNewBackgroundColor .. string_sub( sOldBackgroundColor, nOldStart, nWidth ) sNewBackgroundColor = sNewBackgroundColor .. string_sub(sOldBackgroundColor, nOldStart, nWidth)
end end
tLine.text = sNewText tLine.text = sNewText
@ -216,7 +216,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
-- Redraw line -- Redraw line
if bVisible then if bVisible then
redrawLine( nCursorY ) redrawLine(nCursorY)
end end
end end
end end
@ -234,25 +234,25 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
-- @type Window -- @type Window
local window = {} local window = {}
function window.write( sText ) function window.write(sText)
sText = tostring( sText ) sText = tostring(sText)
internalBlit( sText, string_rep( tHex[ nTextColor ], #sText ), string_rep( tHex[ nBackgroundColor ], #sText ) ) internalBlit(sText, string_rep(tHex[nTextColor], #sText), string_rep(tHex[nBackgroundColor], #sText))
end end
function window.blit( sText, sTextColor, sBackgroundColor ) function window.blit(sText, sTextColor, sBackgroundColor)
if type(sText) ~= "string" then expect(1, sText, "string") end if type(sText) ~= "string" then expect(1, sText, "string") end
if type(sTextColor) ~= "string" then expect(2, sTextColor, "string") end if type(sTextColor) ~= "string" then expect(2, sTextColor, "string") end
if type(sBackgroundColor) ~= "string" then expect(3, sBackgroundColor, "string") end if type(sBackgroundColor) ~= "string" then expect(3, sBackgroundColor, "string") end
if #sTextColor ~= #sText or #sBackgroundColor ~= #sText then if #sTextColor ~= #sText or #sBackgroundColor ~= #sText then
error( "Arguments must be the same length", 2 ) error("Arguments must be the same length", 2)
end end
internalBlit( sText, sTextColor, sBackgroundColor ) internalBlit(sText, sTextColor, sBackgroundColor)
end end
function window.clear() function window.clear()
local sEmptyText = sEmptySpaceLine local sEmptyText = sEmptySpaceLine
local sEmptyTextColor = tEmptyColorLines[ nTextColor ] local sEmptyTextColor = tEmptyColorLines[nTextColor]
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
for y = 1, nHeight do for y = 1, nHeight do
tLines[y] = { tLines[y] = {
text = sEmptyText, text = sEmptyText,
@ -270,15 +270,15 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
function window.clearLine() function window.clearLine()
if nCursorY >= 1 and nCursorY <= nHeight then if nCursorY >= 1 and nCursorY <= nHeight then
local sEmptyText = sEmptySpaceLine local sEmptyText = sEmptySpaceLine
local sEmptyTextColor = tEmptyColorLines[ nTextColor ] local sEmptyTextColor = tEmptyColorLines[nTextColor]
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
tLines[ nCursorY ] = { tLines[nCursorY] = {
text = sEmptyText, text = sEmptyText,
textColor = sEmptyTextColor, textColor = sEmptyTextColor,
backgroundColor = sEmptyBackgroundColor, backgroundColor = sEmptyBackgroundColor,
} }
if bVisible then if bVisible then
redrawLine( nCursorY ) redrawLine(nCursorY)
updateCursorColor() updateCursorColor()
updateCursorPos() updateCursorPos()
end end
@ -289,17 +289,17 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
return nCursorX, nCursorY return nCursorX, nCursorY
end end
function window.setCursorPos( x, y ) function window.setCursorPos(x, y)
if type(x) ~= "number" then expect(1, x, "number") end if type(x) ~= "number" then expect(1, x, "number") end
if type(y) ~= "number" then expect(2, y, "number") end if type(y) ~= "number" then expect(2, y, "number") end
nCursorX = math.floor( x ) nCursorX = math.floor(x)
nCursorY = math.floor( y ) nCursorY = math.floor(y)
if bVisible then if bVisible then
updateCursorPos() updateCursorPos()
end end
end end
function window.setCursorBlink( blink ) function window.setCursorBlink(blink)
if type(blink) ~= "boolean" then expect(1, blink, "boolean") end if type(blink) ~= "boolean" then expect(1, blink, "boolean") end
bCursorBlink = blink bCursorBlink = blink
if bVisible then if bVisible then
@ -323,10 +323,10 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
return isColor() return isColor()
end end
local function setTextColor( color ) local function setTextColor(color)
if type(color) ~= "number" then expect(1, color, "number") end if type(color) ~= "number" then expect(1, color, "number") end
if tHex[color] == nil then if tHex[color] == nil then
error( "Invalid color (got " .. color .. ")" , 2 ) error("Invalid color (got " .. color .. ")" , 2)
end end
nTextColor = color nTextColor = color
@ -338,50 +338,50 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
window.setTextColor = setTextColor window.setTextColor = setTextColor
window.setTextColour = setTextColor window.setTextColour = setTextColor
function window.setPaletteColour( colour, r, g, b ) function window.setPaletteColour(colour, r, g, b)
if type(colour) ~= "number" then expect(1, colour, "number") end if type(colour) ~= "number" then expect(1, colour, "number") end
if tHex[colour] == nil then if tHex[colour] == nil then
error( "Invalid color (got " .. colour .. ")" , 2 ) error("Invalid color (got " .. colour .. ")" , 2)
end end
local tCol local tCol
if type(r) == "number" and g == nil and b == nil then if type(r) == "number" and g == nil and b == nil then
tCol = { colours.unpackRGB( r ) } tCol = { colours.unpackRGB(r) }
tPalette[ colour ] = tCol tPalette[colour] = tCol
else else
if type(r) ~= "number" then expect(2, r, "number") end if type(r) ~= "number" then expect(2, r, "number") end
if type(g) ~= "number" then expect(3, g, "number") end if type(g) ~= "number" then expect(3, g, "number") end
if type(b) ~= "number" then expect(4, b, "number") end if type(b) ~= "number" then expect(4, b, "number") end
tCol = tPalette[ colour ] tCol = tPalette[colour]
tCol[1] = r tCol[1] = r
tCol[2] = g tCol[2] = g
tCol[3] = b tCol[3] = b
end end
if bVisible then if bVisible then
return parent.setPaletteColour( colour, tCol[1], tCol[2], tCol[3] ) return parent.setPaletteColour(colour, tCol[1], tCol[2], tCol[3])
end end
end end
window.setPaletteColor = window.setPaletteColour window.setPaletteColor = window.setPaletteColour
function window.getPaletteColour( colour ) function window.getPaletteColour(colour)
if type(colour) ~= "number" then expect(1, colour, "number") end if type(colour) ~= "number" then expect(1, colour, "number") end
if tHex[colour] == nil then if tHex[colour] == nil then
error( "Invalid color (got " .. colour .. ")" , 2 ) error("Invalid color (got " .. colour .. ")" , 2)
end end
local tCol = tPalette[ colour ] local tCol = tPalette[colour]
return tCol[1], tCol[2], tCol[3] return tCol[1], tCol[2], tCol[3]
end end
window.getPaletteColor = window.getPaletteColour window.getPaletteColor = window.getPaletteColour
local function setBackgroundColor( color ) local function setBackgroundColor(color)
if type(color) ~= "number" then expect(1, color, "number") end if type(color) ~= "number" then expect(1, color, "number") end
if tHex[color] == nil then if tHex[color] == nil then
error( "Invalid color (got " .. color .. ")", 2 ) error("Invalid color (got " .. color .. ")", 2)
end end
nBackgroundColor = color nBackgroundColor = color
end end
@ -393,13 +393,13 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
return nWidth, nHeight return nWidth, nHeight
end end
function window.scroll( n ) function window.scroll(n)
if type(n) ~= "number" then expect(1, n, "number") end if type(n) ~= "number" then expect(1, n, "number") end
if n ~= 0 then if n ~= 0 then
local tNewLines = {} local tNewLines = {}
local sEmptyText = sEmptySpaceLine local sEmptyText = sEmptySpaceLine
local sEmptyTextColor = tEmptyColorLines[ nTextColor ] local sEmptyTextColor = tEmptyColorLines[nTextColor]
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
for newY = 1, nHeight do for newY = 1, nHeight do
local y = newY + n local y = newY + n
if y >= 1 and y <= nHeight then if y >= 1 and y <= nHeight then
@ -448,7 +448,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end end
-- Other functions -- Other functions
function window.setVisible( bVis ) function window.setVisible(bVis)
if type(bVis) ~= "boolean" then expect(1, bVis, "boolean") end if type(bVis) ~= "boolean" then expect(1, bVis, "boolean") end
if bVisible ~= bVis then if bVisible ~= bVis then
bVisible = bVis bVisible = bVis
@ -480,7 +480,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
return nX, nY return nX, nY
end end
function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight, newParent ) function window.reposition(nNewX, nNewY, nNewWidth, nNewHeight, newParent)
if type(nNewX) ~= "number" then expect(1, nNewX, "number") end if type(nNewX) ~= "number" then expect(1, nNewX, "number") end
if type(nNewY) ~= "number" then expect(2, nNewY, "number") end if type(nNewY) ~= "number" then expect(2, nNewY, "number") end
if nNewWidth ~= nil or nNewHeight ~= nil then if nNewWidth ~= nil or nNewHeight ~= nil then
@ -496,10 +496,10 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
if nNewWidth and nNewHeight then if nNewWidth and nNewHeight then
local tNewLines = {} local tNewLines = {}
createEmptyLines( nNewWidth ) createEmptyLines(nNewWidth)
local sEmptyText = sEmptySpaceLine local sEmptyText = sEmptySpaceLine
local sEmptyTextColor = tEmptyColorLines[ nTextColor ] local sEmptyTextColor = tEmptyColorLines[nTextColor]
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ] local sEmptyBackgroundColor = tEmptyColorLines[nBackgroundColor]
for y = 1, nNewHeight do for y = 1, nNewHeight do
if y > nHeight then if y > nHeight then
tNewLines[y] = { tNewLines[y] = {
@ -513,15 +513,15 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
tNewLines[y] = tOldLine tNewLines[y] = tOldLine
elseif nNewWidth < nWidth then elseif nNewWidth < nWidth then
tNewLines[y] = { tNewLines[y] = {
text = string_sub( tOldLine.text, 1, nNewWidth ), text = string_sub(tOldLine.text, 1, nNewWidth),
textColor = string_sub( tOldLine.textColor, 1, nNewWidth ), textColor = string_sub(tOldLine.textColor, 1, nNewWidth),
backgroundColor = string_sub( tOldLine.backgroundColor, 1, nNewWidth ), backgroundColor = string_sub(tOldLine.backgroundColor, 1, nNewWidth),
} }
else else
tNewLines[y] = { tNewLines[y] = {
text = tOldLine.text .. string_sub( sEmptyText, nWidth + 1, nNewWidth ), text = tOldLine.text .. string_sub(sEmptyText, nWidth + 1, nNewWidth),
textColor = tOldLine.textColor .. string_sub( sEmptyTextColor, nWidth + 1, nNewWidth ), textColor = tOldLine.textColor .. string_sub(sEmptyTextColor, nWidth + 1, nNewWidth),
backgroundColor = tOldLine.backgroundColor .. string_sub( sEmptyBackgroundColor, nWidth + 1, nNewWidth ), backgroundColor = tOldLine.backgroundColor .. string_sub(sEmptyBackgroundColor, nWidth + 1, nNewWidth),
} }
end end
end end

View File

@ -37,9 +37,9 @@ local function expect(index, value, ...)
end end
if name then if name then
error( ("bad argument #%d to '%s' (expected %s, got %s)"):format(index, name, type_names, t), 3 ) error(("bad argument #%d to '%s' (expected %s, got %s)"):format(index, name, type_names, t), 3)
else else
error( ("bad argument #%d (expected %s, got %s)"):format(index, type_names, t), 3 ) error(("bad argument #%d (expected %s, got %s)"):format(index, type_names, t), 3)
end end
end end

View File

@ -320,11 +320,11 @@ end
Doc.__tostring = render --- @local Doc.__tostring = render --- @local
local keywords = { local keywords = {
[ "and" ] = true, [ "break" ] = true, [ "do" ] = true, [ "else" ] = true, ["and"] = true, ["break"] = true, ["do"] = true, ["else"] = true,
[ "elseif" ] = true, [ "end" ] = true, [ "false" ] = true, [ "for" ] = true, ["elseif"] = true, ["end"] = true, ["false"] = true, ["for"] = true,
[ "function" ] = true, [ "if" ] = true, [ "in" ] = true, [ "local" ] = true, ["function"] = true, ["if"] = true, ["in"] = true, ["local"] = true,
[ "nil" ] = true, [ "not" ] = true, [ "or" ] = true, [ "repeat" ] = true, [ "return" ] = true, ["nil"] = true, ["not"] = true, ["or"] = true, ["repeat"] = true, ["return"] = true,
[ "then" ] = true, [ "true" ] = true, [ "until" ] = true, [ "while" ] = true, ["then"] = true, ["true"] = true, ["until"] = true, ["while"] = true,
} }
local comma = text(",") local comma = text(",")

View File

@ -1,12 +1,12 @@
if not shell.openTab then if not shell.openTab then
printError( "Requires multishell" ) printError("Requires multishell")
return return
end end
local tArgs = { ... } local tArgs = { ... }
if #tArgs > 0 then if #tArgs > 0 then
shell.openTab( table.unpack( tArgs ) ) shell.openTab(table.unpack(tArgs))
else else
shell.openTab( "shell" ) shell.openTab("shell")
end end

View File

@ -1,18 +1,18 @@
if not shell.openTab then if not shell.openTab then
printError( "Requires multishell" ) printError("Requires multishell")
return return
end end
local tArgs = { ... } local tArgs = { ... }
if #tArgs > 0 then if #tArgs > 0 then
local nTask = shell.openTab( table.unpack( tArgs ) ) local nTask = shell.openTab(table.unpack(tArgs))
if nTask then if nTask then
shell.switchTab( nTask ) shell.switchTab(nTask)
end end
else else
local nTask = shell.openTab( "shell" ) local nTask = shell.openTab("shell")
if nTask then if nTask then
shell.switchTab( nTask ) shell.switchTab(nTask)
end end
end end

View File

@ -12,84 +12,84 @@ local bWindowsResized = false
local nScrollPos = 1 local nScrollPos = 1
local bScrollRight = false local bScrollRight = false
local function selectProcess( n ) local function selectProcess(n)
if nCurrentProcess ~= n then if nCurrentProcess ~= n then
if nCurrentProcess then if nCurrentProcess then
local tOldProcess = tProcesses[ nCurrentProcess ] local tOldProcess = tProcesses[nCurrentProcess]
tOldProcess.window.setVisible( false ) tOldProcess.window.setVisible(false)
end end
nCurrentProcess = n nCurrentProcess = n
if nCurrentProcess then if nCurrentProcess then
local tNewProcess = tProcesses[ nCurrentProcess ] local tNewProcess = tProcesses[nCurrentProcess]
tNewProcess.window.setVisible( true ) tNewProcess.window.setVisible(true)
tNewProcess.bInteracted = true tNewProcess.bInteracted = true
end end
end end
end end
local function setProcessTitle( n, sTitle ) local function setProcessTitle(n, sTitle)
tProcesses[ n ].sTitle = sTitle tProcesses[n].sTitle = sTitle
end end
local function resumeProcess( nProcess, sEvent, ... ) local function resumeProcess(nProcess, sEvent, ...)
local tProcess = tProcesses[ nProcess ] local tProcess = tProcesses[nProcess]
local sFilter = tProcess.sFilter local sFilter = tProcess.sFilter
if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then
local nPreviousProcess = nRunningProcess local nPreviousProcess = nRunningProcess
nRunningProcess = nProcess nRunningProcess = nProcess
term.redirect( tProcess.terminal ) term.redirect(tProcess.terminal)
local ok, result = coroutine.resume( tProcess.co, sEvent, ... ) local ok, result = coroutine.resume(tProcess.co, sEvent, ...)
tProcess.terminal = term.current() tProcess.terminal = term.current()
if ok then if ok then
tProcess.sFilter = result tProcess.sFilter = result
else else
printError( result ) printError(result)
end end
nRunningProcess = nPreviousProcess nRunningProcess = nPreviousProcess
end end
end end
local function launchProcess( bFocus, tProgramEnv, sProgramPath, ... ) local function launchProcess(bFocus, tProgramEnv, sProgramPath, ...)
local tProgramArgs = table.pack( ... ) local tProgramArgs = table.pack(...)
local nProcess = #tProcesses + 1 local nProcess = #tProcesses + 1
local tProcess = {} local tProcess = {}
tProcess.sTitle = fs.getName( sProgramPath ) tProcess.sTitle = fs.getName(sProgramPath)
if bShowMenu then if bShowMenu then
tProcess.window = window.create( parentTerm, 1, 2, w, h - 1, false ) tProcess.window = window.create(parentTerm, 1, 2, w, h - 1, false)
else else
tProcess.window = window.create( parentTerm, 1, 1, w, h, false ) tProcess.window = window.create(parentTerm, 1, 1, w, h, false)
end end
tProcess.co = coroutine.create( function() tProcess.co = coroutine.create(function()
os.run( tProgramEnv, sProgramPath, table.unpack( tProgramArgs, 1, tProgramArgs.n ) ) os.run(tProgramEnv, sProgramPath, table.unpack(tProgramArgs, 1, tProgramArgs.n))
if not tProcess.bInteracted then if not tProcess.bInteracted then
term.setCursorBlink( false ) term.setCursorBlink(false)
print( "Press any key to continue" ) print("Press any key to continue")
os.pullEvent( "char" ) os.pullEvent("char")
end end
end ) end)
tProcess.sFilter = nil tProcess.sFilter = nil
tProcess.terminal = tProcess.window tProcess.terminal = tProcess.window
tProcess.bInteracted = false tProcess.bInteracted = false
tProcesses[ nProcess ] = tProcess tProcesses[nProcess] = tProcess
if bFocus then if bFocus then
selectProcess( nProcess ) selectProcess(nProcess)
end end
resumeProcess( nProcess ) resumeProcess(nProcess)
return nProcess return nProcess
end end
local function cullProcess( nProcess ) local function cullProcess(nProcess)
local tProcess = tProcesses[ nProcess ] local tProcess = tProcesses[nProcess]
if coroutine.status( tProcess.co ) == "dead" then if coroutine.status(tProcess.co) == "dead" then
if nCurrentProcess == nProcess then if nCurrentProcess == nProcess then
selectProcess( nil ) selectProcess(nil)
end end
table.remove( tProcesses, nProcess ) table.remove(tProcesses, nProcess)
if nCurrentProcess == nil then if nCurrentProcess == nil then
if nProcess > 1 then if nProcess > 1 then
selectProcess( nProcess - 1 ) selectProcess(nProcess - 1)
elseif #tProcesses > 0 then elseif #tProcesses > 0 then
selectProcess( 1 ) selectProcess(1)
end end
end end
if nScrollPos ~= 1 then if nScrollPos ~= 1 then
@ -103,7 +103,7 @@ end
local function cullProcesses() local function cullProcesses()
local culled = false local culled = false
for n = #tProcesses, 1, -1 do for n = #tProcesses, 1, -1 do
culled = culled or cullProcess( n ) culled = culled or cullProcess(n)
end end
return culled return culled
end end
@ -121,40 +121,40 @@ end
local function redrawMenu() local function redrawMenu()
if bShowMenu then if bShowMenu then
-- Draw menu -- Draw menu
parentTerm.setCursorPos( 1, 1 ) parentTerm.setCursorPos(1, 1)
parentTerm.setBackgroundColor( menuOtherBgColor ) parentTerm.setBackgroundColor(menuOtherBgColor)
parentTerm.clearLine() parentTerm.clearLine()
local nCharCount = 0 local nCharCount = 0
local nSize = parentTerm.getSize() local nSize = parentTerm.getSize()
if nScrollPos ~= 1 then if nScrollPos ~= 1 then
parentTerm.setTextColor( menuOtherTextColor ) parentTerm.setTextColor(menuOtherTextColor)
parentTerm.setBackgroundColor( menuOtherBgColor ) parentTerm.setBackgroundColor(menuOtherBgColor)
parentTerm.write( "<" ) parentTerm.write("<")
nCharCount = 1 nCharCount = 1
end end
for n = nScrollPos, #tProcesses do for n = nScrollPos, #tProcesses do
if n == nCurrentProcess then if n == nCurrentProcess then
parentTerm.setTextColor( menuMainTextColor ) parentTerm.setTextColor(menuMainTextColor)
parentTerm.setBackgroundColor( menuMainBgColor ) parentTerm.setBackgroundColor(menuMainBgColor)
else else
parentTerm.setTextColor( menuOtherTextColor ) parentTerm.setTextColor(menuOtherTextColor)
parentTerm.setBackgroundColor( menuOtherBgColor ) parentTerm.setBackgroundColor(menuOtherBgColor)
end end
parentTerm.write( " " .. tProcesses[n].sTitle .. " " ) parentTerm.write(" " .. tProcesses[n].sTitle .. " ")
nCharCount = nCharCount + #tProcesses[n].sTitle + 2 nCharCount = nCharCount + #tProcesses[n].sTitle + 2
end end
if nCharCount > nSize then if nCharCount > nSize then
parentTerm.setTextColor( menuOtherTextColor ) parentTerm.setTextColor(menuOtherTextColor)
parentTerm.setBackgroundColor( menuOtherBgColor ) parentTerm.setBackgroundColor(menuOtherBgColor)
parentTerm.setCursorPos( nSize, 1 ) parentTerm.setCursorPos(nSize, 1)
parentTerm.write( ">" ) parentTerm.write(">")
bScrollRight = true bScrollRight = true
else else
bScrollRight = false bScrollRight = false
end end
-- Put the cursor back where it should be -- Put the cursor back where it should be
local tProcess = tProcesses[ nCurrentProcess ] local tProcess = tProcesses[nCurrentProcess]
if tProcess then if tProcess then
tProcess.window.restoreCursor() tProcess.window.restoreCursor()
end end
@ -174,15 +174,15 @@ local function resizeWindows()
local tProcess = tProcesses[n] local tProcess = tProcesses[n]
local x, y = tProcess.window.getCursorPos() local x, y = tProcess.window.getCursorPos()
if y > windowHeight then if y > windowHeight then
tProcess.window.scroll( y - windowHeight ) tProcess.window.scroll(y - windowHeight)
tProcess.window.setCursorPos( x, windowHeight ) tProcess.window.setCursorPos(x, windowHeight)
end end
tProcess.window.reposition( 1, windowY, w, windowHeight ) tProcess.window.reposition(1, windowY, w, windowHeight)
end end
bWindowsResized = true bWindowsResized = true
end end
local function setMenuVisible( bVis ) local function setMenuVisible(bVis)
if bShowMenu ~= bVis then if bShowMenu ~= bVis then
bShowMenu = bVis bShowMenu = bVis
resizeWindows() resizeWindows()
@ -196,17 +196,17 @@ function multishell.getFocus()
return nCurrentProcess return nCurrentProcess
end end
function multishell.setFocus( n ) function multishell.setFocus(n)
expect(1, n, "number") expect(1, n, "number")
if n >= 1 and n <= #tProcesses then if n >= 1 and n <= #tProcesses then
selectProcess( n ) selectProcess(n)
redrawMenu() redrawMenu()
return true return true
end end
return false return false
end end
function multishell.getTitle( n ) function multishell.getTitle(n)
expect(1, n, "number") expect(1, n, "number")
if n >= 1 and n <= #tProcesses then if n >= 1 and n <= #tProcesses then
return tProcesses[n].sTitle return tProcesses[n].sTitle
@ -214,11 +214,11 @@ function multishell.getTitle( n )
return nil return nil
end end
function multishell.setTitle( n, sTitle ) function multishell.setTitle(n, sTitle)
expect(1, n, "number") expect(1, n, "number")
expect(2, sTitle, "string") expect(2, sTitle, "string")
if n >= 1 and n <= #tProcesses then if n >= 1 and n <= #tProcesses then
setProcessTitle( n, sTitle ) setProcessTitle(n, sTitle)
redrawMenu() redrawMenu()
end end
end end
@ -227,14 +227,14 @@ function multishell.getCurrent()
return nRunningProcess return nRunningProcess
end end
function multishell.launch( tProgramEnv, sProgramPath, ... ) function multishell.launch(tProgramEnv, sProgramPath, ...)
expect(1, tProgramEnv, "table") expect(1, tProgramEnv, "table")
expect(2, sProgramPath, "string") expect(2, sProgramPath, "string")
local previousTerm = term.current() local previousTerm = term.current()
setMenuVisible( #tProcesses + 1 >= 2 ) setMenuVisible(#tProcesses + 1 >= 2)
local nResult = launchProcess( false, tProgramEnv, sProgramPath, ... ) local nResult = launchProcess(false, tProgramEnv, sProgramPath, ...)
redrawMenu() redrawMenu()
term.redirect( previousTerm ) term.redirect(previousTerm)
return nResult return nResult
end end
@ -244,16 +244,16 @@ end
-- Begin -- Begin
parentTerm.clear() parentTerm.clear()
setMenuVisible( false ) setMenuVisible(false)
launchProcess( true, { launchProcess(true, {
["shell"] = shell, ["shell"] = shell,
["multishell"] = multishell, ["multishell"] = multishell,
}, "/rom/programs/shell.lua" ) }, "/rom/programs/shell.lua")
-- Run processes -- Run processes
while #tProcesses > 0 do while #tProcesses > 0 do
-- Get the event -- Get the event
local tEventData = table.pack( os.pullEventRaw() ) local tEventData = table.pack(os.pullEventRaw())
local sEvent = tEventData[1] local sEvent = tEventData[1]
if sEvent == "term_resize" then if sEvent == "term_resize" then
-- Resize event -- Resize event
@ -264,9 +264,9 @@ while #tProcesses > 0 do
elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then
-- Keyboard event -- Keyboard event
-- Passthrough to current process -- Passthrough to current process
resumeProcess( nCurrentProcess, table.unpack( tEventData, 1, tEventData.n ) ) resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n))
if cullProcess( nCurrentProcess ) then if cullProcess(nCurrentProcess) then
setMenuVisible( #tProcesses >= 2 ) setMenuVisible(#tProcesses >= 2)
redrawMenu() redrawMenu()
end end
@ -289,7 +289,7 @@ while #tProcesses > 0 do
for n = nScrollPos, #tProcesses do for n = nScrollPos, #tProcesses do
local tabEnd = tabStart + #tProcesses[n].sTitle + 1 local tabEnd = tabStart + #tProcesses[n].sTitle + 1
if x >= tabStart and x <= tabEnd then if x >= tabStart and x <= tabEnd then
selectProcess( n ) selectProcess(n)
redrawMenu() redrawMenu()
break break
end end
@ -298,9 +298,9 @@ while #tProcesses > 0 do
end end
else else
-- Passthrough to current process -- Passthrough to current process
resumeProcess( nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y ) resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y)
if cullProcess( nCurrentProcess ) then if cullProcess(nCurrentProcess) then
setMenuVisible( #tProcesses >= 2 ) setMenuVisible(#tProcesses >= 2)
redrawMenu() redrawMenu()
end end
end end
@ -318,9 +318,9 @@ while #tProcesses > 0 do
end end
elseif not (bShowMenu and y == 1) then elseif not (bShowMenu and y == 1) then
-- Passthrough to current process -- Passthrough to current process
resumeProcess( nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y ) resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y)
if cullProcess( nCurrentProcess ) then if cullProcess(nCurrentProcess) then
setMenuVisible( #tProcesses >= 2 ) setMenuVisible(#tProcesses >= 2)
redrawMenu() redrawMenu()
end end
end end
@ -330,10 +330,10 @@ while #tProcesses > 0 do
-- Passthrough to all processes -- Passthrough to all processes
local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
for n = 1, nLimit do for n = 1, nLimit do
resumeProcess( n, table.unpack( tEventData, 1, tEventData.n ) ) resumeProcess(n, table.unpack(tEventData, 1, tEventData.n))
end end
if cullProcesses() then if cullProcesses() then
setMenuVisible( #tProcesses >= 2 ) setMenuVisible(#tProcesses >= 2)
redrawMenu() redrawMenu()
end end
end end
@ -342,15 +342,15 @@ while #tProcesses > 0 do
-- Pass term_resize to all processes -- Pass term_resize to all processes
local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
for n = 1, nLimit do for n = 1, nLimit do
resumeProcess( n, "term_resize" ) resumeProcess(n, "term_resize")
end end
bWindowsResized = false bWindowsResized = false
if cullProcesses() then if cullProcesses() then
setMenuVisible( #tProcesses >= 2 ) setMenuVisible(#tProcesses >= 2)
redrawMenu() redrawMenu()
end end
end end
end end
-- Shutdown -- Shutdown
term.redirect( parentTerm ) term.redirect(parentTerm)

View File

@ -1,7 +1,7 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs > 2 then if #tArgs > 2 then
print( "Usage: alias <alias> <program>" ) print("Usage: alias <alias> <program>")
return return
end end
@ -10,17 +10,17 @@ local sProgram = tArgs[2]
if sAlias and sProgram then if sAlias and sProgram then
-- Set alias -- Set alias
shell.setAlias( sAlias, sProgram ) shell.setAlias(sAlias, sProgram)
elseif sAlias then elseif sAlias then
-- Clear alias -- Clear alias
shell.clearAlias( sAlias ) shell.clearAlias(sAlias)
else else
-- List aliases -- List aliases
local tAliases = shell.aliases() local tAliases = shell.aliases()
local tList = {} local tList = {}
for sAlias, sCommand in pairs( tAliases ) do for sAlias, sCommand in pairs(tAliases) do
table.insert( tList, sAlias .. ":" .. sCommand ) table.insert(tList, sAlias .. ":" .. sCommand)
end end
table.sort( tList ) table.sort(tList)
textutils.pagedTabulate( tList ) textutils.pagedTabulate(tList)
end end

View File

@ -1,15 +1,15 @@
local tApis = {} local tApis = {}
for k, v in pairs( _G ) do for k, v in pairs(_G) do
if type(k) == "string" and type(v) == "table" and k ~= "_G" then if type(k) == "string" and type(v) == "table" and k ~= "_G" then
table.insert( tApis, k ) table.insert(tApis, k)
end end
end end
table.insert( tApis, "shell" ) table.insert(tApis, "shell")
table.insert( tApis, "package" ) table.insert(tApis, "package")
if multishell then if multishell then
table.insert( tApis, "multishell" ) table.insert(tApis, "multishell")
end end
table.sort( tApis ) table.sort(tApis)
textutils.pagedTabulate( tApis ) textutils.pagedTabulate(tApis)

View File

@ -1,14 +1,14 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 1 then if #tArgs < 1 then
print( "Usage: cd <path>" ) print("Usage: cd <path>")
return return
end end
local sNewDir = shell.resolve( tArgs[1] ) local sNewDir = shell.resolve(tArgs[1])
if fs.isDir( sNewDir ) then if fs.isDir(sNewDir) then
shell.setDir( sNewDir ) shell.setDir(sNewDir)
else else
print( "Not a directory" ) print("Not a directory")
return return
end end

View File

@ -1,2 +1,2 @@
term.clear() term.clear()
term.setCursorPos( 1, 1 ) term.setCursorPos(1, 1)

View File

@ -1,16 +1,16 @@
if not commands then if not commands then
printError( "Requires a Command Computer." ) printError("Requires a Command Computer.")
return return
end end
local tCommands = commands.list() local tCommands = commands.list()
table.sort( tCommands ) table.sort(tCommands)
if term.isColor() then if term.isColor() then
term.setTextColor( colors.green ) term.setTextColor(colors.green)
end end
print( "Available commands:" ) print("Available commands:")
term.setTextColor( colors.white ) term.setTextColor(colors.white)
textutils.pagedTabulate( tCommands ) textutils.pagedTabulate(tCommands)

View File

@ -1,40 +1,40 @@
local tArgs = { ... } local tArgs = { ... }
if not commands then if not commands then
printError( "Requires a Command Computer." ) printError("Requires a Command Computer.")
return return
end end
if #tArgs == 0 then if #tArgs == 0 then
printError( "Usage: exec <command>" ) printError("Usage: exec <command>")
return return
end end
local function printSuccess( text ) local function printSuccess(text)
if term.isColor() then if term.isColor() then
term.setTextColor( colors.green ) term.setTextColor(colors.green)
end end
print( text ) print(text)
term.setTextColor( colors.white ) term.setTextColor(colors.white)
end end
local sCommand = string.lower( tArgs[1] ) local sCommand = string.lower(tArgs[1])
for n = 2, #tArgs do for n = 2, #tArgs do
sCommand = sCommand .. " " .. tArgs[n] sCommand = sCommand .. " " .. tArgs[n]
end end
local bResult, tOutput = commands.exec( sCommand ) local bResult, tOutput = commands.exec(sCommand)
if bResult then if bResult then
printSuccess( "Success" ) printSuccess("Success")
if #tOutput > 0 then if #tOutput > 0 then
for n = 1, #tOutput do for n = 1, #tOutput do
print( tOutput[n] ) print(tOutput[n])
end end
end end
else else
printError( "Failed" ) printError("Failed")
if #tOutput > 0 then if #tOutput > 0 then
for n = 1, #tOutput do for n = 1, #tOutput do
print( tOutput[n] ) print(tOutput[n])
end end
end end
end end

View File

@ -1,32 +1,32 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 2 then if #tArgs < 2 then
print( "Usage: cp <source> <destination>" ) print("Usage: cp <source> <destination>")
return return
end end
local sSource = shell.resolve( tArgs[1] ) local sSource = shell.resolve(tArgs[1])
local sDest = shell.resolve( tArgs[2] ) local sDest = shell.resolve(tArgs[2])
local tFiles = fs.find( sSource ) local tFiles = fs.find(sSource)
if #tFiles > 0 then if #tFiles > 0 then
for _, sFile in ipairs( tFiles ) do for _, sFile in ipairs(tFiles) do
if fs.isDir( sDest ) then if fs.isDir(sDest) then
fs.copy( sFile, fs.combine( sDest, fs.getName(sFile) ) ) fs.copy(sFile, fs.combine(sDest, fs.getName(sFile)))
elseif #tFiles == 1 then elseif #tFiles == 1 then
if fs.exists( sDest ) then if fs.exists(sDest) then
printError( "Destination exists" ) printError("Destination exists")
elseif fs.isReadOnly( sDest ) then elseif fs.isReadOnly(sDest) then
printError( "Destination is read-only" ) printError("Destination is read-only")
elseif fs.getFreeSpace( sDest ) < fs.getSize( sFile ) then elseif fs.getFreeSpace(sDest) < fs.getSize(sFile) then
printError( "Not enough space" ) printError("Not enough space")
else else
fs.copy( sFile, sDest ) fs.copy(sFile, sDest)
end end
else else
printError( "Cannot overwrite file multiple times" ) printError("Cannot overwrite file multiple times")
return return
end end
end end
else else
printError( "No matching files" ) printError("No matching files")
end end

View File

@ -3,19 +3,19 @@ local tArgs = { ... }
-- Get where a directory is mounted -- Get where a directory is mounted
local sPath = shell.dir() local sPath = shell.dir()
if tArgs[1] ~= nil then if tArgs[1] ~= nil then
sPath = shell.resolve( tArgs[1] ) sPath = shell.resolve(tArgs[1])
end end
if fs.exists( sPath ) then if fs.exists(sPath) then
write( fs.getDrive( sPath ) .. " (" ) write(fs.getDrive(sPath) .. " (")
local nSpace = fs.getFreeSpace( sPath ) local nSpace = fs.getFreeSpace(sPath)
if nSpace >= 1000 * 1000 then if nSpace >= 1000 * 1000 then
print( math.floor( nSpace / (100 * 1000) ) / 10 .. "MB remaining)" ) print(math.floor(nSpace / (100 * 1000)) / 10 .. "MB remaining)")
elseif nSpace >= 1000 then elseif nSpace >= 1000 then
print( math.floor( nSpace / 100 ) / 10 .. "KB remaining)" ) print(math.floor(nSpace / 100) / 10 .. "KB remaining)")
else else
print( nSpace .. "B remaining)" ) print(nSpace .. "B remaining)")
end end
else else
print( "No such path" ) print("No such path")
end end

View File

@ -1,22 +1,22 @@
-- Get file to edit -- Get file to edit
local tArgs = { ... } local tArgs = { ... }
if #tArgs == 0 then if #tArgs == 0 then
print( "Usage: edit <path>" ) print("Usage: edit <path>")
return return
end end
-- Error checking -- Error checking
local sPath = shell.resolve( tArgs[1] ) local sPath = shell.resolve(tArgs[1])
local bReadOnly = fs.isReadOnly( sPath ) local bReadOnly = fs.isReadOnly(sPath)
if fs.exists( sPath ) and fs.isDir( sPath ) then if fs.exists(sPath) and fs.isDir(sPath) then
print( "Cannot edit a directory." ) print("Cannot edit a directory.")
return return
end end
-- Create .lua files by default -- Create .lua files by default
if not fs.exists( sPath ) and not string.find( sPath, "%." ) then if not fs.exists(sPath) and not string.find(sPath, "%.") then
local sExtension = settings.get("edit.default_extension", "") local sExtension = settings.get("edit.default_extension", "")
if sExtension ~= "" and type( sExtension ) == "string" then if sExtension ~= "" and type(sExtension) == "string" then
sPath = sPath .. "." .. sExtension sPath = sPath .. "." .. sExtension
end end
end end
@ -51,59 +51,59 @@ local bMenu = false
local nMenuItem = 1 local nMenuItem = 1
local tMenuItems = {} local tMenuItems = {}
if not bReadOnly then if not bReadOnly then
table.insert( tMenuItems, "Save" ) table.insert(tMenuItems, "Save")
end end
if shell.openTab then if shell.openTab then
table.insert( tMenuItems, "Run" ) table.insert(tMenuItems, "Run")
end end
if peripheral.find( "printer" ) then if peripheral.find("printer") then
table.insert( tMenuItems, "Print" ) table.insert(tMenuItems, "Print")
end end
table.insert( tMenuItems, "Exit" ) table.insert(tMenuItems, "Exit")
local sStatus = "Press Ctrl to access menu" local sStatus = "Press Ctrl to access menu"
if #sStatus > w - 5 then if #sStatus > w - 5 then
sStatus = "Press Ctrl for menu" sStatus = "Press Ctrl for menu"
end end
local function load( _sPath ) local function load(_sPath)
tLines = {} tLines = {}
if fs.exists( _sPath ) then if fs.exists(_sPath) then
local file = io.open( _sPath, "r" ) local file = io.open(_sPath, "r")
local sLine = file:read() local sLine = file:read()
while sLine do while sLine do
table.insert( tLines, sLine ) table.insert(tLines, sLine)
sLine = file:read() sLine = file:read()
end end
file:close() file:close()
end end
if #tLines == 0 then if #tLines == 0 then
table.insert( tLines, "" ) table.insert(tLines, "")
end end
end end
local function save( _sPath ) local function save(_sPath)
-- Create intervening folder -- Create intervening folder
local sDir = _sPath:sub(1, _sPath:len() - fs.getName(_sPath):len()) local sDir = _sPath:sub(1, _sPath:len() - fs.getName(_sPath):len())
if not fs.exists( sDir ) then if not fs.exists(sDir) then
fs.makeDir( sDir ) fs.makeDir(sDir)
end end
-- Save -- Save
local file, fileerr local file, fileerr
local function innerSave() local function innerSave()
file, fileerr = fs.open( _sPath, "w" ) file, fileerr = fs.open(_sPath, "w")
if file then if file then
for _, sLine in ipairs( tLines ) do for _, sLine in ipairs(tLines) do
file.write( sLine .. "\n" ) file.write(sLine .. "\n")
end end
else else
error( "Failed to open " .. _sPath ) error("Failed to open " .. _sPath)
end end
end end
local ok, err = pcall( innerSave ) local ok, err = pcall(innerSave)
if file then if file then
file.close() file.close()
end end
@ -134,38 +134,38 @@ local tKeywords = {
["while"] = true, ["while"] = true,
} }
local function tryWrite( sLine, regex, colour ) local function tryWrite(sLine, regex, colour)
local match = string.match( sLine, regex ) local match = string.match(sLine, regex)
if match then if match then
if type(colour) == "number" then if type(colour) == "number" then
term.setTextColour( colour ) term.setTextColour(colour)
else else
term.setTextColour( colour(match) ) term.setTextColour(colour(match))
end end
term.write( match ) term.write(match)
term.setTextColour( textColour ) term.setTextColour(textColour)
return string.sub( sLine, #match + 1 ) return string.sub(sLine, #match + 1)
end end
return nil return nil
end end
local function writeHighlighted( sLine ) local function writeHighlighted(sLine)
while #sLine > 0 do while #sLine > 0 do
sLine = sLine =
tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or tryWrite(sLine, "^%-%-%[%[.-%]%]", commentColour) or
tryWrite( sLine, "^%-%-.*", commentColour ) or tryWrite(sLine, "^%-%-.*", commentColour) or
tryWrite( sLine, "^\"\"", stringColour ) or tryWrite(sLine, "^\"\"", stringColour) or
tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or tryWrite(sLine, "^\".-[^\\]\"", stringColour) or
tryWrite( sLine, "^\'\'", stringColour ) or tryWrite(sLine, "^\'\'", stringColour) or
tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or tryWrite(sLine, "^\'.-[^\\]\'", stringColour) or
tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or tryWrite(sLine, "^%[%[.-%]%]", stringColour) or
tryWrite( sLine, "^[%w_]+", function( match ) tryWrite(sLine, "^[%w_]+", function(match)
if tKeywords[ match ] then if tKeywords[match] then
return keywordColour return keywordColour
end end
return textColour return textColour
end ) or end) or
tryWrite( sLine, "^[^%w_]", textColour ) tryWrite(sLine, "^[^%w_]", textColour)
end end
end end
@ -173,14 +173,14 @@ local tCompletions
local nCompletion local nCompletion
local tCompleteEnv = _ENV local tCompleteEnv = _ENV
local function complete( sLine ) local function complete(sLine)
if settings.get( "edit.autocomplete" ) then if settings.get("edit.autocomplete") then
local nStartPos = string.find( sLine, "[a-zA-Z0-9_%.:]+$" ) local nStartPos = string.find(sLine, "[a-zA-Z0-9_%.:]+$")
if nStartPos then if nStartPos then
sLine = string.sub( sLine, nStartPos ) sLine = string.sub(sLine, nStartPos)
end end
if #sLine > 0 then if #sLine > 0 then
return textutils.complete( sLine, tCompleteEnv ) return textutils.complete(sLine, tCompleteEnv)
end end
end end
return nil return nil
@ -189,7 +189,7 @@ end
local function recomplete() local function recomplete()
local sLine = tLines[y] local sLine = tLines[y]
if not bMenu and not bReadOnly and x == #sLine + 1 then if not bMenu and not bReadOnly and x == #sLine + 1 then
tCompletions = complete( sLine ) tCompletions = complete(sLine)
if tCompletions and #tCompletions > 0 then if tCompletions and #tCompletions > 0 then
nCompletion = 1 nCompletion = 1
else else
@ -201,85 +201,85 @@ local function recomplete()
end end
end end
local function writeCompletion( sLine ) local function writeCompletion(sLine)
if nCompletion then if nCompletion then
local sCompletion = tCompletions[ nCompletion ] local sCompletion = tCompletions[nCompletion]
term.setTextColor( colours.white ) term.setTextColor(colours.white)
term.setBackgroundColor( colours.grey ) term.setBackgroundColor(colours.grey)
term.write( sCompletion ) term.write(sCompletion)
term.setTextColor( textColour ) term.setTextColor(textColour)
term.setBackgroundColor( bgColour ) term.setBackgroundColor(bgColour)
end end
end end
local function redrawText() local function redrawText()
local cursorX, cursorY = x, y local cursorX, cursorY = x, y
for y = 1, h - 1 do for y = 1, h - 1 do
term.setCursorPos( 1 - scrollX, y ) term.setCursorPos(1 - scrollX, y)
term.clearLine() term.clearLine()
local sLine = tLines[ y + scrollY ] local sLine = tLines[y + scrollY]
if sLine ~= nil then if sLine ~= nil then
writeHighlighted( sLine ) writeHighlighted(sLine)
if cursorY == y and cursorX == #sLine + 1 then if cursorY == y and cursorX == #sLine + 1 then
writeCompletion() writeCompletion()
end end
end end
end end
term.setCursorPos( x - scrollX, y - scrollY ) term.setCursorPos(x - scrollX, y - scrollY)
end end
local function redrawLine(_nY) local function redrawLine(_nY)
local sLine = tLines[_nY] local sLine = tLines[_nY]
if sLine then if sLine then
term.setCursorPos( 1 - scrollX, _nY - scrollY ) term.setCursorPos(1 - scrollX, _nY - scrollY)
term.clearLine() term.clearLine()
writeHighlighted( sLine ) writeHighlighted(sLine)
if _nY == y and x == #sLine + 1 then if _nY == y and x == #sLine + 1 then
writeCompletion() writeCompletion()
end end
term.setCursorPos( x - scrollX, _nY - scrollY ) term.setCursorPos(x - scrollX, _nY - scrollY)
end end
end end
local function redrawMenu() local function redrawMenu()
-- Clear line -- Clear line
term.setCursorPos( 1, h ) term.setCursorPos(1, h)
term.clearLine() term.clearLine()
-- Draw line numbers -- Draw line numbers
term.setCursorPos( w - #( "Ln " .. y ) + 1, h ) term.setCursorPos(w - #("Ln " .. y) + 1, h)
term.setTextColour( highlightColour ) term.setTextColour(highlightColour)
term.write( "Ln " ) term.write("Ln ")
term.setTextColour( textColour ) term.setTextColour(textColour)
term.write( y ) term.write(y)
term.setCursorPos( 1, h ) term.setCursorPos(1, h)
if bMenu then if bMenu then
-- Draw menu -- Draw menu
term.setTextColour( textColour ) term.setTextColour(textColour)
for nItem, sItem in pairs( tMenuItems ) do for nItem, sItem in pairs(tMenuItems) do
if nItem == nMenuItem then if nItem == nMenuItem then
term.setTextColour( highlightColour ) term.setTextColour(highlightColour)
term.write( "[" ) term.write("[")
term.setTextColour( textColour ) term.setTextColour(textColour)
term.write( sItem ) term.write(sItem)
term.setTextColour( highlightColour ) term.setTextColour(highlightColour)
term.write( "]" ) term.write("]")
term.setTextColour( textColour ) term.setTextColour(textColour)
else else
term.write( " " .. sItem .. " " ) term.write(" " .. sItem .. " ")
end end
end end
else else
-- Draw status -- Draw status
term.setTextColour( highlightColour ) term.setTextColour(highlightColour)
term.write( sStatus ) term.write(sStatus)
term.setTextColour( textColour ) term.setTextColour(textColour)
end end
-- Reset cursor -- Reset cursor
term.setCursorPos( x - scrollX, y - scrollY ) term.setCursorPos(x - scrollX, y - scrollY)
end end
local tMenuFuncs = { local tMenuFuncs = {
@ -287,7 +287,7 @@ local tMenuFuncs = {
if bReadOnly then if bReadOnly then
sStatus = "Access denied" sStatus = "Access denied"
else else
local ok, _, fileerr = save( sPath ) local ok, _, fileerr = save(sPath)
if ok then if ok then
sStatus = "Saved to " .. sPath sStatus = "Saved to " .. sPath
else else
@ -301,14 +301,14 @@ local tMenuFuncs = {
redrawMenu() redrawMenu()
end, end,
Print = function() Print = function()
local printer = peripheral.find( "printer" ) local printer = peripheral.find("printer")
if not printer then if not printer then
sStatus = "No printer attached" sStatus = "No printer attached"
return return
end end
local nPage = 0 local nPage = 0
local sName = fs.getName( sPath ) local sName = fs.getName(sPath)
if printer.getInkLevel() < 1 then if printer.getInkLevel() < 1 then
sStatus = "Printer out of ink" sStatus = "Printer out of ink"
return return
@ -326,7 +326,7 @@ local tMenuFuncs = {
} }
printerTerminal.scroll = function() printerTerminal.scroll = function()
if nPage == 1 then if nPage == 1 then
printer.setPageTitle( sName .. " (page " .. nPage .. ")" ) printer.setPageTitle(sName .. " (page " .. nPage .. ")")
end end
while not printer.newPage() do while not printer.newPage() do
@ -338,38 +338,38 @@ local tMenuFuncs = {
sStatus = "Printer output tray full, please empty" sStatus = "Printer output tray full, please empty"
end end
term.redirect( screenTerminal ) term.redirect(screenTerminal)
redrawMenu() redrawMenu()
term.redirect( printerTerminal ) term.redirect(printerTerminal)
sleep(0.5) sleep(0.5)
end end
nPage = nPage + 1 nPage = nPage + 1
if nPage == 1 then if nPage == 1 then
printer.setPageTitle( sName ) printer.setPageTitle(sName)
else else
printer.setPageTitle( sName .. " (page " .. nPage .. ")" ) printer.setPageTitle(sName .. " (page " .. nPage .. ")")
end end
end end
bMenu = false bMenu = false
term.redirect( printerTerminal ) term.redirect(printerTerminal)
local ok, error = pcall( function() local ok, error = pcall(function()
term.scroll() term.scroll()
for _, sLine in ipairs( tLines ) do for _, sLine in ipairs(tLines) do
print( sLine ) print(sLine)
end end
end ) end)
term.redirect( screenTerminal ) term.redirect(screenTerminal)
if not ok then if not ok then
print( error ) print(error)
end end
while not printer.endPage() do while not printer.endPage() do
sStatus = "Printer output tray full, please empty" sStatus = "Printer output tray full, please empty"
redrawMenu() redrawMenu()
sleep( 0.5 ) sleep(0.5)
end end
bMenu = true bMenu = true
@ -385,15 +385,15 @@ local tMenuFuncs = {
end, end,
Run = function() Run = function()
local sTempPath = "/.temp" local sTempPath = "/.temp"
local ok = save( sTempPath ) local ok = save(sTempPath)
if ok then if ok then
local nTask = shell.openTab( sTempPath ) local nTask = shell.openTab(sTempPath)
if nTask then if nTask then
shell.switchTab( nTask ) shell.switchTab(nTask)
else else
sStatus = "Error starting Task" sStatus = "Error starting Task"
end end
fs.delete( sTempPath ) fs.delete(sTempPath)
else else
sStatus = "Error saving to " .. sTempPath sStatus = "Error saving to " .. sTempPath
end end
@ -401,16 +401,16 @@ local tMenuFuncs = {
end, end,
} }
local function doMenuItem( _n ) local function doMenuItem(_n)
tMenuFuncs[tMenuItems[_n]]() tMenuFuncs[tMenuItems[_n]]()
if bMenu then if bMenu then
bMenu = false bMenu = false
term.setCursorBlink( true ) term.setCursorBlink(true)
end end
redrawMenu() redrawMenu()
end end
local function setCursor( newX, newY ) local function setCursor(newX, newY)
local _, oldY = x, y local _, oldY = x, y
x, y = newX, newY x, y = newX, newY
local screenX = x - scrollX local screenX = x - scrollX
@ -441,12 +441,12 @@ local function setCursor( newX, newY )
if bRedraw then if bRedraw then
redrawText() redrawText()
elseif y ~= oldY then elseif y ~= oldY then
redrawLine( oldY ) redrawLine(oldY)
redrawLine( y ) redrawLine(y)
else else
redrawLine( y ) redrawLine(y)
end end
term.setCursorPos( screenX, screenY ) term.setCursorPos(screenX, screenY)
redrawMenu() redrawMenu()
end end
@ -454,10 +454,10 @@ end
-- Actual program functionality begins -- Actual program functionality begins
load(sPath) load(sPath)
term.setBackgroundColour( bgColour ) term.setBackgroundColour(bgColour)
term.clear() term.clear()
term.setCursorPos(x, y) term.setCursorPos(x, y)
term.setCursorBlink( true ) term.setCursorBlink(true)
recomplete() recomplete()
redrawText() redrawText()
@ -466,9 +466,9 @@ redrawMenu()
local function acceptCompletion() local function acceptCompletion()
if nCompletion then if nCompletion then
-- Append the completion -- Append the completion
local sCompletion = tCompletions[ nCompletion ] local sCompletion = tCompletions[nCompletion]
tLines[y] = tLines[y] .. sCompletion tLines[y] = tLines[y] .. sCompletion
setCursor( x + #sCompletion , y ) setCursor(x + #sCompletion , y)
end end
end end
@ -490,7 +490,7 @@ while bRunning do
elseif y > 1 then elseif y > 1 then
-- Move cursor up -- Move cursor up
setCursor( setCursor(
math.min( x, #tLines[y - 1] + 1 ), math.min(x, #tLines[y - 1] + 1),
y - 1 y - 1
) )
end end
@ -511,7 +511,7 @@ while bRunning do
elseif y < #tLines then elseif y < #tLines then
-- Move cursor down -- Move cursor down
setCursor( setCursor(
math.min( x, #tLines[y + 1] + 1 ), math.min(x, #tLines[y + 1] + 1),
y + 1 y + 1
) )
end end
@ -527,7 +527,7 @@ while bRunning do
-- Indent line -- Indent line
local sLine = tLines[y] local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. " " .. string.sub(sLine, x) tLines[y] = string.sub(sLine, 1, x - 1) .. " " .. string.sub(sLine, x)
setCursor( x + 4, y ) setCursor(x + 4, y)
end end
end end
@ -542,7 +542,7 @@ while bRunning do
newY = 1 newY = 1
end end
setCursor( setCursor(
math.min( x, #tLines[newY] + 1 ), math.min(x, #tLines[newY] + 1),
newY newY
) )
end end
@ -557,8 +557,8 @@ while bRunning do
else else
newY = #tLines newY = #tLines
end end
local newX = math.min( x, #tLines[newY] + 1 ) local newX = math.min(x, #tLines[newY] + 1)
setCursor( newX, newY ) setCursor(newX, newY)
end end
elseif param == keys.home then elseif param == keys.home then
@ -576,7 +576,7 @@ while bRunning do
-- Move cursor to the end -- Move cursor to the end
local nLimit = #tLines[y] + 1 local nLimit = #tLines[y] + 1
if x < nLimit then if x < nLimit then
setCursor( nLimit, y ) setCursor(nLimit, y)
end end
end end
@ -585,9 +585,9 @@ while bRunning do
if not bMenu then if not bMenu then
if x > 1 then if x > 1 then
-- Move cursor left -- Move cursor left
setCursor( x - 1, y ) setCursor(x - 1, y)
elseif x == 1 and y > 1 then elseif x == 1 and y > 1 then
setCursor( #tLines[y - 1] + 1, y - 1 ) setCursor(#tLines[y - 1] + 1, y - 1)
end end
else else
-- Move menu left -- Move menu left
@ -604,13 +604,13 @@ while bRunning do
local nLimit = #tLines[y] + 1 local nLimit = #tLines[y] + 1
if x < nLimit then if x < nLimit then
-- Move cursor right -- Move cursor right
setCursor( x + 1, y ) setCursor(x + 1, y)
elseif nCompletion and x == #tLines[y] + 1 then elseif nCompletion and x == #tLines[y] + 1 then
-- Accept autocomplete -- Accept autocomplete
acceptCompletion() acceptCompletion()
elseif x == nLimit and y < #tLines then elseif x == nLimit and y < #tLines then
-- Go to next line -- Go to next line
setCursor( 1, y + 1 ) setCursor(1, y + 1)
end end
else else
-- Move menu right -- Move menu right
@ -632,7 +632,7 @@ while bRunning do
redrawLine(y) redrawLine(y)
elseif y < #tLines then elseif y < #tLines then
tLines[y] = tLines[y] .. tLines[y + 1] tLines[y] = tLines[y] .. tLines[y + 1]
table.remove( tLines, y + 1 ) table.remove(tLines, y + 1)
recomplete() recomplete()
redrawText() redrawText()
end end
@ -646,17 +646,17 @@ while bRunning do
local sLine = tLines[y] local sLine = tLines[y]
if x > 4 and string.sub(sLine, x - 4, x - 1) == " " and not string.sub(sLine, 1, x - 1):find("%S") then if x > 4 and string.sub(sLine, x - 4, x - 1) == " " and not string.sub(sLine, 1, x - 1):find("%S") then
tLines[y] = string.sub(sLine, 1, x - 5) .. string.sub(sLine, x) tLines[y] = string.sub(sLine, 1, x - 5) .. string.sub(sLine, x)
setCursor( x - 4, y ) setCursor(x - 4, y)
else else
tLines[y] = string.sub(sLine, 1, x - 2) .. string.sub(sLine, x) tLines[y] = string.sub(sLine, 1, x - 2) .. string.sub(sLine, x)
setCursor( x - 1, y ) setCursor(x - 1, y)
end end
elseif y > 1 then elseif y > 1 then
-- Remove newline -- Remove newline
local sPrevLen = #tLines[y - 1] local sPrevLen = #tLines[y - 1]
tLines[y - 1] = tLines[y - 1] .. tLines[y] tLines[y - 1] = tLines[y - 1] .. tLines[y]
table.remove( tLines, y ) table.remove(tLines, y)
setCursor( sPrevLen + 1, y - 1 ) setCursor(sPrevLen + 1, y - 1)
redrawText() redrawText()
end end
end end
@ -671,13 +671,13 @@ while bRunning do
spaces = 0 spaces = 0
end end
tLines[y] = string.sub(sLine, 1, x - 1) tLines[y] = string.sub(sLine, 1, x - 1)
table.insert( tLines, y + 1, string.rep(' ', spaces) .. string.sub(sLine, x) ) table.insert(tLines, y + 1, string.rep(' ', spaces) .. string.sub(sLine, x))
setCursor( spaces + 1, y + 1 ) setCursor(spaces + 1, y + 1)
redrawText() redrawText()
elseif bMenu then elseif bMenu then
-- Menu selection -- Menu selection
doMenuItem( nMenuItem ) doMenuItem(nMenuItem)
end end
@ -685,9 +685,9 @@ while bRunning do
-- Menu toggle -- Menu toggle
bMenu = not bMenu bMenu = not bMenu
if bMenu then if bMenu then
term.setCursorBlink( false ) term.setCursorBlink(false)
else else
term.setCursorBlink( true ) term.setCursorBlink(true)
end end
redrawMenu() redrawMenu()
@ -698,13 +698,13 @@ while bRunning do
-- Input text -- Input text
local sLine = tLines[y] local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. param .. string.sub(sLine, x) tLines[y] = string.sub(sLine, 1, x - 1) .. param .. string.sub(sLine, x)
setCursor( x + 1, y ) setCursor(x + 1, y)
elseif bMenu then elseif bMenu then
-- Select menu items -- Select menu items
for n, sMenuItem in ipairs( tMenuItems ) do for n, sMenuItem in ipairs(tMenuItems) do
if string.lower(string.sub(sMenuItem, 1, 1)) == string.lower(param) then if string.lower(string.sub(sMenuItem, 1, 1)) == string.lower(param) then
doMenuItem( n ) doMenuItem(n)
break break
end end
end end
@ -715,13 +715,13 @@ while bRunning do
-- Close menu if open -- Close menu if open
if bMenu then if bMenu then
bMenu = false bMenu = false
term.setCursorBlink( true ) term.setCursorBlink(true)
redrawMenu() redrawMenu()
end end
-- Input text -- Input text
local sLine = tLines[y] local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. param .. string.sub(sLine, x) tLines[y] = string.sub(sLine, 1, x - 1) .. param .. string.sub(sLine, x)
setCursor( x + #param , y ) setCursor(x + #param , y)
end end
elseif sEvent == "mouse_click" then elseif sEvent == "mouse_click" then
@ -730,9 +730,9 @@ while bRunning do
-- Left click -- Left click
local cx, cy = param2, param3 local cx, cy = param2, param3
if cy < h then if cy < h then
local newY = math.min( math.max( scrollY + cy, 1 ), #tLines ) local newY = math.min(math.max(scrollY + cy, 1), #tLines)
local newX = math.min( math.max( scrollX + cx, 1 ), #tLines[newY] + 1 ) local newX = math.min(math.max(scrollX + cx, 1), #tLines[newY] + 1)
setCursor( newX, newY ) setCursor(newX, newY)
end end
end end
end end
@ -761,7 +761,7 @@ while bRunning do
elseif sEvent == "term_resize" then elseif sEvent == "term_resize" then
w, h = term.getSize() w, h = term.getSize()
setCursor( x, y ) setCursor(x, y)
redrawMenu() redrawMenu()
redrawText() redrawText()
@ -770,5 +770,5 @@ end
-- Cleanup -- Cleanup
term.clear() term.clear()
term.setCursorBlink( false ) term.setCursorBlink(false)
term.setCursorPos( 1, 1 ) term.setCursorPos(1, 1)

View File

@ -2,17 +2,17 @@
-- Get arguments -- Get arguments
local tArgs = { ... } local tArgs = { ... }
if #tArgs == 0 then if #tArgs == 0 then
print( "Usage: eject <drive>" ) print("Usage: eject <drive>")
return return
end end
local sDrive = tArgs[1] local sDrive = tArgs[1]
-- Check the disk exists -- Check the disk exists
local bPresent = disk.isPresent( sDrive ) local bPresent = disk.isPresent(sDrive)
if not bPresent then if not bPresent then
print( "Nothing in " .. sDrive .. " drive" ) print("Nothing in " .. sDrive .. " drive")
return return
end end
disk.eject( sDrive ) disk.eject(sDrive)

View File

@ -32,7 +32,7 @@ if not term.isColour() then
end end
-- Determines if the file exists, and can be edited on this computer -- Determines if the file exists, and can be edited on this computer
local tArgs = {...} local tArgs = { ... }
if #tArgs == 0 then if #tArgs == 0 then
print("Usage: paint <path>") print("Usage: paint <path>")
return return
@ -45,9 +45,9 @@ if fs.exists(sPath) and fs.isDir(sPath) then
end end
-- Create .nfp files by default -- Create .nfp files by default
if not fs.exists( sPath ) and not string.find( sPath, "%." ) then if not fs.exists(sPath) and not string.find(sPath, "%.") then
local sExtension = settings.get("paint.default_extension", "") local sExtension = settings.get("paint.default_extension", "")
if sExtension ~= "" and type( sExtension ) == "string" then if sExtension ~= "" and type(sExtension) == "string" then
sPath = sPath .. "." .. sExtension sPath = sPath .. "." .. sExtension
end end
end end
@ -57,7 +57,7 @@ end
-- Functions -- -- Functions --
--------------- ---------------
local function getCanvasPixel( x, y ) local function getCanvasPixel(x, y)
if canvas[y] then if canvas[y] then
return canvas[y][x] return canvas[y][x]
end end
@ -69,12 +69,12 @@ end
params: colour = the number to convert to a hex value params: colour = the number to convert to a hex value
returns: a string representing the chosen colour returns: a string representing the chosen colour
]] ]]
local function getCharOf( colour ) local function getCharOf(colour)
-- Incorrect values always convert to nil -- Incorrect values always convert to nil
if type(colour) == "number" then if type(colour) == "number" then
local value = math.floor( math.log(colour) / math.log(2) ) + 1 local value = math.floor(math.log(colour) / math.log(2)) + 1
if value >= 1 and value <= 16 then if value >= 1 and value <= 16 then
return string.sub( "0123456789abcdef", value, value ) return string.sub("0123456789abcdef", value, value)
end end
end end
return " " return " "
@ -87,9 +87,9 @@ end
]] ]]
local tColourLookup = {} local tColourLookup = {}
for n = 1, 16 do for n = 1, 16 do
tColourLookup[ string.byte( "0123456789abcdef", n, n ) ] = 2 ^ (n - 1) tColourLookup[string.byte("0123456789abcdef", n, n)] = 2 ^ (n - 1)
end end
local function getColourOf( char ) local function getColourOf(char)
-- Values not in the hex table are transparent (canvas coloured) -- Values not in the hex table are transparent (canvas coloured)
return tColourLookup[char] return tColourLookup[char]
end end
@ -107,9 +107,9 @@ local function load(path)
while sLine do while sLine do
local line = {} local line = {}
for x = 1, w - 2 do for x = 1, w - 2 do
line[x] = getColourOf( string.byte(sLine, x, x) ) line[x] = getColourOf(string.byte(sLine, x, x))
end end
table.insert( canvas, line ) table.insert(canvas, line)
sLine = file.readLine() sLine = file.readLine()
end end
file.close() file.close()
@ -128,7 +128,7 @@ local function save(path)
fs.makeDir(sDir) fs.makeDir(sDir)
end end
local file, err = fs.open( path, "w" ) local file, err = fs.open(path, "w")
if not file then if not file then
return false, err return false, err
end end
@ -140,13 +140,13 @@ local function save(path)
local sLine = "" local sLine = ""
local nLastChar = 0 local nLastChar = 0
for x = 1, w - 2 do for x = 1, w - 2 do
local c = getCharOf( getCanvasPixel( x, y ) ) local c = getCharOf(getCanvasPixel(x, y))
sLine = sLine .. c sLine = sLine .. c
if c ~= " " then if c ~= " " then
nLastChar = x nLastChar = x
end end
end end
sLine = string.sub( sLine, 1, nLastChar ) sLine = string.sub(sLine, 1, nLastChar)
tLines[y] = sLine tLines[y] = sLine
if #sLine > 0 then if #sLine > 0 then
nLastLine = y nLastLine = y
@ -155,7 +155,7 @@ local function save(path)
-- Save out -- Save out
for n = 1, nLastLine do for n = 1, nLastLine do
file.writeLine( tLines[ n ] ) file.writeLine(tLines[n])
end end
file.close() file.close()
return true return true
@ -176,38 +176,38 @@ local function drawInterface()
-- Colour Picker -- Colour Picker
for i = 1, 16 do for i = 1, 16 do
term.setCursorPos(w - 1, i) term.setCursorPos(w - 1, i)
term.setBackgroundColour( 2 ^ (i - 1) ) term.setBackgroundColour(2 ^ (i - 1))
term.write(" ") term.write(" ")
end end
term.setCursorPos(w - 1, 17) term.setCursorPos(w - 1, 17)
term.setBackgroundColour( canvasColour ) term.setBackgroundColour(canvasColour)
term.setTextColour( colours.grey ) term.setTextColour(colours.grey)
term.write("\127\127") term.write("\127\127")
-- Left and Right Selected Colours -- Left and Right Selected Colours
do do
term.setCursorPos(w - 1, 18) term.setCursorPos(w - 1, 18)
if leftColour ~= nil then if leftColour ~= nil then
term.setBackgroundColour( leftColour ) term.setBackgroundColour(leftColour)
term.write(" ") term.write(" ")
else else
term.setBackgroundColour( canvasColour ) term.setBackgroundColour(canvasColour)
term.setTextColour( colours.grey ) term.setTextColour(colours.grey)
term.write("\127") term.write("\127")
end end
if rightColour ~= nil then if rightColour ~= nil then
term.setBackgroundColour( rightColour ) term.setBackgroundColour(rightColour)
term.write(" ") term.write(" ")
else else
term.setBackgroundColour( canvasColour ) term.setBackgroundColour(canvasColour)
term.setTextColour( colours.grey ) term.setTextColour(colours.grey)
term.write("\127") term.write("\127")
end end
end end
-- Padding -- Padding
term.setBackgroundColour( canvasColour ) term.setBackgroundColour(canvasColour)
for i = 20, h - 1 do for i = 20, h - 1 do
term.setCursorPos(w - 1, i) term.setCursorPos(w - 1, i)
term.write(" ") term.write(" ")
@ -218,15 +218,15 @@ end
Converts a single pixel of a single line of the canvas and draws it Converts a single pixel of a single line of the canvas and draws it
returns: nil returns: nil
]] ]]
local function drawCanvasPixel( x, y ) local function drawCanvasPixel(x, y)
local pixel = getCanvasPixel( x, y ) local pixel = getCanvasPixel(x, y)
if pixel then if pixel then
term.setBackgroundColour( pixel or canvasColour ) term.setBackgroundColour(pixel or canvasColour)
term.setCursorPos(x, y) term.setCursorPos(x, y)
term.write(" ") term.write(" ")
else else
term.setBackgroundColour( canvasColour ) term.setBackgroundColour(canvasColour)
term.setTextColour( colours.grey ) term.setTextColour(colours.grey)
term.setCursorPos(x, y) term.setCursorPos(x, y)
term.write("\127") term.write("\127")
end end
@ -236,9 +236,9 @@ end
Converts each colour in a single line of the canvas and draws it Converts each colour in a single line of the canvas and draws it
returns: nil returns: nil
]] ]]
local function drawCanvasLine( y ) local function drawCanvasLine(y)
for x = 1, w - 2 do for x = 1, w - 2 do
drawCanvasPixel( x, y ) drawCanvasPixel(x, y)
end end
end end
@ -248,7 +248,7 @@ end
]] ]]
local function drawCanvas() local function drawCanvas()
for y = 1, h - 1 do for y = 1, h - 1 do
drawCanvasLine( y ) drawCanvasLine(y)
end end
end end
@ -377,7 +377,7 @@ local function handleEvents()
end end
canvas[p3][p2] = paintColour canvas[p3][p2] = paintColour
drawCanvasPixel( p2, p3 ) drawCanvasPixel(p2, p3)
end end
elseif id == "key" then elseif id == "key" then
if p1 == keys.leftCtrl or p1 == keys.rightCtrl then if p1 == keys.leftCtrl or p1 == keys.rightCtrl then

View File

@ -59,10 +59,10 @@ local cR4 = colors.yellow
local tArgs = { ... } local tArgs = { ... }
--Functions-- --Functions--
local function printCentred( yc, stg ) local function printCentred(yc, stg)
local xc = math.floor((TermW - #stg) / 2) + 1 local xc = math.floor((TermW - #stg) / 2) + 1
term.setCursorPos(xc, yc) term.setCursorPos(xc, yc)
term.write( stg ) term.write(stg)
end end
local function centerOrgin() local function centerOrgin()
@ -173,9 +173,9 @@ end
local function loadLevel(nNum) local function loadLevel(nNum)
sLevelTitle = "Level " .. nNum sLevelTitle = "Level " .. nNum
if nNum == nil then return error("nNum == nil") end if nNum == nil then return error("nNum == nil") end
local sDir = fs.getDir( shell.getRunningProgram() ) local sDir = fs.getDir(shell.getRunningProgram())
local sLevelD = sDir .. "/levels/" .. tostring(nNum) .. ".dat" local sLevelD = sDir .. "/levels/" .. tostring(nNum) .. ".dat"
if not ( fs.exists(sLevelD) or fs.isDir(sLevelD) ) then return error("Level Not Exists : " .. sLevelD) end if not (fs.exists(sLevelD) or fs.isDir(sLevelD)) then return error("Level Not Exists : " .. sLevelD) end
fLevel = fs.open(sLevelD, "r") fLevel = fs.open(sLevelD, "r")
local wl = true local wl = true
Blocks = tonumber(string.sub(fLevel.readLine(), 1, 1)) Blocks = tonumber(string.sub(fLevel.readLine(), 1, 1))
@ -512,18 +512,18 @@ local function gRender(sContext)
end end
function InterFace.drawBar() function InterFace.drawBar()
term.setBackgroundColor( colors.black ) term.setBackgroundColor(colors.black)
term.setTextColor( InterFace.cTitle ) term.setTextColor(InterFace.cTitle)
printCentred( 1, " " .. sLevelTitle .. " " ) printCentred(1, " " .. sLevelTitle .. " ")
term.setCursorPos(1, 1) term.setCursorPos(1, 1)
term.setBackgroundColor( cW ) term.setBackgroundColor(cW)
write( " " ) write(" ")
term.setBackgroundColor( colors.black ) term.setBackgroundColor(colors.black)
write( " x " .. tostring(Blocks) .. " " ) write(" x " .. tostring(Blocks) .. " ")
term.setCursorPos( TermW - 8, TermH ) term.setCursorPos(TermW - 8, TermH)
term.setBackgroundColor( colors.black ) term.setBackgroundColor(colors.black)
term.setTextColour(InterFace.cSpeedD) term.setTextColour(InterFace.cSpeedD)
write(" <<") write(" <<")
if bPaused then if bPaused then
@ -539,9 +539,9 @@ function InterFace.drawBar()
end end
write(" >>") write(" >>")
term.setCursorPos( TermW - 1, 1 ) term.setCursorPos(TermW - 1, 1)
term.setBackgroundColor( colors.black ) term.setBackgroundColor(colors.black)
term.setTextColour( InterFace.cExit ) term.setTextColour(InterFace.cExit)
write(" X") write(" X")
term.setBackgroundColor(colors.black) term.setBackgroundColor(colors.black)
end end
@ -612,7 +612,7 @@ local function startG(LevelN)
elseif isExit == "retry" then elseif isExit == "retry" then
return LevelN return LevelN
elseif fExit == "yes" then elseif fExit == "yes" then
if fs.exists( fs.getDir( shell.getRunningProgram() ) .. "/levels/" .. tostring(LevelN + 1) .. ".dat" ) then if fs.exists(fs.getDir(shell.getRunningProgram()) .. "/levels/" .. tostring(LevelN + 1) .. ".dat") then
return LevelN + 1 return LevelN + 1
else else
return nil return nil
@ -629,26 +629,26 @@ local ok, err = true, nil
--Menu-- --Menu--
local sStartLevel = tArgs[1] local sStartLevel = tArgs[1]
if ok and not sStartLevel then if ok and not sStartLevel then
ok, err = pcall( function() ok, err = pcall(function()
term.setTextColor(colors.white) term.setTextColor(colors.white)
term.setBackgroundColor( colors.black ) term.setBackgroundColor(colors.black)
term.clear() term.clear()
drawStars() drawStars()
term.setTextColor( colors.red ) term.setTextColor(colors.red)
printCentred( TermH / 2 - 1, " REDIRECTION " ) printCentred(TermH / 2 - 1, " REDIRECTION ")
printCentred( TermH / 2 - 0, " ComputerCraft Edition " ) printCentred(TermH / 2 - 0, " ComputerCraft Edition ")
term.setTextColor( colors.yellow ) term.setTextColor(colors.yellow)
printCentred( TermH / 2 + 2, " Click to Begin " ) printCentred(TermH / 2 + 2, " Click to Begin ")
os.pullEvent( "mouse_click" ) os.pullEvent("mouse_click")
end ) end)
end end
--Game-- --Game--
if ok then if ok then
ok, err = pcall( function() ok, err = pcall(function()
local nLevel local nLevel
if sStartLevel then if sStartLevel then
nLevel = tonumber( sStartLevel ) nLevel = tonumber(sStartLevel)
else else
nLevel = 1 nLevel = 1
end end
@ -656,36 +656,36 @@ if ok then
reset() reset()
nLevel = startG(nLevel) nLevel = startG(nLevel)
end end
end ) end)
end end
--Upsell screen-- --Upsell screen--
if ok then if ok then
ok, err = pcall( function() ok, err = pcall(function()
term.setTextColor(colors.white) term.setTextColor(colors.white)
term.setBackgroundColor( colors.black ) term.setBackgroundColor(colors.black)
term.clear() term.clear()
drawStars() drawStars()
term.setTextColor( colors.red ) term.setTextColor(colors.red)
if TermW >= 40 then if TermW >= 40 then
printCentred( TermH / 2 - 1, " Thank you for playing Redirection " ) printCentred(TermH / 2 - 1, " Thank you for playing Redirection ")
printCentred( TermH / 2 - 0, " ComputerCraft Edition " ) printCentred(TermH / 2 - 0, " ComputerCraft Edition ")
printCentred( TermH / 2 + 2, " Check out the full game: " ) printCentred(TermH / 2 + 2, " Check out the full game: ")
term.setTextColor( colors.yellow ) term.setTextColor(colors.yellow)
printCentred( TermH / 2 + 3, " http://www.redirectiongame.com " ) printCentred(TermH / 2 + 3, " http://www.redirectiongame.com ")
else else
printCentred( TermH / 2 - 2, " Thank you for " ) printCentred(TermH / 2 - 2, " Thank you for ")
printCentred( TermH / 2 - 1, " playing Redirection " ) printCentred(TermH / 2 - 1, " playing Redirection ")
printCentred( TermH / 2 - 0, " ComputerCraft Edition " ) printCentred(TermH / 2 - 0, " ComputerCraft Edition ")
printCentred( TermH / 2 + 2, " Check out the full game: " ) printCentred(TermH / 2 + 2, " Check out the full game: ")
term.setTextColor( colors.yellow ) term.setTextColor(colors.yellow)
printCentred( TermH / 2 + 3, " www.redirectiongame.com " ) printCentred(TermH / 2 + 3, " www.redirectiongame.com ")
end end
parallel.waitForAll( parallel.waitForAll(
function() sleep(2) end, function() sleep(2) end,
function() os.pullEvent( "mouse_click" ) end function() os.pullEvent("mouse_click") end
) )
end ) end)
end end
--Clear and exit-- --Clear and exit--
@ -695,9 +695,9 @@ term.setBackgroundColor(colors.black)
term.clear() term.clear()
if not ok then if not ok then
if err == "Terminated" then if err == "Terminated" then
print( "Check out the full version of Redirection:" ) print("Check out the full version of Redirection:")
print( "http://www.redirectiongame.com" ) print("http://www.redirectiongame.com")
else else
printError( err ) printError(err)
end end
end end

View File

@ -1,10 +1,10 @@
local tArgs = { ... } local tArgs = { ... }
local function printUsage() local function printUsage()
print( "Usages:" ) print("Usages:")
print( "dj play" ) print("dj play")
print( "dj play <drive>" ) print("dj play <drive>")
print( "dj stop" ) print("dj stop")
end end
if #tArgs > 2 then if #tArgs > 2 then
@ -23,24 +23,24 @@ elseif sCommand == "play" or sCommand == nil then
if sName == nil then if sName == nil then
-- No disc specified, pick one at random -- No disc specified, pick one at random
local tNames = {} local tNames = {}
for _, sName in ipairs( peripheral.getNames() ) do for _, sName in ipairs(peripheral.getNames()) do
if disk.isPresent( sName ) and disk.hasAudio( sName ) then if disk.isPresent(sName) and disk.hasAudio(sName) then
table.insert( tNames, sName ) table.insert(tNames, sName)
end end
end end
if #tNames == 0 then if #tNames == 0 then
print( "No Music Discs in attached disk drives" ) print("No Music Discs in attached disk drives")
return return
end end
sName = tNames[ math.random(1, #tNames) ] sName = tNames[math.random(1, #tNames)]
end end
-- Play the disc -- Play the disc
if disk.isPresent( sName ) and disk.hasAudio( sName ) then if disk.isPresent(sName) and disk.hasAudio(sName) then
print( "Playing " .. disk.getAudioTitle( sName ) ) print("Playing " .. disk.getAudioTitle(sName))
disk.playAudio( sName ) disk.playAudio(sName)
else else
print( "No Music Disc in disk drive: " .. sName ) print("No Music Disc in disk drive: " .. sName)
return return
end end

View File

@ -1,5 +1,5 @@
if term.isColour() then if term.isColour() then
term.setTextColour( 2 ^ math.random(0, 15) ) term.setTextColour(2 ^ math.random(0, 15))
end end
textutils.slowPrint( "Hello World!" ) textutils.slowPrint("Hello World!")
term.setTextColour( colours.white ) term.setTextColour(colours.white)

View File

@ -15,11 +15,11 @@ else
fruitColour = colours.white fruitColour = colours.white
end end
local function printCentred( y, s ) local function printCentred(y, s)
local x = math.floor((w - #s) / 2) local x = math.floor((w - #s) / 2)
term.setCursorPos(x, y) term.setCursorPos(x, y)
--term.clearLine() --term.clearLine()
term.write( s ) term.write(s)
end end
local xVel, yVel = 1, 0 local xVel, yVel = 1, 0
@ -65,9 +65,9 @@ local function addFruit()
if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then
screen[x][y] = { fruit = true } screen[x][y] = { fruit = true }
term.setCursorPos(x, y) term.setCursorPos(x, y)
term.setBackgroundColour( fruitColour ) term.setBackgroundColour(fruitColour)
term.write(" ") term.write(" ")
term.setBackgroundColour( colours.black ) term.setBackgroundColour(colours.black)
break break
end end
end end
@ -79,23 +79,23 @@ local function addFruit()
end end
local function drawMenu() local function drawMenu()
term.setTextColour( headingColour ) term.setTextColour(headingColour)
term.setCursorPos(1, 1) term.setCursorPos(1, 1)
term.write( "SCORE " ) term.write("SCORE ")
term.setTextColour( textColour ) term.setTextColour(textColour)
term.setCursorPos(7, 1) term.setCursorPos(7, 1)
term.write( tostring(nScore) ) term.write(tostring(nScore))
term.setTextColour( headingColour ) term.setTextColour(headingColour)
term.setCursorPos(w - 11, 1) term.setCursorPos(w - 11, 1)
term.write( "DIFFICULTY " ) term.write("DIFFICULTY ")
term.setTextColour( textColour ) term.setTextColour(textColour)
term.setCursorPos(w, 1) term.setCursorPos(w, 1)
term.write( tostring(nDifficulty or "?") ) term.write(tostring(nDifficulty or "?"))
term.setTextColour( colours.white ) term.setTextColour(colours.white)
end end
local function update( ) local function update( )
@ -150,9 +150,9 @@ local function update( )
end end
term.setCursorPos(xPos, yPos) term.setCursorPos(xPos, yPos)
term.setBackgroundColour( wormColour ) term.setBackgroundColour(wormColour)
term.write(" ") term.write(" ")
term.setBackgroundColour( colours.black ) term.setBackgroundColour(colours.black)
drawMenu() drawMenu()
end end
@ -163,29 +163,29 @@ local function drawFrontend()
--term.setTextColour( titleColour ) --term.setTextColour( titleColour )
--printCentred( math.floor(h/2) - 4, " W O R M " ) --printCentred( math.floor(h/2) - 4, " W O R M " )
term.setTextColour( headingColour ) term.setTextColour(headingColour)
printCentred( math.floor(h / 2) - 3, "" ) printCentred(math.floor(h / 2) - 3, "")
printCentred( math.floor(h / 2) - 2, " SELECT DIFFICULTY " ) printCentred(math.floor(h / 2) - 2, " SELECT DIFFICULTY ")
printCentred( math.floor(h / 2) - 1, "" ) printCentred(math.floor(h / 2) - 1, "")
printCentred( math.floor(h / 2) + 0, " " ) printCentred(math.floor(h / 2) + 0, " ")
printCentred( math.floor(h / 2) + 1, " " ) printCentred(math.floor(h / 2) + 1, " ")
printCentred( math.floor(h / 2) + 2, " " ) printCentred(math.floor(h / 2) + 2, " ")
printCentred( math.floor(h / 2) - 1 + nDifficulty, " [ ] " ) printCentred(math.floor(h / 2) - 1 + nDifficulty, " [ ] ")
term.setTextColour( textColour ) term.setTextColour(textColour)
printCentred( math.floor(h / 2) + 0, "EASY" ) printCentred(math.floor(h / 2) + 0, "EASY")
printCentred( math.floor(h / 2) + 1, "MEDIUM" ) printCentred(math.floor(h / 2) + 1, "MEDIUM")
printCentred( math.floor(h / 2) + 2, "HARD" ) printCentred(math.floor(h / 2) + 2, "HARD")
printCentred( math.floor(h / 2) + 3, "" ) printCentred(math.floor(h / 2) + 3, "")
term.setTextColour( colours.white ) term.setTextColour(colours.white)
end end
drawMenu() drawMenu()
drawFrontend() drawFrontend()
while true do while true do
local _, key = os.pullEvent( "key" ) local _, key = os.pullEvent("key")
if key == keys.up or key == keys.w then if key == keys.up or key == keys.w then
-- Up -- Up
if nDifficulty > 1 then if nDifficulty > 1 then
@ -226,7 +226,7 @@ while bRunning do
local event, p1 = os.pullEvent() local event, p1 = os.pullEvent()
if event == "timer" and p1 == timer then if event == "timer" and p1 == timer then
timer = os.startTimer(nInterval) timer = os.startTimer(nInterval)
update( false ) update(false)
elseif event == "key" then elseif event == "key" then
local key = p1 local key = p1
@ -257,24 +257,24 @@ while bRunning do
end end
-- Display the gameover screen -- Display the gameover screen
term.setTextColour( headingColour ) term.setTextColour(headingColour)
printCentred( math.floor(h / 2) - 2, " " ) printCentred(math.floor(h / 2) - 2, " ")
printCentred( math.floor(h / 2) - 1, " G A M E O V E R " ) printCentred(math.floor(h / 2) - 1, " G A M E O V E R ")
term.setTextColour( textColour ) term.setTextColour(textColour)
printCentred( math.floor(h / 2) + 0, " " ) printCentred(math.floor(h / 2) + 0, " ")
printCentred( math.floor(h / 2) + 1, " FINAL SCORE " .. nScore .. " " ) printCentred(math.floor(h / 2) + 1, " FINAL SCORE " .. nScore .. " ")
printCentred( math.floor(h / 2) + 2, " " ) printCentred(math.floor(h / 2) + 2, " ")
term.setTextColour( colours.white ) term.setTextColour(colours.white)
local timer = os.startTimer(2.5) local timer = os.startTimer(2.5)
repeat repeat
local e, p = os.pullEvent() local e, p = os.pullEvent()
if e == "timer" and p == timer then if e == "timer" and p == timer then
term.setTextColour( textColour ) term.setTextColour(textColour)
printCentred( math.floor(h / 2) + 2, " PRESS ANY KEY " ) printCentred(math.floor(h / 2) + 2, " PRESS ANY KEY ")
printCentred( math.floor(h / 2) + 3, " " ) printCentred(math.floor(h / 2) + 3, " ")
term.setTextColour( colours.white ) term.setTextColour(colours.white)
end end
until e == "char" until e == "char"

View File

@ -1,9 +1,9 @@
local function printUsage() local function printUsage()
print( "Usages:" ) print("Usages:")
print( "gps host" ) print("gps host")
print( "gps host <x> <y> <z>" ) print("gps host <x> <y> <z>")
print( "gps locate" ) print("gps locate")
end end
local tArgs = { ... } local tArgs = { ... }
@ -16,27 +16,27 @@ end
if sCommand == "locate" then if sCommand == "locate" then
-- "gps locate" -- "gps locate"
-- Just locate this computer (this will print the results) -- Just locate this computer (this will print the results)
gps.locate( 2, true ) gps.locate(2, true)
elseif sCommand == "host" then elseif sCommand == "host" then
-- "gps host" -- "gps host"
-- Act as a GPS host -- Act as a GPS host
if pocket then if pocket then
print( "GPS Hosts must be stationary" ) print("GPS Hosts must be stationary")
return return
end end
-- Find a modem -- Find a modem
local sModemSide = nil local sModemSide = nil
for _, sSide in ipairs( rs.getSides() ) do for _, sSide in ipairs(rs.getSides()) do
if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then if peripheral.getType(sSide) == "modem" and peripheral.call(sSide, "isWireless") then
sModemSide = sSide sModemSide = sSide
break break
end end
end end
if sModemSide == nil then if sModemSide == nil then
print( "No wireless modems found. 1 required." ) print("No wireless modems found. 1 required.")
return return
end end
@ -51,31 +51,31 @@ elseif sCommand == "host" then
printUsage() printUsage()
return return
end end
print( "Position is " .. x .. "," .. y .. "," .. z ) print("Position is " .. x .. "," .. y .. "," .. z)
else else
-- Position is to be determined using locate -- Position is to be determined using locate
x, y, z = gps.locate( 2, true ) x, y, z = gps.locate(2, true)
if x == nil then if x == nil then
print( "Run \"gps host <x> <y> <z>\" to set position manually" ) print("Run \"gps host <x> <y> <z>\" to set position manually")
return return
end end
end end
-- Open a channel -- Open a channel
local modem = peripheral.wrap( sModemSide ) local modem = peripheral.wrap(sModemSide)
print( "Opening channel on modem " .. sModemSide ) print("Opening channel on modem " .. sModemSide)
modem.open( gps.CHANNEL_GPS ) modem.open(gps.CHANNEL_GPS)
-- Serve requests indefinately -- Serve requests indefinately
local nServed = 0 local nServed = 0
while true do while true do
local e, p1, p2, p3, p4, p5 = os.pullEvent( "modem_message" ) local e, p1, p2, p3, p4, p5 = os.pullEvent("modem_message")
if e == "modem_message" then if e == "modem_message" then
-- We received a message from a modem -- We received a message from a modem
local sSide, sChannel, sReplyChannel, sMessage, nDistance = p1, p2, p3, p4, p5 local sSide, sChannel, sReplyChannel, sMessage, nDistance = p1, p2, p3, p4, p5
if sSide == sModemSide and sChannel == gps.CHANNEL_GPS and sMessage == "PING" and nDistance then if sSide == sModemSide and sChannel == gps.CHANNEL_GPS and sMessage == "PING" and nDistance then
-- We received a ping message on the GPS channel, send a response -- We received a ping message on the GPS channel, send a response
modem.transmit( sReplyChannel, gps.CHANNEL_GPS, { x, y, z } ) modem.transmit(sReplyChannel, gps.CHANNEL_GPS, { x, y, z })
-- Print the number of requests handled -- Print the number of requests handled
nServed = nServed + 1 nServed = nServed + 1
@ -83,7 +83,7 @@ elseif sCommand == "host" then
local _, y = term.getCursorPos() local _, y = term.getCursorPos()
term.setCursorPos(1, y - 1) term.setCursorPos(1, y - 1)
end end
print( nServed .. " GPS requests served" ) print(nServed .. " GPS requests served")
end end
end end
end end

View File

@ -7,20 +7,20 @@ else
end end
if sTopic == "index" then if sTopic == "index" then
print( "Help topics available:" ) print("Help topics available:")
local tTopics = help.topics() local tTopics = help.topics()
textutils.pagedTabulate( tTopics ) textutils.pagedTabulate(tTopics)
return return
end end
local sFile = help.lookup( sTopic ) local sFile = help.lookup(sTopic)
local file = sFile ~= nil and io.open( sFile ) or nil local file = sFile ~= nil and io.open(sFile) or nil
if file then if file then
local sContents = file:read("*a") local sContents = file:read("*a")
file:close() file:close()
local _, nHeight = term.getSize() local _, nHeight = term.getSize()
textutils.pagedPrint( sContents, nHeight - 3 ) textutils.pagedPrint(sContents, nHeight - 3)
else else
print( "No help available" ) print("No help available")
end end

View File

@ -1,9 +1,9 @@
local function printUsage() local function printUsage()
print( "Usages:" ) print("Usages:")
print( "pastebin put <filename>" ) print("pastebin put <filename>")
print( "pastebin get <code> <filename>" ) print("pastebin get <code> <filename>")
print( "pastebin run <code> <arguments>" ) print("pastebin run <code> <arguments>")
end end
local tArgs = { ... } local tArgs = { ... }
@ -13,8 +13,8 @@ if #tArgs < 2 then
end end
if not http then if not http then
printError( "Pastebin requires the http API" ) printError("Pastebin requires the http API")
printError( "Set http.enabled to true in CC: Tweaked's config" ) printError("Set http.enabled to true in CC: Tweaked's config")
return return
end end
@ -29,7 +29,7 @@ local function extractId(paste)
} }
for i = 1, #patterns do for i = 1, #patterns do
local code = paste:match( patterns[i] ) local code = paste:match(patterns[i])
if code then return code end if code then return code end
end end
@ -37,36 +37,36 @@ local function extractId(paste)
end end
local function get(url) local function get(url)
local paste = extractId( url ) local paste = extractId(url)
if not paste then if not paste then
io.stderr:write( "Invalid pastebin code.\n" ) io.stderr:write("Invalid pastebin code.\n")
io.write( "The code is the ID at the end of the pastebin.com URL.\n" ) io.write("The code is the ID at the end of the pastebin.com URL.\n")
return return
end end
write( "Connecting to pastebin.com... " ) write("Connecting to pastebin.com... ")
-- Add a cache buster so that spam protection is re-checked -- Add a cache buster so that spam protection is re-checked
local cacheBuster = ("%x"):format(math.random(0, 2 ^ 30)) local cacheBuster = ("%x"):format(math.random(0, 2 ^ 30))
local response, err = http.get( local response, err = http.get(
"https://pastebin.com/raw/" .. textutils.urlEncode( paste ) .. "?cb=" .. cacheBuster "https://pastebin.com/raw/" .. textutils.urlEncode(paste) .. "?cb=" .. cacheBuster
) )
if response then if response then
-- If spam protection is activated, we get redirected to /paste with Content-Type: text/html -- If spam protection is activated, we get redirected to /paste with Content-Type: text/html
local headers = response.getResponseHeaders() local headers = response.getResponseHeaders()
if not headers["Content-Type"] or not headers["Content-Type"]:find( "^text/plain" ) then if not headers["Content-Type"] or not headers["Content-Type"]:find("^text/plain") then
io.stderr:write( "Failed.\n" ) io.stderr:write("Failed.\n")
print( "Pastebin blocked the download due to spam protection. Please complete the captcha in a web browser: https://pastebin.com/" .. textutils.urlEncode( paste ) ) print("Pastebin blocked the download due to spam protection. Please complete the captcha in a web browser: https://pastebin.com/" .. textutils.urlEncode(paste))
return return
end end
print( "Success." ) print("Success.")
local sResponse = response.readAll() local sResponse = response.readAll()
response.close() response.close()
return sResponse return sResponse
else else
io.stderr:write( "Failed.\n" ) io.stderr:write("Failed.\n")
print(err) print(err)
end end
end end
@ -76,20 +76,20 @@ if sCommand == "put" then
-- Upload a file to pastebin.com -- Upload a file to pastebin.com
-- Determine file to upload -- Determine file to upload
local sFile = tArgs[2] local sFile = tArgs[2]
local sPath = shell.resolve( sFile ) local sPath = shell.resolve(sFile)
if not fs.exists( sPath ) or fs.isDir( sPath ) then if not fs.exists(sPath) or fs.isDir(sPath) then
print( "No such file" ) print("No such file")
return return
end end
-- Read in the file -- Read in the file
local sName = fs.getName( sPath ) local sName = fs.getName(sPath)
local file = fs.open( sPath, "r" ) local file = fs.open(sPath, "r")
local sText = file.readAll() local sText = file.readAll()
file.close() file.close()
-- POST the contents to pastebin -- POST the contents to pastebin
write( "Connecting to pastebin.com... " ) write("Connecting to pastebin.com... ")
local key = "0ec2eb25b6166c0c27a394ae118ad829" local key = "0ec2eb25b6166c0c27a394ae118ad829"
local response = http.post( local response = http.post(
"https://pastebin.com/api/api_post.php", "https://pastebin.com/api/api_post.php",
@ -101,17 +101,17 @@ if sCommand == "put" then
) )
if response then if response then
print( "Success." ) print("Success.")
local sResponse = response.readAll() local sResponse = response.readAll()
response.close() response.close()
local sCode = string.match( sResponse, "[^/]+$" ) local sCode = string.match(sResponse, "[^/]+$")
print( "Uploaded as " .. sResponse ) print("Uploaded as " .. sResponse)
print( "Run \"pastebin get " .. sCode .. "\" to download anywhere" ) print("Run \"pastebin get " .. sCode .. "\" to download anywhere")
else else
print( "Failed." ) print("Failed.")
end end
elseif sCommand == "get" then elseif sCommand == "get" then
@ -124,20 +124,20 @@ elseif sCommand == "get" then
-- Determine file to download -- Determine file to download
local sCode = tArgs[2] local sCode = tArgs[2]
local sFile = tArgs[3] local sFile = tArgs[3]
local sPath = shell.resolve( sFile ) local sPath = shell.resolve(sFile)
if fs.exists( sPath ) then if fs.exists(sPath) then
print( "File already exists" ) print("File already exists")
return return
end end
-- GET the contents from pastebin -- GET the contents from pastebin
local res = get(sCode) local res = get(sCode)
if res then if res then
local file = fs.open( sPath, "w" ) local file = fs.open(sPath, "w")
file.write( res ) file.write(res)
file.close() file.close()
print( "Downloaded as " .. sFile ) print("Downloaded as " .. sFile)
end end
elseif sCommand == "run" then elseif sCommand == "run" then
local sCode = tArgs[2] local sCode = tArgs[2]
@ -146,12 +146,12 @@ elseif sCommand == "run" then
if res then if res then
local func, err = load(res, sCode, "t", _ENV) local func, err = load(res, sCode, "t", _ENV)
if not func then if not func then
printError( err ) printError(err)
return return
end end
local success, msg = pcall(func, select(3, ...)) local success, msg = pcall(func, select(3, ...))
if not success then if not success then
printError( msg ) printError(msg)
end end
end end
else else

View File

@ -1,15 +1,15 @@
local function printUsage() local function printUsage()
print( "Usage:" ) print("Usage:")
print( "wget <url> [filename]" ) print("wget <url> [filename]")
print( "wget run <url>" ) print("wget run <url>")
end end
local tArgs = { ... } local tArgs = { ... }
local run = false local run = false
if tArgs[1] == "run" then if tArgs[1] == "run" then
table.remove( tArgs, 1 ) table.remove(tArgs, 1)
run = true run = true
end end
@ -18,36 +18,36 @@ if #tArgs < 1 then
return return
end end
local url = table.remove( tArgs, 1 ) local url = table.remove(tArgs, 1)
if not http then if not http then
printError( "wget requires the http API" ) printError("wget requires the http API")
printError( "Set http.enabled to true in CC: Tweaked's config" ) printError("Set http.enabled to true in CC: Tweaked's config")
return return
end end
local function getFilename( sUrl ) local function getFilename(sUrl)
sUrl = sUrl:gsub( "[#?].*" , "" ):gsub( "/+$" , "" ) sUrl = sUrl:gsub("[#?].*" , ""):gsub("/+$" , "")
return sUrl:match( "/([^/]+)$" ) return sUrl:match("/([^/]+)$")
end end
local function get( sUrl ) local function get(sUrl)
-- Check if the URL is valid -- Check if the URL is valid
local ok, err = http.checkURL( url ) local ok, err = http.checkURL(url)
if not ok then if not ok then
printError( err or "Invalid URL." ) printError(err or "Invalid URL.")
return return
end end
write( "Connecting to " .. sUrl .. "... " ) write("Connecting to " .. sUrl .. "... ")
local response = http.get( sUrl , nil , true ) local response = http.get(sUrl , nil , true)
if not response then if not response then
print( "Failed." ) print("Failed.")
return nil return nil
end end
print( "Success." ) print("Success.")
local sResponse = response.readAll() local sResponse = response.readAll()
response.close() response.close()
@ -66,22 +66,22 @@ if run then
local ok, err = pcall(func, table.unpack(tArgs)) local ok, err = pcall(func, table.unpack(tArgs))
if not ok then if not ok then
printError( err ) printError(err)
end end
else else
local sFile = tArgs[1] or getFilename( url ) local sFile = tArgs[1] or getFilename(url)
local sPath = shell.resolve( sFile ) local sPath = shell.resolve(sFile)
if fs.exists( sPath ) then if fs.exists(sPath) then
print( "File already exists" ) print("File already exists")
return return
end end
local res = get(url) local res = get(url)
if not res then return end if not res then return end
local file = fs.open( sPath, "wb" ) local file = fs.open(sPath, "wb")
file.write( res ) file.write(res)
file.close() file.close()
print( "Downloaded as " .. sFile ) print("Downloaded as " .. sFile)
end end

View File

@ -2,28 +2,28 @@
local sDrive = nil local sDrive = nil
local tArgs = { ... } local tArgs = { ... }
if #tArgs > 0 then if #tArgs > 0 then
sDrive = tostring( tArgs[1] ) sDrive = tostring(tArgs[1])
end end
if sDrive == nil then if sDrive == nil then
print( "This is computer #" .. os.getComputerID() ) print("This is computer #" .. os.getComputerID())
local label = os.getComputerLabel() local label = os.getComputerLabel()
if label then if label then
print( "This computer is labelled \"" .. label .. "\"" ) print("This computer is labelled \"" .. label .. "\"")
end end
else else
local bData = disk.hasData( sDrive ) local bData = disk.hasData(sDrive)
if not bData then if not bData then
print( "No disk in drive " .. sDrive ) print("No disk in drive " .. sDrive)
return return
end end
print( "The disk is #" .. disk.getID( sDrive ) ) print("The disk is #" .. disk.getID(sDrive))
local label = disk.getLabel( sDrive ) local label = disk.getLabel(sDrive)
if label then if label then
print( "The disk is labelled \"" .. label .. "\"" ) print("The disk is labelled \"" .. label .. "\"")
end end
end end

View File

@ -1,67 +1,67 @@
local function printUsage() local function printUsage()
print( "Usages:" ) print("Usages:")
print( "label get" ) print("label get")
print( "label get <drive>" ) print("label get <drive>")
print( "label set <text>" ) print("label set <text>")
print( "label set <drive> <text>" ) print("label set <drive> <text>")
print( "label clear" ) print("label clear")
print( "label clear <drive>" ) print("label clear <drive>")
end end
local function checkDrive( sDrive ) local function checkDrive(sDrive)
if peripheral.getType( sDrive ) == "drive" then if peripheral.getType(sDrive) == "drive" then
-- Check the disk exists -- Check the disk exists
local bData = disk.hasData( sDrive ) local bData = disk.hasData(sDrive)
if not bData then if not bData then
print( "No disk in " .. sDrive .. " drive" ) print("No disk in " .. sDrive .. " drive")
return false return false
end end
else else
print( "No disk drive named " .. sDrive ) print("No disk drive named " .. sDrive)
return false return false
end end
return true return true
end end
local function get( sDrive ) local function get(sDrive)
if sDrive ~= nil then if sDrive ~= nil then
if checkDrive( sDrive ) then if checkDrive(sDrive) then
local sLabel = disk.getLabel( sDrive ) local sLabel = disk.getLabel(sDrive)
if sLabel then if sLabel then
print( "Disk label is \"" .. sLabel .. "\"" ) print("Disk label is \"" .. sLabel .. "\"")
else else
print( "No Disk label" ) print("No Disk label")
end end
end end
else else
local sLabel = os.getComputerLabel() local sLabel = os.getComputerLabel()
if sLabel then if sLabel then
print( "Computer label is \"" .. sLabel .. "\"" ) print("Computer label is \"" .. sLabel .. "\"")
else else
print( "No Computer label" ) print("No Computer label")
end end
end end
end end
local function set( sDrive, sText ) local function set(sDrive, sText)
if sDrive ~= nil then if sDrive ~= nil then
if checkDrive( sDrive ) then if checkDrive(sDrive) then
disk.setLabel( sDrive, sText ) disk.setLabel(sDrive, sText)
local sLabel = disk.getLabel( sDrive ) local sLabel = disk.getLabel(sDrive)
if sLabel then if sLabel then
print( "Disk label set to \"" .. sLabel .. "\"" ) print("Disk label set to \"" .. sLabel .. "\"")
else else
print( "Disk label cleared" ) print("Disk label cleared")
end end
end end
else else
os.setComputerLabel( sText ) os.setComputerLabel(sText)
local sLabel = os.getComputerLabel() local sLabel = os.getComputerLabel()
if sLabel then if sLabel then
print( "Computer label set to \"" .. sLabel .. "\"" ) print("Computer label set to \"" .. sLabel .. "\"")
else else
print( "Computer label cleared" ) print("Computer label cleared")
end end
end end
end end
@ -71,27 +71,27 @@ local sCommand = tArgs[1]
if sCommand == "get" then if sCommand == "get" then
-- Get a label -- Get a label
if #tArgs == 1 then if #tArgs == 1 then
get( nil ) get(nil)
elseif #tArgs == 2 then elseif #tArgs == 2 then
get( tArgs[2] ) get(tArgs[2])
else else
printUsage() printUsage()
end end
elseif sCommand == "set" then elseif sCommand == "set" then
-- Set a label -- Set a label
if #tArgs == 2 then if #tArgs == 2 then
set( nil, tArgs[2] ) set(nil, tArgs[2])
elseif #tArgs == 3 then elseif #tArgs == 3 then
set( tArgs[2], tArgs[3] ) set(tArgs[2], tArgs[3])
else else
printUsage() printUsage()
end end
elseif sCommand == "clear" then elseif sCommand == "clear" then
-- Clear a label -- Clear a label
if #tArgs == 1 then if #tArgs == 1 then
set( nil, nil ) set(nil, nil)
elseif #tArgs == 2 then elseif #tArgs == 2 then
set( tArgs[2], nil ) set(tArgs[2], nil)
else else
printUsage() printUsage()
end end

View File

@ -4,35 +4,35 @@ local tArgs = { ... }
-- Get all the files in the directory -- Get all the files in the directory
local sDir = shell.dir() local sDir = shell.dir()
if tArgs[1] ~= nil then if tArgs[1] ~= nil then
sDir = shell.resolve( tArgs[1] ) sDir = shell.resolve(tArgs[1])
end end
if not fs.isDir( sDir ) then if not fs.isDir(sDir) then
printError( "Not a directory" ) printError("Not a directory")
return return
end end
-- Sort into dirs/files, and calculate column count -- Sort into dirs/files, and calculate column count
local tAll = fs.list( sDir ) local tAll = fs.list(sDir)
local tFiles = {} local tFiles = {}
local tDirs = {} local tDirs = {}
local bShowHidden = settings.get( "list.show_hidden" ) local bShowHidden = settings.get("list.show_hidden")
for _, sItem in pairs( tAll ) do for _, sItem in pairs(tAll) do
if bShowHidden or string.sub( sItem, 1, 1 ) ~= "." then if bShowHidden or string.sub(sItem, 1, 1) ~= "." then
local sPath = fs.combine( sDir, sItem ) local sPath = fs.combine(sDir, sItem)
if fs.isDir( sPath ) then if fs.isDir(sPath) then
table.insert( tDirs, sItem ) table.insert(tDirs, sItem)
else else
table.insert( tFiles, sItem ) table.insert(tFiles, sItem)
end end
end end
end end
table.sort( tDirs ) table.sort(tDirs)
table.sort( tFiles ) table.sort(tFiles)
if term.isColour() then if term.isColour() then
textutils.pagedTabulate( colors.green, tDirs, colors.white, tFiles ) textutils.pagedTabulate(colors.green, tDirs, colors.white, tFiles)
else else
textutils.pagedTabulate( tDirs, tFiles ) textutils.pagedTabulate(tDirs, tFiles)
end end

View File

@ -1,8 +1,8 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs > 0 then if #tArgs > 0 then
print( "This is an interactive Lua prompt." ) print("This is an interactive Lua prompt.")
print( "To run a lua program, just type its name." ) print("To run a lua program, just type its name.")
return return
end end
@ -15,11 +15,11 @@ local tEnv = {
__tostring = function() return "Call exit() to exit." end, __tostring = function() return "Call exit() to exit." end,
__call = function() bRunning = false end, __call = function() bRunning = false end,
}), }),
["_echo"] = function( ... ) ["_echo"] = function(...)
return ... return ...
end, end,
} }
setmetatable( tEnv, { __index = _ENV } ) setmetatable(tEnv, { __index = _ENV })
-- Replace our package.path, so that it loads from the current directory, rather -- Replace our package.path, so that it loads from the current directory, rather
-- than from /rom/programs. This makes it a little more friendly to use and -- than from /rom/programs. This makes it a little more friendly to use and
@ -39,38 +39,38 @@ do
end end
if term.isColour() then if term.isColour() then
term.setTextColour( colours.yellow ) term.setTextColour(colours.yellow)
end end
print( "Interactive Lua prompt." ) print("Interactive Lua prompt.")
print( "Call exit() to exit." ) print("Call exit() to exit.")
term.setTextColour( colours.white ) term.setTextColour(colours.white)
while bRunning do while bRunning do
--if term.isColour() then --if term.isColour() then
-- term.setTextColour( colours.yellow ) -- term.setTextColour( colours.yellow )
--end --end
write( "lua> " ) write("lua> ")
--term.setTextColour( colours.white ) --term.setTextColour( colours.white )
local s = read( nil, tCommandHistory, function( sLine ) local s = read(nil, tCommandHistory, function(sLine)
if settings.get( "lua.autocomplete" ) then if settings.get("lua.autocomplete") then
local nStartPos = string.find( sLine, "[a-zA-Z0-9_%.:]+$" ) local nStartPos = string.find(sLine, "[a-zA-Z0-9_%.:]+$")
if nStartPos then if nStartPos then
sLine = string.sub( sLine, nStartPos ) sLine = string.sub(sLine, nStartPos)
end end
if #sLine > 0 then if #sLine > 0 then
return textutils.complete( sLine, tEnv ) return textutils.complete(sLine, tEnv)
end end
end end
return nil return nil
end ) end)
if s:match("%S") and tCommandHistory[#tCommandHistory] ~= s then if s:match("%S") and tCommandHistory[#tCommandHistory] ~= s then
table.insert( tCommandHistory, s ) table.insert(tCommandHistory, s)
end end
local nForcePrint = 0 local nForcePrint = 0
local func, e = load( s, "=lua", "t", tEnv ) local func, e = load(s, "=lua", "t", tEnv)
local func2 = load( "return _echo(" .. s .. ");", "=lua", "t", tEnv ) local func2 = load("return _echo(" .. s .. ");", "=lua", "t", tEnv)
if not func then if not func then
if func2 then if func2 then
func = func2 func = func2
@ -84,11 +84,11 @@ while bRunning do
end end
if func then if func then
local tResults = table.pack( pcall( func ) ) local tResults = table.pack(pcall(func))
if tResults[1] then if tResults[1] then
local n = 1 local n = 1
while n < tResults.n or n <= nForcePrint do while n < tResults.n or n <= nForcePrint do
local value = tResults[ n + 1 ] local value = tResults[n + 1]
local ok, serialised = pcall(pretty.pretty, value) local ok, serialised = pcall(pretty.pretty, value)
if ok then if ok then
pretty.print(serialised) pretty.print(serialised)
@ -98,10 +98,10 @@ while bRunning do
n = n + 1 n = n + 1
end end
else else
printError( tResults[2] ) printError(tResults[2])
end end
else else
printError( e ) printError(e)
end end
end end

View File

@ -1,17 +1,17 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 1 then if #tArgs < 1 then
print( "Usage: mkdir <paths>" ) print("Usage: mkdir <paths>")
return return
end end
for _, v in ipairs( tArgs ) do for _, v in ipairs(tArgs) do
local sNewDir = shell.resolve( v ) local sNewDir = shell.resolve(v)
if fs.exists( sNewDir ) and not fs.isDir( sNewDir ) then if fs.exists(sNewDir) and not fs.isDir(sNewDir) then
printError( v .. ": Destination exists" ) printError(v .. ": Destination exists")
elseif fs.isReadOnly( sNewDir ) then elseif fs.isReadOnly(sNewDir) then
printError( v .. ": Access denied" ) printError(v .. ": Access denied")
else else
fs.makeDir( sNewDir ) fs.makeDir(sNewDir)
end end
end end

View File

@ -1,5 +1,5 @@
local function printUsage() local function printUsage()
print( "Usage: monitor <name> <program> <arguments>" ) print("Usage: monitor <name> <program> <arguments>")
return return
end end
@ -10,65 +10,65 @@ if #tArgs < 2 then
end end
local sName = tArgs[1] local sName = tArgs[1]
if peripheral.getType( sName ) ~= "monitor" then if peripheral.getType(sName) ~= "monitor" then
print( "No monitor named " .. sName ) print("No monitor named " .. sName)
return return
end end
local sProgram = tArgs[2] local sProgram = tArgs[2]
local sPath = shell.resolveProgram( sProgram ) local sPath = shell.resolveProgram(sProgram)
if sPath == nil then if sPath == nil then
print( "No such program: " .. sProgram ) print("No such program: " .. sProgram)
return return
end end
print( "Running " .. sProgram .. " on monitor " .. sName ) print("Running " .. sProgram .. " on monitor " .. sName)
local monitor = peripheral.wrap( sName ) local monitor = peripheral.wrap(sName)
local previousTerm = term.redirect( monitor ) local previousTerm = term.redirect(monitor)
local co = coroutine.create( function() local co = coroutine.create(function()
shell.run( sProgram, table.unpack( tArgs, 3 ) ) shell.run(sProgram, table.unpack(tArgs, 3))
end ) end)
local function resume( ... ) local function resume(...)
local ok, param = coroutine.resume( co, ... ) local ok, param = coroutine.resume(co, ...)
if not ok then if not ok then
printError( param ) printError(param)
end end
return param return param
end end
local timers = {} local timers = {}
local ok, param = pcall( function() local ok, param = pcall(function()
local sFilter = resume() local sFilter = resume()
while coroutine.status( co ) ~= "dead" do while coroutine.status(co) ~= "dead" do
local tEvent = table.pack( os.pullEventRaw() ) local tEvent = table.pack(os.pullEventRaw())
if sFilter == nil or tEvent[1] == sFilter or tEvent[1] == "terminate" then if sFilter == nil or tEvent[1] == sFilter or tEvent[1] == "terminate" then
sFilter = resume( table.unpack( tEvent, 1, tEvent.n ) ) sFilter = resume(table.unpack(tEvent, 1, tEvent.n))
end end
if coroutine.status( co ) ~= "dead" and (sFilter == nil or sFilter == "mouse_click") then if coroutine.status(co) ~= "dead" and (sFilter == nil or sFilter == "mouse_click") then
if tEvent[1] == "monitor_touch" and tEvent[2] == sName then if tEvent[1] == "monitor_touch" and tEvent[2] == sName then
timers[os.startTimer( 0.1 )] = { tEvent[3], tEvent[4] } timers[os.startTimer(0.1)] = { tEvent[3], tEvent[4] }
sFilter = resume( "mouse_click", 1, table.unpack( tEvent, 3, tEvent.n ) ) sFilter = resume("mouse_click", 1, table.unpack(tEvent, 3, tEvent.n))
end end
end end
if coroutine.status( co ) ~= "dead" and (sFilter == nil or sFilter == "term_resize") then if coroutine.status(co) ~= "dead" and (sFilter == nil or sFilter == "term_resize") then
if tEvent[1] == "monitor_resize" and tEvent[2] == sName then if tEvent[1] == "monitor_resize" and tEvent[2] == sName then
sFilter = resume( "term_resize" ) sFilter = resume("term_resize")
end end
end end
if coroutine.status( co ) ~= "dead" and (sFilter == nil or sFilter == "mouse_up") then if coroutine.status(co) ~= "dead" and (sFilter == nil or sFilter == "mouse_up") then
if tEvent[1] == "timer" and timers[tEvent[2]] then if tEvent[1] == "timer" and timers[tEvent[2]] then
sFilter = resume( "mouse_up", 1, table.unpack( timers[tEvent[2]], 1, 2 ) ) sFilter = resume("mouse_up", 1, table.unpack(timers[tEvent[2]], 1, 2))
timers[tEvent[2]] = nil timers[tEvent[2]] = nil
end end
end end
end end
end ) end)
term.redirect( previousTerm ) term.redirect(previousTerm)
if not ok then if not ok then
printError( param ) printError(param)
end end

View File

@ -1,6 +1,6 @@
local tMotd = {} local tMotd = {}
for sPath in string.gmatch(settings.get( "motd.path" ), "[^:]+") do for sPath in string.gmatch(settings.get("motd.path"), "[^:]+") do
if fs.exists(sPath) then if fs.exists(sPath) then
for sLine in io.lines(sPath) do for sLine in io.lines(sPath) do
table.insert(tMotd, sLine) table.insert(tMotd, sLine)

View File

@ -1,24 +1,24 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 2 then if #tArgs < 2 then
print( "Usage: mv <source> <destination>" ) print("Usage: mv <source> <destination>")
return return
end end
local sSource = shell.resolve( tArgs[1] ) local sSource = shell.resolve(tArgs[1])
local sDest = shell.resolve( tArgs[2] ) local sDest = shell.resolve(tArgs[2])
local tFiles = fs.find( sSource ) local tFiles = fs.find(sSource)
if #tFiles > 0 then if #tFiles > 0 then
for _, sFile in ipairs( tFiles ) do for _, sFile in ipairs(tFiles) do
if fs.isDir( sDest ) then if fs.isDir(sDest) then
fs.move( sFile, fs.combine( sDest, fs.getName(sFile) ) ) fs.move(sFile, fs.combine(sDest, fs.getName(sFile)))
elseif #tFiles == 1 then elseif #tFiles == 1 then
fs.move( sFile, sDest ) fs.move(sFile, sDest)
else else
printError( "Cannot overwrite file multiple times" ) printError("Cannot overwrite file multiple times")
return return
end end
end end
else else
printError( "No matching files" ) printError("No matching files")
end end

View File

@ -1,10 +1,10 @@
local tPeripherals = peripheral.getNames() local tPeripherals = peripheral.getNames()
print( "Attached Peripherals:" ) print("Attached Peripherals:")
if #tPeripherals > 0 then if #tPeripherals > 0 then
for n = 1, #tPeripherals do for n = 1, #tPeripherals do
local sPeripheral = tPeripherals[n] local sPeripheral = tPeripherals[n]
print( sPeripheral .. " (" .. peripheral.getType( sPeripheral ) .. ")" ) print(sPeripheral .. " (" .. peripheral.getType(sPeripheral) .. ")")
end end
else else
print( "None" ) print("None")
end end

View File

@ -1,11 +1,11 @@
if not pocket then if not pocket then
printError( "Requires a Pocket Computer" ) printError("Requires a Pocket Computer")
return return
end end
local ok, err = pocket.equipBack() local ok, err = pocket.equipBack()
if not ok then if not ok then
printError( err ) printError(err)
else else
print( "Item equipped" ) print("Item equipped")
end end

View File

@ -160,7 +160,7 @@ local block_T = {
local blocks = { block_line, block_square, block_s1, block_s2, block_L1, block_L2, block_T } local blocks = { block_line, block_square, block_s1, block_s2, block_L1, block_L2, block_T }
local points = {4, 10, 30, 120} local points = { 4, 10, 30, 120 }
local function lpad(text, amt) local function lpad(text, amt)
text = tostring(text) text = tostring(text)
@ -456,7 +456,7 @@ local function playGame()
sleep(.25) sleep(.25)
for r = 1, #rows do for r = 1, #rows do
table.remove(pit, rows[r]) table.remove(pit, rows[r])
table.insert(pit, 1, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) table.insert(pit, 1, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 })
end end
redrawPit() redrawPit()
lines = lines + #rows lines = lines + #rows
@ -496,7 +496,7 @@ local function playGame()
while not halt do while not halt do
local e = {os.pullEvent()} local e = { os.pullEvent() }
if e[1] == "timer" then if e[1] == "timer" then
if e[2] == dropTimer then if e[2] == dropTimer then
blockFall() blockFall()
@ -517,7 +517,7 @@ local function playGame()
elseif key == keys.space then elseif key == keys.space then
hidePit() hidePit()
msgBox("Paused") msgBox("Paused")
while ({os.pullEvent("key")})[2] ~= keys.space do end while ({ os.pullEvent("key") })[2] ~= keys.space do end
redrawPit() redrawPit()
drawBlockAt(curBlock, curX, curY, curRot) drawBlockAt(curBlock, curX, curY, curRot)
dropTimer = os.startTimer(dropSpeed) dropTimer = os.startTimer(dropSpeed)
@ -606,7 +606,7 @@ local function runMenu()
drawMenu() drawMenu()
while true do while true do
local event = {os.pullEvent()} local event = { os.pullEvent() }
if event[1] == "key" then if event[1] == "key" then
local key = event[2] local key = event[2]
if key == keys.right or key == keys.d and selected == 1 then if key == keys.right or key == keys.d and selected == 1 then

View File

@ -1,11 +1,11 @@
if not pocket then if not pocket then
printError( "Requires a Pocket Computer" ) printError("Requires a Pocket Computer")
return return
end end
local ok, err = pocket.unequipBack() local ok, err = pocket.unequipBack()
if not ok then if not ok then
printError( err ) printError(err)
else else
print( "Item unequipped" ) print("Item unequipped")
end end

View File

@ -5,5 +5,5 @@ if #tArgs > 0 and tArgs[1] == "all" then
bAll = true bAll = true
end end
local tPrograms = shell.programs( bAll ) local tPrograms = shell.programs(bAll)
textutils.pagedTabulate( tPrograms ) textutils.pagedTabulate(tPrograms)

View File

@ -1,8 +1,8 @@
if term.isColour() then if term.isColour() then
term.setTextColour( colours.yellow ) term.setTextColour(colours.yellow)
end end
print( "Goodbye" ) print("Goodbye")
term.setTextColour( colours.white ) term.setTextColour(colours.white)
sleep( 1 ) sleep(1)
os.reboot() os.reboot()

View File

@ -2,29 +2,29 @@
local tArgs = { ... } local tArgs = { ... }
local function printUsage() local function printUsage()
print( "Usages:" ) print("Usages:")
print( "chat host <hostname>" ) print("chat host <hostname>")
print( "chat join <hostname> <nickname>" ) print("chat join <hostname> <nickname>")
end end
local sOpenedModem = nil local sOpenedModem = nil
local function openModem() local function openModem()
for _, sModem in ipairs( peripheral.getNames() ) do for _, sModem in ipairs(peripheral.getNames()) do
if peripheral.getType( sModem ) == "modem" then if peripheral.getType(sModem) == "modem" then
if not rednet.isOpen( sModem ) then if not rednet.isOpen(sModem) then
rednet.open( sModem ) rednet.open(sModem)
sOpenedModem = sModem sOpenedModem = sModem
end end
return true return true
end end
end end
print( "No modems found." ) print("No modems found.")
return false return false
end end
local function closeModem() local function closeModem()
if sOpenedModem ~= nil then if sOpenedModem ~= nil then
rednet.close( sOpenedModem ) rednet.close(sOpenedModem)
sOpenedModem = nil sOpenedModem = nil
end end
end end
@ -53,54 +53,54 @@ if sCommand == "host" then
if not openModem() then if not openModem() then
return return
end end
rednet.host( "chat", sHostname ) rednet.host("chat", sHostname)
print( "0 users connected." ) print("0 users connected.")
local tUsers = {} local tUsers = {}
local nUsers = 0 local nUsers = 0
local function send( sText, nUserID ) local function send(sText, nUserID)
if nUserID then if nUserID then
local tUser = tUsers[ nUserID ] local tUser = tUsers[nUserID]
if tUser then if tUser then
rednet.send( tUser.nID, { rednet.send(tUser.nID, {
sType = "text", sType = "text",
nUserID = nUserID, nUserID = nUserID,
sText = sText, sText = sText,
}, "chat" ) }, "chat")
end end
else else
for nUserID, tUser in pairs( tUsers ) do for nUserID, tUser in pairs(tUsers) do
rednet.send( tUser.nID, { rednet.send(tUser.nID, {
sType = "text", sType = "text",
nUserID = nUserID, nUserID = nUserID,
sText = sText, sText = sText,
}, "chat" ) }, "chat")
end end
end end
end end
-- Setup ping pong -- Setup ping pong
local tPingPongTimer = {} local tPingPongTimer = {}
local function ping( nUserID ) local function ping(nUserID)
local tUser = tUsers[ nUserID ] local tUser = tUsers[nUserID]
rednet.send( tUser.nID, { rednet.send(tUser.nID, {
sType = "ping to client", sType = "ping to client",
nUserID = nUserID, nUserID = nUserID,
}, "chat" ) }, "chat")
local timer = os.startTimer( 15 ) local timer = os.startTimer(15)
tUser.bPingPonged = false tUser.bPingPonged = false
tPingPongTimer[ timer ] = nUserID tPingPongTimer[timer] = nUserID
end end
local function printUsers() local function printUsers()
local _, y = term.getCursorPos() local _, y = term.getCursorPos()
term.setCursorPos( 1, y - 1 ) term.setCursorPos(1, y - 1)
term.clearLine() term.clearLine()
if nUsers == 1 then if nUsers == 1 then
print( nUsers .. " user connected." ) print(nUsers .. " user connected.")
else else
print( nUsers .. " users connected." ) print(nUsers .. " users connected.")
end end
end end
@ -108,18 +108,18 @@ if sCommand == "host" then
local ok, error = pcall(parallel.waitForAny, local ok, error = pcall(parallel.waitForAny,
function() function()
while true do while true do
local _, timer = os.pullEvent( "timer" ) local _, timer = os.pullEvent("timer")
local nUserID = tPingPongTimer[ timer ] local nUserID = tPingPongTimer[timer]
if nUserID and tUsers[ nUserID ] then if nUserID and tUsers[nUserID] then
local tUser = tUsers[ nUserID ] local tUser = tUsers[nUserID]
if tUser then if tUser then
if not tUser.bPingPonged then if not tUser.bPingPonged then
send( "* " .. tUser.sUsername .. " has timed out" ) send("* " .. tUser.sUsername .. " has timed out")
tUsers[ nUserID ] = nil tUsers[nUserID] = nil
nUsers = nUsers - 1 nUsers = nUsers - 1
printUsers() printUsers()
else else
ping( nUserID ) ping(nUserID)
end end
end end
end end
@ -129,91 +129,91 @@ if sCommand == "host" then
while true do while true do
local tCommands local tCommands
tCommands = { tCommands = {
["me"] = function( tUser, sContent ) ["me"] = function(tUser, sContent)
if #sContent > 0 then if #sContent > 0 then
send( "* " .. tUser.sUsername .. " " .. sContent ) send("* " .. tUser.sUsername .. " " .. sContent)
else else
send( "* Usage: /me [words]", tUser.nUserID ) send("* Usage: /me [words]", tUser.nUserID)
end end
end, end,
["nick"] = function( tUser, sContent ) ["nick"] = function(tUser, sContent)
if #sContent > 0 then if #sContent > 0 then
local sOldName = tUser.sUsername local sOldName = tUser.sUsername
tUser.sUsername = sContent tUser.sUsername = sContent
send( "* " .. sOldName .. " is now known as " .. tUser.sUsername ) send("* " .. sOldName .. " is now known as " .. tUser.sUsername)
else else
send( "* Usage: /nick [nickname]", tUser.nUserID ) send("* Usage: /nick [nickname]", tUser.nUserID)
end end
end, end,
["users"] = function( tUser, sContent ) ["users"] = function(tUser, sContent)
send( "* Connected Users:", tUser.nUserID ) send("* Connected Users:", tUser.nUserID)
local sUsers = "*" local sUsers = "*"
for _, tUser in pairs( tUsers ) do for _, tUser in pairs(tUsers) do
sUsers = sUsers .. " " .. tUser.sUsername sUsers = sUsers .. " " .. tUser.sUsername
end end
send( sUsers, tUser.nUserID ) send(sUsers, tUser.nUserID)
end, end,
["help"] = function( tUser, sContent ) ["help"] = function(tUser, sContent)
send( "* Available commands:", tUser.nUserID ) send("* Available commands:", tUser.nUserID)
local sCommands = "*" local sCommands = "*"
for sCommand in pairs( tCommands ) do for sCommand in pairs(tCommands) do
sCommands = sCommands .. " /" .. sCommand sCommands = sCommands .. " /" .. sCommand
end end
send( sCommands .. " /logout", tUser.nUserID ) send(sCommands .. " /logout", tUser.nUserID)
end, end,
} }
local nSenderID, tMessage = rednet.receive( "chat" ) local nSenderID, tMessage = rednet.receive("chat")
if type( tMessage ) == "table" then if type(tMessage) == "table" then
if tMessage.sType == "login" then if tMessage.sType == "login" then
-- Login from new client -- Login from new client
local nUserID = tMessage.nUserID local nUserID = tMessage.nUserID
local sUsername = tMessage.sUsername local sUsername = tMessage.sUsername
if nUserID and sUsername then if nUserID and sUsername then
tUsers[ nUserID ] = { tUsers[nUserID] = {
nID = nSenderID, nID = nSenderID,
nUserID = nUserID, nUserID = nUserID,
sUsername = sUsername, sUsername = sUsername,
} }
nUsers = nUsers + 1 nUsers = nUsers + 1
printUsers() printUsers()
send( "* " .. sUsername .. " has joined the chat" ) send("* " .. sUsername .. " has joined the chat")
ping( nUserID ) ping(nUserID)
end end
else else
-- Something else from existing client -- Something else from existing client
local nUserID = tMessage.nUserID local nUserID = tMessage.nUserID
local tUser = tUsers[ nUserID ] local tUser = tUsers[nUserID]
if tUser and tUser.nID == nSenderID then if tUser and tUser.nID == nSenderID then
if tMessage.sType == "logout" then if tMessage.sType == "logout" then
send( "* " .. tUser.sUsername .. " has left the chat" ) send("* " .. tUser.sUsername .. " has left the chat")
tUsers[ nUserID ] = nil tUsers[nUserID] = nil
nUsers = nUsers - 1 nUsers = nUsers - 1
printUsers() printUsers()
elseif tMessage.sType == "chat" then elseif tMessage.sType == "chat" then
local sMessage = tMessage.sText local sMessage = tMessage.sText
if sMessage then if sMessage then
local sCommand = string.match( sMessage, "^/([a-z]+)" ) local sCommand = string.match(sMessage, "^/([a-z]+)")
if sCommand then if sCommand then
local fnCommand = tCommands[ sCommand ] local fnCommand = tCommands[sCommand]
if fnCommand then if fnCommand then
local sContent = string.sub( sMessage, #sCommand + 3 ) local sContent = string.sub(sMessage, #sCommand + 3)
fnCommand( tUser, sContent ) fnCommand(tUser, sContent)
else else
send( "* Unrecognised command: /" .. sCommand, tUser.nUserID ) send("* Unrecognised command: /" .. sCommand, tUser.nUserID)
end end
else else
send( "<" .. tUser.sUsername .. "> " .. tMessage.sText ) send("<" .. tUser.sUsername .. "> " .. tMessage.sText)
end end
end end
elseif tMessage.sType == "ping to server" then elseif tMessage.sType == "ping to server" then
rednet.send( tUser.nID, { rednet.send(tUser.nID, {
sType = "pong to client", sType = "pong to client",
nUserID = nUserID, nUserID = nUserID,
}, "chat" ) }, "chat")
elseif tMessage.sType == "pong to server" then elseif tMessage.sType == "pong to server" then
tUser.bPingPonged = true tUser.bPingPonged = true
@ -226,17 +226,17 @@ if sCommand == "host" then
end end
) )
if not ok then if not ok then
printError( error ) printError(error)
end end
-- Unhost server -- Unhost server
for nUserID, tUser in pairs( tUsers ) do for nUserID, tUser in pairs(tUsers) do
rednet.send( tUser.nID, { rednet.send(tUser.nID, {
sType = "kick", sType = "kick",
nUserID = nUserID, nUserID = nUserID,
}, "chat" ) }, "chat")
end end
rednet.unhost( "chat" ) rednet.unhost("chat")
closeModem() closeModem()
elseif sCommand == "join" then elseif sCommand == "join" then
@ -253,80 +253,80 @@ elseif sCommand == "join" then
if not openModem() then if not openModem() then
return return
end end
write( "Looking up " .. sHostname .. "... " ) write("Looking up " .. sHostname .. "... ")
local nHostID = rednet.lookup( "chat", sHostname ) local nHostID = rednet.lookup("chat", sHostname)
if nHostID == nil then if nHostID == nil then
print( "Failed." ) print("Failed.")
return return
else else
print( "Success." ) print("Success.")
end end
-- Login -- Login
local nUserID = math.random( 1, 2147483647 ) local nUserID = math.random(1, 2147483647)
rednet.send( nHostID, { rednet.send(nHostID, {
sType = "login", sType = "login",
nUserID = nUserID, nUserID = nUserID,
sUsername = sUsername, sUsername = sUsername,
}, "chat" ) }, "chat")
-- Setup ping pong -- Setup ping pong
local bPingPonged = true local bPingPonged = true
local pingPongTimer = os.startTimer( 0 ) local pingPongTimer = os.startTimer(0)
local function ping() local function ping()
rednet.send( nHostID, { rednet.send(nHostID, {
sType = "ping to server", sType = "ping to server",
nUserID = nUserID, nUserID = nUserID,
}, "chat" ) }, "chat")
bPingPonged = false bPingPonged = false
pingPongTimer = os.startTimer( 15 ) pingPongTimer = os.startTimer(15)
end end
-- Handle messages -- Handle messages
local w, h = term.getSize() local w, h = term.getSize()
local parentTerm = term.current() local parentTerm = term.current()
local titleWindow = window.create( parentTerm, 1, 1, w, 1, true ) local titleWindow = window.create(parentTerm, 1, 1, w, 1, true)
local historyWindow = window.create( parentTerm, 1, 2, w, h - 2, true ) local historyWindow = window.create(parentTerm, 1, 2, w, h - 2, true)
local promptWindow = window.create( parentTerm, 1, h, w, 1, true ) local promptWindow = window.create(parentTerm, 1, h, w, 1, true)
historyWindow.setCursorPos( 1, h - 2 ) historyWindow.setCursorPos(1, h - 2)
term.clear() term.clear()
term.setTextColour( textColour ) term.setTextColour(textColour)
term.redirect( promptWindow ) term.redirect(promptWindow)
promptWindow.restoreCursor() promptWindow.restoreCursor()
local function drawTitle() local function drawTitle()
local w = titleWindow.getSize() local w = titleWindow.getSize()
local sTitle = sUsername .. " on " .. sHostname local sTitle = sUsername .. " on " .. sHostname
titleWindow.setTextColour( highlightColour ) titleWindow.setTextColour(highlightColour)
titleWindow.setCursorPos( math.floor( w / 2 - #sTitle / 2 ), 1 ) titleWindow.setCursorPos(math.floor(w / 2 - #sTitle / 2), 1)
titleWindow.clearLine() titleWindow.clearLine()
titleWindow.write( sTitle ) titleWindow.write(sTitle)
promptWindow.restoreCursor() promptWindow.restoreCursor()
end end
local function printMessage( sMessage ) local function printMessage(sMessage)
term.redirect( historyWindow ) term.redirect(historyWindow)
print() print()
if string.match( sMessage, "^%*" ) then if string.match(sMessage, "^%*") then
-- Information -- Information
term.setTextColour( highlightColour ) term.setTextColour(highlightColour)
write( sMessage ) write(sMessage)
term.setTextColour( textColour ) term.setTextColour(textColour)
else else
-- Chat -- Chat
local sUsernameBit = string.match( sMessage, "^<[^>]*>" ) local sUsernameBit = string.match(sMessage, "^<[^>]*>")
if sUsernameBit then if sUsernameBit then
term.setTextColour( highlightColour ) term.setTextColour(highlightColour)
write( sUsernameBit ) write(sUsernameBit)
term.setTextColour( textColour ) term.setTextColour(textColour)
write( string.sub( sMessage, #sUsernameBit + 1 ) ) write(string.sub(sMessage, #sUsernameBit + 1))
else else
write( sMessage ) write(sMessage)
end end
end end
term.redirect( promptWindow ) term.redirect(promptWindow)
promptWindow.restoreCursor() promptWindow.restoreCursor()
end end
@ -339,7 +339,7 @@ elseif sCommand == "join" then
if sEvent == "timer" then if sEvent == "timer" then
if timer == pingPongTimer then if timer == pingPongTimer then
if not bPingPonged then if not bPingPonged then
printMessage( "Server timeout." ) printMessage("Server timeout.")
return return
else else
ping() ping()
@ -348,28 +348,28 @@ elseif sCommand == "join" then
elseif sEvent == "term_resize" then elseif sEvent == "term_resize" then
local w, h = parentTerm.getSize() local w, h = parentTerm.getSize()
titleWindow.reposition( 1, 1, w, 1 ) titleWindow.reposition(1, 1, w, 1)
historyWindow.reposition( 1, 2, w, h - 2 ) historyWindow.reposition(1, 2, w, h - 2)
promptWindow.reposition( 1, h, w, 1 ) promptWindow.reposition(1, h, w, 1)
end end
end end
end, end,
function() function()
while true do while true do
local nSenderID, tMessage = rednet.receive( "chat" ) local nSenderID, tMessage = rednet.receive("chat")
if nSenderID == nHostID and type( tMessage ) == "table" and tMessage.nUserID == nUserID then if nSenderID == nHostID and type(tMessage) == "table" and tMessage.nUserID == nUserID then
if tMessage.sType == "text" then if tMessage.sType == "text" then
local sText = tMessage.sText local sText = tMessage.sText
if sText then if sText then
printMessage( sText ) printMessage(sText)
end end
elseif tMessage.sType == "ping to client" then elseif tMessage.sType == "ping to client" then
rednet.send( nSenderID, { rednet.send(nSenderID, {
sType = "pong to server", sType = "pong to server",
nUserID = nUserID, nUserID = nUserID,
}, "chat" ) }, "chat")
elseif tMessage.sType == "pong to client" then elseif tMessage.sType == "pong to client" then
bPingPonged = true bPingPonged = true
@ -384,48 +384,48 @@ elseif sCommand == "join" then
function() function()
local tSendHistory = {} local tSendHistory = {}
while true do while true do
promptWindow.setCursorPos( 1, 1 ) promptWindow.setCursorPos(1, 1)
promptWindow.clearLine() promptWindow.clearLine()
promptWindow.setTextColor( highlightColour ) promptWindow.setTextColor(highlightColour)
promptWindow.write( ": " ) promptWindow.write(": ")
promptWindow.setTextColor( textColour ) promptWindow.setTextColor(textColour)
local sChat = read( nil, tSendHistory ) local sChat = read(nil, tSendHistory)
if string.match( sChat, "^/logout" ) then if string.match(sChat, "^/logout") then
break break
else else
rednet.send( nHostID, { rednet.send(nHostID, {
sType = "chat", sType = "chat",
nUserID = nUserID, nUserID = nUserID,
sText = sChat, sText = sChat,
}, "chat" ) }, "chat")
table.insert( tSendHistory, sChat ) table.insert(tSendHistory, sChat)
end end
end end
end end
) )
-- Close the windows -- Close the windows
term.redirect( parentTerm ) term.redirect(parentTerm)
-- Print error notice -- Print error notice
local _, h = term.getSize() local _, h = term.getSize()
term.setCursorPos( 1, h ) term.setCursorPos(1, h)
term.clearLine() term.clearLine()
term.setCursorBlink( false ) term.setCursorBlink(false)
if not ok then if not ok then
printError( error ) printError(error)
end end
-- Logout -- Logout
rednet.send( nHostID, { rednet.send(nHostID, {
sType = "logout", sType = "logout",
nUserID = nUserID, nUserID = nUserID,
}, "chat" ) }, "chat")
closeModem() closeModem()
-- Print disconnection notice -- Print disconnection notice
print( "Disconnected." ) print("Disconnected.")
else else
-- "chat somethingelse" -- "chat somethingelse"

View File

@ -1,40 +1,40 @@
-- Find modems -- Find modems
local tModems = {} local tModems = {}
for _, sModem in ipairs( peripheral.getNames() ) do for _, sModem in ipairs(peripheral.getNames()) do
if peripheral.getType( sModem ) == "modem" then if peripheral.getType(sModem) == "modem" then
table.insert( tModems, sModem ) table.insert(tModems, sModem)
end end
end end
if #tModems == 0 then if #tModems == 0 then
print( "No modems found." ) print("No modems found.")
return return
elseif #tModems == 1 then elseif #tModems == 1 then
print( "1 modem found." ) print("1 modem found.")
else else
print( #tModems .. " modems found." ) print(#tModems .. " modems found.")
end end
local function open( nChannel ) local function open(nChannel)
for n = 1, #tModems do for n = 1, #tModems do
local sModem = tModems[n] local sModem = tModems[n]
peripheral.call( sModem, "open", nChannel ) peripheral.call(sModem, "open", nChannel)
end end
end end
local function close( nChannel ) local function close(nChannel)
for n = 1, #tModems do for n = 1, #tModems do
local sModem = tModems[n] local sModem = tModems[n]
peripheral.call( sModem, "close", nChannel ) peripheral.call(sModem, "close", nChannel)
end end
end end
-- Open channels -- Open channels
print( "0 messages repeated." ) print("0 messages repeated.")
open( rednet.CHANNEL_REPEAT ) open(rednet.CHANNEL_REPEAT)
-- Main loop (terminate to break) -- Main loop (terminate to break)
local ok, error = pcall( function() local ok, error = pcall(function()
local tReceivedMessages = {} local tReceivedMessages = {}
local tReceivedMessageTimeouts = {} local tReceivedMessageTimeouts = {}
local nTransmittedMessages = 0 local nTransmittedMessages = 0
@ -44,28 +44,28 @@ local ok, error = pcall( function()
if sEvent == "modem_message" then if sEvent == "modem_message" then
-- Got a modem message, rebroadcast it if it's a rednet thing -- Got a modem message, rebroadcast it if it's a rednet thing
if nChannel == rednet.CHANNEL_REPEAT then if nChannel == rednet.CHANNEL_REPEAT then
if type( tMessage ) == "table" and tMessage.nMessageID and tMessage.nRecipient and type(tMessage.nRecipient) == "number" then if type(tMessage) == "table" and tMessage.nMessageID and tMessage.nRecipient and type(tMessage.nRecipient) == "number" then
if not tReceivedMessages[ tMessage.nMessageID ] then if not tReceivedMessages[tMessage.nMessageID] then
-- Ensure we only repeat a message once -- Ensure we only repeat a message once
tReceivedMessages[ tMessage.nMessageID ] = true tReceivedMessages[tMessage.nMessageID] = true
tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = tMessage.nMessageID tReceivedMessageTimeouts[os.startTimer(30)] = tMessage.nMessageID
-- Send on all other open modems, to the target and to other repeaters -- Send on all other open modems, to the target and to other repeaters
for n = 1, #tModems do for n = 1, #tModems do
local sOtherModem = tModems[n] local sOtherModem = tModems[n]
peripheral.call( sOtherModem, "transmit", rednet.CHANNEL_REPEAT, nReplyChannel, tMessage ) peripheral.call(sOtherModem, "transmit", rednet.CHANNEL_REPEAT, nReplyChannel, tMessage)
peripheral.call( sOtherModem, "transmit", tMessage.nRecipient, nReplyChannel, tMessage ) peripheral.call(sOtherModem, "transmit", tMessage.nRecipient, nReplyChannel, tMessage)
end end
-- Log the event -- Log the event
nTransmittedMessages = nTransmittedMessages + 1 nTransmittedMessages = nTransmittedMessages + 1
local _, y = term.getCursorPos() local _, y = term.getCursorPos()
term.setCursorPos( 1, y - 1 ) term.setCursorPos(1, y - 1)
term.clearLine() term.clearLine()
if nTransmittedMessages == 1 then if nTransmittedMessages == 1 then
print( nTransmittedMessages .. " message repeated." ) print(nTransmittedMessages .. " message repeated.")
else else
print( nTransmittedMessages .. " messages repeated." ) print(nTransmittedMessages .. " messages repeated.")
end end
end end
end end
@ -74,18 +74,18 @@ local ok, error = pcall( function()
elseif sEvent == "timer" then elseif sEvent == "timer" then
-- Got a timer event, use it to clear the message history -- Got a timer event, use it to clear the message history
local nTimer = sModem local nTimer = sModem
local nMessageID = tReceivedMessageTimeouts[ nTimer ] local nMessageID = tReceivedMessageTimeouts[nTimer]
if nMessageID then if nMessageID then
tReceivedMessageTimeouts[ nTimer ] = nil tReceivedMessageTimeouts[nTimer] = nil
tReceivedMessages[ nMessageID ] = nil tReceivedMessages[nMessageID] = nil
end end
end end
end end
end ) end)
if not ok then if not ok then
printError( error ) printError(error)
end end
-- Close channels -- Close channels
close( rednet.CHANNEL_REPEAT ) close(rednet.CHANNEL_REPEAT)

View File

@ -2,64 +2,64 @@
local tArgs = { ... } local tArgs = { ... }
local function printUsage() local function printUsage()
print( "Usages:" ) print("Usages:")
print( "redstone probe" ) print("redstone probe")
print( "redstone set <side> <value>" ) print("redstone set <side> <value>")
print( "redstone set <side> <color> <value>" ) print("redstone set <side> <color> <value>")
print( "redstone pulse <side> <count> <period>" ) print("redstone pulse <side> <count> <period>")
end end
local sCommand = tArgs[1] local sCommand = tArgs[1]
if sCommand == "probe" then if sCommand == "probe" then
-- "redstone probe" -- "redstone probe"
-- Regular input -- Regular input
print( "Redstone inputs: " ) print("Redstone inputs: ")
local count = 0 local count = 0
local bundledCount = 0 local bundledCount = 0
for _, sSide in ipairs( redstone.getSides() ) do for _, sSide in ipairs(redstone.getSides()) do
if redstone.getBundledInput( sSide ) > 0 then if redstone.getBundledInput(sSide) > 0 then
bundledCount = bundledCount + 1 bundledCount = bundledCount + 1
end end
if redstone.getInput( sSide ) then if redstone.getInput(sSide) then
if count > 0 then if count > 0 then
io.write( ", " ) io.write(", ")
end end
io.write( sSide ) io.write(sSide)
count = count + 1 count = count + 1
end end
end end
if count > 0 then if count > 0 then
print( "." ) print(".")
else else
print( "None." ) print("None.")
end end
-- Bundled input -- Bundled input
if bundledCount > 0 then if bundledCount > 0 then
print() print()
print( "Bundled inputs:" ) print("Bundled inputs:")
for _, sSide in ipairs( redstone.getSides() ) do for _, sSide in ipairs(redstone.getSides()) do
local nInput = redstone.getBundledInput( sSide ) local nInput = redstone.getBundledInput(sSide)
if nInput ~= 0 then if nInput ~= 0 then
write( sSide .. ": " ) write(sSide .. ": ")
local count = 0 local count = 0
for sColour, nColour in pairs( colors ) do for sColour, nColour in pairs(colors) do
if type( nColour ) == "number" and colors.test( nInput, nColour ) then if type(nColour) == "number" and colors.test(nInput, nColour) then
if count > 0 then if count > 0 then
write( ", " ) write(", ")
end end
if term.isColour() then if term.isColour() then
term.setTextColour( nColour ) term.setTextColour(nColour)
end end
write( sColour ) write(sColour)
if term.isColour() then if term.isColour() then
term.setTextColour( colours.white ) term.setTextColour(colours.white)
end end
count = count + 1 count = count + 1
end end
end end
print( "." ) print(".")
end end
end end
end end
@ -67,13 +67,13 @@ if sCommand == "probe" then
elseif sCommand == "pulse" then elseif sCommand == "pulse" then
-- "redstone pulse" -- "redstone pulse"
local sSide = tArgs[2] local sSide = tArgs[2]
local nCount = tonumber( tArgs[3] ) or 1 local nCount = tonumber(tArgs[3]) or 1
local nPeriod = tonumber( tArgs[4] ) or 0.5 local nPeriod = tonumber(tArgs[4]) or 0.5
for _ = 1, nCount do for _ = 1, nCount do
redstone.setOutput( sSide, true ) redstone.setOutput(sSide, true)
sleep( nPeriod / 2 ) sleep(nPeriod / 2)
redstone.setOutput( sSide, false ) redstone.setOutput(sSide, false)
sleep( nPeriod / 2 ) sleep(nPeriod / 2)
end end
elseif sCommand == "set" then elseif sCommand == "set" then
@ -84,30 +84,30 @@ elseif sCommand == "set" then
local sColour = tArgs[3] local sColour = tArgs[3]
local nColour = colors[sColour] or colours[sColour] local nColour = colors[sColour] or colours[sColour]
if type(nColour) ~= "number" then if type(nColour) ~= "number" then
printError( "No such color" ) printError("No such color")
return return
end end
local sValue = tArgs[4] local sValue = tArgs[4]
if sValue == "true" then if sValue == "true" then
rs.setBundledOutput( sSide, colors.combine( rs.getBundledOutput( sSide ), nColour ) ) rs.setBundledOutput(sSide, colors.combine(rs.getBundledOutput(sSide), nColour))
elseif sValue == "false" then elseif sValue == "false" then
rs.setBundledOutput( sSide, colors.subtract( rs.getBundledOutput( sSide ), nColour ) ) rs.setBundledOutput(sSide, colors.subtract(rs.getBundledOutput(sSide), nColour))
else else
print( "Value must be boolean" ) print("Value must be boolean")
end end
else else
-- Regular output -- Regular output
local sValue = tArgs[3] local sValue = tArgs[3]
local nValue = tonumber(sValue) local nValue = tonumber(sValue)
if sValue == "true" then if sValue == "true" then
rs.setOutput( sSide, true ) rs.setOutput(sSide, true)
elseif sValue == "false" then elseif sValue == "false" then
rs.setOutput( sSide, false ) rs.setOutput(sSide, false)
elseif nValue and nValue >= 0 and nValue <= 15 then elseif nValue and nValue >= 0 and nValue <= 15 then
rs.setAnalogOutput( sSide, nValue ) rs.setAnalogOutput(sSide, nValue)
else else
print( "Value must be boolean or 0-15" ) print("Value must be boolean or 0-15")
end end
end end

View File

@ -1,21 +1,21 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 2 then if #tArgs < 2 then
print( "Usage: rename <source> <destination>" ) print("Usage: rename <source> <destination>")
return return
end end
local sSource = shell.resolve( tArgs[1] ) local sSource = shell.resolve(tArgs[1])
local sDest = shell.resolve( tArgs[2] ) local sDest = shell.resolve(tArgs[2])
if not fs.exists( sSource ) then if not fs.exists(sSource) then
printError( "No matching files" ) printError("No matching files")
return return
elseif fs.exists( sDest ) then elseif fs.exists(sDest) then
printError( "Destination exists" ) printError("Destination exists")
return return
elseif fs.isReadOnly( sDest ) then elseif fs.isReadOnly(sDest) then
printError( "Destination is read-only" ) printError("Destination is read-only")
return return
end end
fs.move( sSource, sDest ) fs.move(sSource, sDest)

View File

@ -4,7 +4,7 @@ if #tArgs == 0 then
-- "set" -- "set"
local _, y = term.getCursorPos() local _, y = term.getCursorPos()
local tSettings = {} local tSettings = {}
for n, sName in ipairs( settings.getNames() ) do for n, sName in ipairs(settings.getNames()) do
tSettings[n] = textutils.serialize(sName) .. " is " .. textutils.serialize(settings.get(sName)) tSettings[n] = textutils.serialize(sName) .. " is " .. textutils.serialize(settings.get(sName))
end end
textutils.pagedPrint(table.concat(tSettings, "\n"), y - 3) textutils.pagedPrint(table.concat(tSettings, "\n"), y - 3)
@ -12,7 +12,7 @@ if #tArgs == 0 then
elseif #tArgs == 1 then elseif #tArgs == 1 then
-- "set foo" -- "set foo"
local sName = tArgs[1] local sName = tArgs[1]
print( textutils.serialize(sName) .. " is " .. textutils.serialize(settings.get(sName)) ) print(textutils.serialize(sName) .. " is " .. textutils.serialize(settings.get(sName)))
else else
-- "set foo bar" -- "set foo bar"
@ -31,15 +31,15 @@ else
value = sValue value = sValue
end end
local oldValue = settings.get( sValue ) local oldValue = settings.get(sValue)
if value ~= nil then if value ~= nil then
settings.set( sName, value ) settings.set(sName, value)
print( textutils.serialize(sName) .. " set to " .. textutils.serialize(value) ) print(textutils.serialize(sName) .. " set to " .. textutils.serialize(value))
else else
settings.unset( sName ) settings.unset(sName)
print( textutils.serialize(sName) .. " unset" ) print(textutils.serialize(sName) .. " unset")
end end
if value ~= oldValue then if value ~= oldValue then
settings.save( ".settings" ) settings.save(".settings")
end end
end end

View File

@ -5,7 +5,7 @@ local parentShell = shell
local parentTerm = term.current() local parentTerm = term.current()
if multishell then if multishell then
multishell.setTitle( multishell.getCurrent(), "shell" ) multishell.setTitle(multishell.getCurrent(), "shell")
end end
local bExit = false local bExit = false
@ -16,10 +16,10 @@ local tCompletionInfo = parentShell and parentShell.getCompletionInfo() or {}
local tProgramStack = {} local tProgramStack = {}
local shell = {} local shell = {}
local function createShellEnv( sDir ) local function createShellEnv(sDir)
local tEnv = {} local tEnv = {}
tEnv[ "shell" ] = shell tEnv.shell = shell
tEnv[ "multishell" ] = multishell tEnv.multishell = multishell
local package = {} local package = {}
package.loaded = { package.loaded = {
@ -40,14 +40,14 @@ local function createShellEnv( sDir )
package.config = "/\n;\n?\n!\n-" package.config = "/\n;\n?\n!\n-"
package.preload = {} package.preload = {}
package.loaders = { package.loaders = {
function( name ) function(name)
if package.preload[name] then if package.preload[name] then
return package.preload[name] return package.preload[name]
else else
return nil, "no field package.preload['" .. name .. "']" return nil, "no field package.preload['" .. name .. "']"
end end
end, end,
function( name ) function(name)
local fname = string.gsub(name, "%.", "/") local fname = string.gsub(name, "%.", "/")
local sError = "" local sError = ""
for pattern in string.gmatch(package.path, "[^;]+") do for pattern in string.gmatch(package.path, "[^;]+") do
@ -56,7 +56,7 @@ local function createShellEnv( sDir )
sPath = fs.combine(sDir, sPath) sPath = fs.combine(sDir, sPath)
end end
if fs.exists(sPath) and not fs.isDir(sPath) then if fs.exists(sPath) and not fs.isDir(sPath) then
local fnFile, sError = loadfile( sPath, nil, tEnv ) local fnFile, sError = loadfile(sPath, nil, tEnv)
if fnFile then if fnFile then
return fnFile, sPath return fnFile, sPath
else else
@ -74,7 +74,7 @@ local function createShellEnv( sDir )
} }
local sentinel = {} local sentinel = {}
local function require( name ) local function require(name)
expect(1, name, "string") expect(1, name, "string")
if package.loaded[name] == sentinel then if package.loaded[name] == sentinel then
error("loop or previous error loading module '" .. name .. "'", 0) error("loop or previous error loading module '" .. name .. "'", 0)
@ -100,8 +100,8 @@ local function createShellEnv( sDir )
error(sError, 2) error(sError, 2)
end end
tEnv["package"] = package tEnv.package = package
tEnv["require"] = require tEnv.require = require
return tEnv return tEnv
end end
@ -118,52 +118,52 @@ else
bgColour = colours.black bgColour = colours.black
end end
local function run( _sCommand, ... ) local function run(_sCommand, ...)
local sPath = shell.resolveProgram( _sCommand ) local sPath = shell.resolveProgram(_sCommand)
if sPath ~= nil then if sPath ~= nil then
tProgramStack[#tProgramStack + 1] = sPath tProgramStack[#tProgramStack + 1] = sPath
if multishell then if multishell then
local sTitle = fs.getName( sPath ) local sTitle = fs.getName(sPath)
if sTitle:sub(-4) == ".lua" then if sTitle:sub(-4) == ".lua" then
sTitle = sTitle:sub(1, -5) sTitle = sTitle:sub(1, -5)
end end
multishell.setTitle( multishell.getCurrent(), sTitle ) multishell.setTitle(multishell.getCurrent(), sTitle)
end end
local sDir = fs.getDir( sPath ) local sDir = fs.getDir(sPath)
local env = createShellEnv( sDir ) local env = createShellEnv(sDir)
env[ "arg" ] = { [0] = _sCommand, ... } env.arg = { [0] = _sCommand, ... }
local result = os.run( env, sPath, ... ) local result = os.run(env, sPath, ...)
tProgramStack[#tProgramStack] = nil tProgramStack[#tProgramStack] = nil
if multishell then if multishell then
if #tProgramStack > 0 then if #tProgramStack > 0 then
local sTitle = fs.getName( tProgramStack[#tProgramStack] ) local sTitle = fs.getName(tProgramStack[#tProgramStack])
if sTitle:sub(-4) == ".lua" then if sTitle:sub(-4) == ".lua" then
sTitle = sTitle:sub(1, -5) sTitle = sTitle:sub(1, -5)
end end
multishell.setTitle( multishell.getCurrent(), sTitle ) multishell.setTitle(multishell.getCurrent(), sTitle)
else else
multishell.setTitle( multishell.getCurrent(), "shell" ) multishell.setTitle(multishell.getCurrent(), "shell")
end end
end end
return result return result
else else
printError( "No such program" ) printError("No such program")
return false return false
end end
end end
local function tokenise( ... ) local function tokenise(...)
local sLine = table.concat( { ... }, " " ) local sLine = table.concat({ ... }, " ")
local tWords = {} local tWords = {}
local bQuoted = false local bQuoted = false
for match in string.gmatch( sLine .. "\"", "(.-)\"" ) do for match in string.gmatch(sLine .. "\"", "(.-)\"") do
if bQuoted then if bQuoted then
table.insert( tWords, match ) table.insert(tWords, match)
else else
for m in string.gmatch( match, "[^ \t]+" ) do for m in string.gmatch(match, "[^ \t]+") do
table.insert( tWords, m ) table.insert(tWords, m)
end end
end end
bQuoted = not bQuoted bQuoted = not bQuoted
@ -172,11 +172,11 @@ local function tokenise( ... )
end end
-- Install shell API -- Install shell API
function shell.run( ... ) function shell.run(...)
local tWords = tokenise( ... ) local tWords = tokenise(...)
local sCommand = tWords[1] local sCommand = tWords[1]
if sCommand then if sCommand then
return run( sCommand, table.unpack( tWords, 2 ) ) return run(sCommand, table.unpack(tWords, 2))
end end
return false return false
end end
@ -189,10 +189,10 @@ function shell.dir()
return sDir return sDir
end end
function shell.setDir( _sDir ) function shell.setDir(_sDir)
expect(1, _sDir, "string") expect(1, _sDir, "string")
if not fs.isDir( _sDir ) then if not fs.isDir(_sDir) then
error( "Not a directory", 2 ) error("Not a directory", 2)
end end
sDir = _sDir sDir = _sDir
end end
@ -201,46 +201,46 @@ function shell.path()
return sPath return sPath
end end
function shell.setPath( _sPath ) function shell.setPath(_sPath)
expect(1, _sPath, "string") expect(1, _sPath, "string")
sPath = _sPath sPath = _sPath
end end
function shell.resolve( _sPath ) function shell.resolve(_sPath)
expect(1, _sPath, "string") expect(1, _sPath, "string")
local sStartChar = string.sub( _sPath, 1, 1 ) local sStartChar = string.sub(_sPath, 1, 1)
if sStartChar == "/" or sStartChar == "\\" then if sStartChar == "/" or sStartChar == "\\" then
return fs.combine( "", _sPath ) return fs.combine("", _sPath)
else else
return fs.combine( sDir, _sPath ) return fs.combine(sDir, _sPath)
end end
end end
local function pathWithExtension( _sPath, _sExt ) local function pathWithExtension(_sPath, _sExt)
local nLen = #sPath local nLen = #sPath
local sEndChar = string.sub( _sPath, nLen, nLen ) local sEndChar = string.sub(_sPath, nLen, nLen)
-- Remove any trailing slashes so we can add an extension to the path safely -- Remove any trailing slashes so we can add an extension to the path safely
if sEndChar == "/" or sEndChar == "\\" then if sEndChar == "/" or sEndChar == "\\" then
_sPath = string.sub( _sPath, 1, nLen - 1 ) _sPath = string.sub(_sPath, 1, nLen - 1)
end end
return _sPath .. "." .. _sExt return _sPath .. "." .. _sExt
end end
function shell.resolveProgram( _sCommand ) function shell.resolveProgram(_sCommand)
expect(1, _sCommand, "string") expect(1, _sCommand, "string")
-- Substitute aliases firsts -- Substitute aliases firsts
if tAliases[ _sCommand ] ~= nil then if tAliases[_sCommand] ~= nil then
_sCommand = tAliases[ _sCommand ] _sCommand = tAliases[_sCommand]
end end
-- If the path is a global path, use it directly -- If the path is a global path, use it directly
if _sCommand:find("/") or _sCommand:find("\\") then if _sCommand:find("/") or _sCommand:find("\\") then
local sPath = shell.resolve( _sCommand ) local sPath = shell.resolve(_sCommand)
if fs.exists( sPath ) and not fs.isDir( sPath ) then if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath return sPath
else else
local sPathLua = pathWithExtension( sPath, "lua" ) local sPathLua = pathWithExtension(sPath, "lua")
if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
return sPathLua return sPathLua
end end
end end
@ -249,12 +249,12 @@ function shell.resolveProgram( _sCommand )
-- Otherwise, look on the path variable -- Otherwise, look on the path variable
for sPath in string.gmatch(sPath, "[^:]+") do for sPath in string.gmatch(sPath, "[^:]+") do
sPath = fs.combine( shell.resolve( sPath ), _sCommand ) sPath = fs.combine(shell.resolve(sPath), _sCommand)
if fs.exists( sPath ) and not fs.isDir( sPath ) then if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath return sPath
else else
local sPathLua = pathWithExtension( sPath, "lua" ) local sPathLua = pathWithExtension(sPath, "lua")
if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
return sPathLua return sPathLua
end end
end end
@ -264,22 +264,22 @@ function shell.resolveProgram( _sCommand )
return nil return nil
end end
function shell.programs( _bIncludeHidden ) function shell.programs(_bIncludeHidden)
local tItems = {} local tItems = {}
-- Add programs from the path -- Add programs from the path
for sPath in string.gmatch(sPath, "[^:]+") do for sPath in string.gmatch(sPath, "[^:]+") do
sPath = shell.resolve( sPath ) sPath = shell.resolve(sPath)
if fs.isDir( sPath ) then if fs.isDir(sPath) then
local tList = fs.list( sPath ) local tList = fs.list(sPath)
for n = 1, #tList do for n = 1, #tList do
local sFile = tList[n] local sFile = tList[n]
if not fs.isDir( fs.combine( sPath, sFile ) ) and if not fs.isDir(fs.combine(sPath, sFile)) and
(_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= ".") then (_bIncludeHidden or string.sub(sFile, 1, 1) ~= ".") then
if #sFile > 4 and sFile:sub(-4) == ".lua" then if #sFile > 4 and sFile:sub(-4) == ".lua" then
sFile = sFile:sub(1, -5) sFile = sFile:sub(1, -5)
end end
tItems[ sFile ] = true tItems[sFile] = true
end end
end end
end end
@ -287,40 +287,40 @@ function shell.programs( _bIncludeHidden )
-- Sort and return -- Sort and return
local tItemList = {} local tItemList = {}
for sItem in pairs( tItems ) do for sItem in pairs(tItems) do
table.insert( tItemList, sItem ) table.insert(tItemList, sItem)
end end
table.sort( tItemList ) table.sort(tItemList)
return tItemList return tItemList
end end
local function completeProgram( sLine ) local function completeProgram(sLine)
if #sLine > 0 and (sLine:find("/") or sLine:find("\\")) then if #sLine > 0 and (sLine:find("/") or sLine:find("\\")) then
-- Add programs from the root -- Add programs from the root
return fs.complete( sLine, sDir, true, false ) return fs.complete(sLine, sDir, true, false)
else else
local tResults = {} local tResults = {}
local tSeen = {} local tSeen = {}
-- Add aliases -- Add aliases
for sAlias in pairs( tAliases ) do for sAlias in pairs(tAliases) do
if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then if #sAlias > #sLine and string.sub(sAlias, 1, #sLine) == sLine then
local sResult = string.sub( sAlias, #sLine + 1 ) local sResult = string.sub(sAlias, #sLine + 1)
if not tSeen[ sResult ] then if not tSeen[sResult] then
table.insert( tResults, sResult ) table.insert(tResults, sResult)
tSeen[ sResult ] = true tSeen[sResult] = true
end end
end end
end end
-- Add all subdirectories. We don't include files as they will be added in the block below -- Add all subdirectories. We don't include files as they will be added in the block below
local tDirs = fs.complete( sLine, sDir, false, false ) local tDirs = fs.complete(sLine, sDir, false, false)
for i = 1, #tDirs do for i = 1, #tDirs do
local sResult = tDirs[i] local sResult = tDirs[i]
if not tSeen[ sResult ] then if not tSeen[sResult] then
table.insert ( tResults, sResult ) table.insert (tResults, sResult)
tSeen [ sResult ] = true tSeen [sResult] = true
end end
end end
@ -328,48 +328,48 @@ local function completeProgram( sLine )
local tPrograms = shell.programs() local tPrograms = shell.programs()
for n = 1, #tPrograms do for n = 1, #tPrograms do
local sProgram = tPrograms[n] local sProgram = tPrograms[n]
if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then if #sProgram > #sLine and string.sub(sProgram, 1, #sLine) == sLine then
local sResult = string.sub( sProgram, #sLine + 1 ) local sResult = string.sub(sProgram, #sLine + 1)
if not tSeen[ sResult ] then if not tSeen[sResult] then
table.insert( tResults, sResult ) table.insert(tResults, sResult)
tSeen[ sResult ] = true tSeen[sResult] = true
end end
end end
end end
-- Sort and return -- Sort and return
table.sort( tResults ) table.sort(tResults)
return tResults return tResults
end end
end end
local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts ) local function completeProgramArgument(sProgram, nArgument, sPart, tPreviousParts)
local tInfo = tCompletionInfo[ sProgram ] local tInfo = tCompletionInfo[sProgram]
if tInfo then if tInfo then
return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts ) return tInfo.fnComplete(shell, nArgument, sPart, tPreviousParts)
end end
return nil return nil
end end
function shell.complete( sLine ) function shell.complete(sLine)
expect(1, sLine, "string") expect(1, sLine, "string")
if #sLine > 0 then if #sLine > 0 then
local tWords = tokenise( sLine ) local tWords = tokenise(sLine)
local nIndex = #tWords local nIndex = #tWords
if string.sub( sLine, #sLine, #sLine ) == " " then if string.sub(sLine, #sLine, #sLine) == " " then
nIndex = nIndex + 1 nIndex = nIndex + 1
end end
if nIndex == 1 then if nIndex == 1 then
local sBit = tWords[1] or "" local sBit = tWords[1] or ""
local sPath = shell.resolveProgram( sBit ) local sPath = shell.resolveProgram(sBit)
if tCompletionInfo[ sPath ] then if tCompletionInfo[sPath] then
return { " " } return { " " }
else else
local tResults = completeProgram( sBit ) local tResults = completeProgram(sBit)
for n = 1, #tResults do for n = 1, #tResults do
local sResult = tResults[n] local sResult = tResults[n]
local sPath = shell.resolveProgram( sBit .. sResult ) local sPath = shell.resolveProgram(sBit .. sResult)
if tCompletionInfo[ sPath ] then if tCompletionInfo[sPath] then
tResults[n] = sResult .. " " tResults[n] = sResult .. " "
end end
end end
@ -377,26 +377,26 @@ function shell.complete( sLine )
end end
elseif nIndex > 1 then elseif nIndex > 1 then
local sPath = shell.resolveProgram( tWords[1] ) local sPath = shell.resolveProgram(tWords[1])
local sPart = tWords[nIndex] or "" local sPart = tWords[nIndex] or ""
local tPreviousParts = tWords local tPreviousParts = tWords
tPreviousParts[nIndex] = nil tPreviousParts[nIndex] = nil
return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts ) return completeProgramArgument(sPath , nIndex - 1, sPart, tPreviousParts)
end end
end end
return nil return nil
end end
function shell.completeProgram( sProgram ) function shell.completeProgram(sProgram)
expect(1, sProgram, "string") expect(1, sProgram, "string")
return completeProgram( sProgram ) return completeProgram(sProgram)
end end
function shell.setCompletionFunction( sProgram, fnComplete ) function shell.setCompletionFunction(sProgram, fnComplete)
expect(1, sProgram, "string") expect(1, sProgram, "string")
expect(2, fnComplete, "function") expect(2, fnComplete, "function")
tCompletionInfo[ sProgram ] = { tCompletionInfo[sProgram] = {
fnComplete = fnComplete, fnComplete = fnComplete,
} }
end end
@ -412,45 +412,45 @@ function shell.getRunningProgram()
return nil return nil
end end
function shell.setAlias( _sCommand, _sProgram ) function shell.setAlias(_sCommand, _sProgram)
expect(1, _sCommand, "string") expect(1, _sCommand, "string")
expect(2, _sProgram, "string") expect(2, _sProgram, "string")
tAliases[ _sCommand ] = _sProgram tAliases[_sCommand] = _sProgram
end end
function shell.clearAlias( _sCommand ) function shell.clearAlias(_sCommand)
expect(1, _sCommand, "string") expect(1, _sCommand, "string")
tAliases[ _sCommand ] = nil tAliases[_sCommand] = nil
end end
function shell.aliases() function shell.aliases()
-- Copy aliases -- Copy aliases
local tCopy = {} local tCopy = {}
for sAlias, sCommand in pairs( tAliases ) do for sAlias, sCommand in pairs(tAliases) do
tCopy[sAlias] = sCommand tCopy[sAlias] = sCommand
end end
return tCopy return tCopy
end end
if multishell then if multishell then
function shell.openTab( ... ) function shell.openTab(...)
local tWords = tokenise( ... ) local tWords = tokenise(...)
local sCommand = tWords[1] local sCommand = tWords[1]
if sCommand then if sCommand then
local sPath = shell.resolveProgram( sCommand ) local sPath = shell.resolveProgram(sCommand)
if sPath == "rom/programs/shell.lua" then if sPath == "rom/programs/shell.lua" then
return multishell.launch( createShellEnv( "rom/programs" ), sPath, table.unpack( tWords, 2 ) ) return multishell.launch(createShellEnv("rom/programs"), sPath, table.unpack(tWords, 2))
elseif sPath ~= nil then elseif sPath ~= nil then
return multishell.launch( createShellEnv( "rom/programs" ), "rom/programs/shell.lua", sCommand, table.unpack( tWords, 2 ) ) return multishell.launch(createShellEnv("rom/programs"), "rom/programs/shell.lua", sCommand, table.unpack(tWords, 2))
else else
printError( "No such program" ) printError("No such program")
end end
end end
end end
function shell.switchTab( nID ) function shell.switchTab(nID)
expect(1, nID, "number") expect(1, nID, "number")
multishell.setFocus( nID ) multishell.setFocus(nID)
end end
end end
@ -458,40 +458,40 @@ local tArgs = { ... }
if #tArgs > 0 then if #tArgs > 0 then
-- "shell x y z" -- "shell x y z"
-- Run the program specified on the commandline -- Run the program specified on the commandline
shell.run( ... ) shell.run(...)
else else
-- "shell" -- "shell"
-- Print the header -- Print the header
term.setBackgroundColor( bgColour ) term.setBackgroundColor(bgColour)
term.setTextColour( promptColour ) term.setTextColour(promptColour)
print( os.version() ) print(os.version())
term.setTextColour( textColour ) term.setTextColour(textColour)
-- Run the startup program -- Run the startup program
if parentShell == nil then if parentShell == nil then
shell.run( "/rom/startup.lua" ) shell.run("/rom/startup.lua")
end end
-- Read commands and execute them -- Read commands and execute them
local tCommandHistory = {} local tCommandHistory = {}
while not bExit do while not bExit do
term.redirect( parentTerm ) term.redirect(parentTerm)
term.setBackgroundColor( bgColour ) term.setBackgroundColor(bgColour)
term.setTextColour( promptColour ) term.setTextColour(promptColour)
write( shell.dir() .. "> " ) write(shell.dir() .. "> ")
term.setTextColour( textColour ) term.setTextColour(textColour)
local sLine local sLine
if settings.get( "shell.autocomplete" ) then if settings.get("shell.autocomplete") then
sLine = read( nil, tCommandHistory, shell.complete ) sLine = read(nil, tCommandHistory, shell.complete)
else else
sLine = read( nil, tCommandHistory ) sLine = read(nil, tCommandHistory)
end end
if sLine:match("%S") and tCommandHistory[#tCommandHistory] ~= sLine then if sLine:match("%S") and tCommandHistory[#tCommandHistory] ~= sLine then
table.insert( tCommandHistory, sLine ) table.insert(tCommandHistory, sLine)
end end
shell.run( sLine ) shell.run(sLine)
end end
end end

View File

@ -1,8 +1,8 @@
if term.isColour() then if term.isColour() then
term.setTextColour( colours.yellow ) term.setTextColour(colours.yellow)
end end
print( "Goodbye" ) print("Goodbye")
term.setTextColour( colours.white ) term.setTextColour(colours.white)
sleep( 1 ) sleep(1)
os.shutdown() os.shutdown()

View File

@ -1,3 +1,3 @@
local nTime = os.time() local nTime = os.time()
local nDay = os.day() local nDay = os.day()
print( "The time is " .. textutils.formatTime( nTime, false ) .. " on Day " .. nDay ) print("The time is " .. textutils.formatTime(nTime, false) .. " on Day " .. nDay)

View File

@ -1,26 +1,26 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
if not turtle.craft then if not turtle.craft then
print( "Requires a Crafty Turtle" ) print("Requires a Crafty Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
local nLimit = nil local nLimit = nil
if #tArgs < 1 then if #tArgs < 1 then
print( "Usage: craft [number]" ) print("Usage: craft [number]")
return return
else else
nLimit = tonumber( tArgs[1] ) nLimit = tonumber(tArgs[1])
end end
local nCrafted = 0 local nCrafted = 0
local nOldCount = turtle.getItemCount( turtle.getSelectedSlot() ) local nOldCount = turtle.getItemCount(turtle.getSelectedSlot())
if turtle.craft( nLimit ) then if turtle.craft(nLimit) then
local nNewCount = turtle.getItemCount( turtle.getSelectedSlot() ) local nNewCount = turtle.getItemCount(turtle.getSelectedSlot())
if nOldCount <= nLimit then if nOldCount <= nLimit then
nCrafted = nNewCount nCrafted = nNewCount
else else
@ -29,9 +29,9 @@ if turtle.craft( nLimit ) then
end end
if nCrafted > 1 then if nCrafted > 1 then
print( nCrafted .. " items crafted" ) print(nCrafted .. " items crafted")
elseif nCrafted == 1 then elseif nCrafted == 1 then
print( "1 item crafted" ) print("1 item crafted")
else else
print( "No items crafted" ) print("No items crafted")
end end

View File

@ -1,5 +1,5 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
end end
local tMoves = { local tMoves = {
@ -77,20 +77,20 @@ local tMoves = {
end, end,
} }
textutils.slowWrite( "Preparing to get down." ) textutils.slowWrite("Preparing to get down.")
textutils.slowPrint( "..", 0.75 ) textutils.slowPrint("..", 0.75)
local sAudio = nil local sAudio = nil
for _, sName in pairs( peripheral.getNames() ) do for _, sName in pairs(peripheral.getNames()) do
if disk.hasAudio( sName ) then if disk.hasAudio(sName) then
disk.playAudio( sName ) disk.playAudio(sName)
print( "Jamming to " .. disk.getAudioTitle( sName ) ) print("Jamming to " .. disk.getAudioTitle(sName))
sAudio = sName sAudio = sName
break break
end end
end end
print( "Press any key to stop the groove" ) print("Press any key to stop the groove")
parallel.waitForAny( parallel.waitForAny(
function() function()
@ -110,5 +110,5 @@ parallel.waitForAny(
) )
if sAudio then if sAudio then
disk.stopAudio( sAudio ) disk.stopAudio(sAudio)
end end

View File

@ -1,11 +1,11 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
local function printUsage() local function printUsage()
print( "Usage: equip <slot> <side>" ) print("Usage: equip <slot> <side>")
end end
if #tArgs ~= 2 then if #tArgs ~= 2 then
@ -13,29 +13,29 @@ if #tArgs ~= 2 then
return return
end end
local function equip( nSlot, fnEquipFunction ) local function equip(nSlot, fnEquipFunction)
turtle.select( nSlot ) turtle.select(nSlot)
local nOldCount = turtle.getItemCount( nSlot ) local nOldCount = turtle.getItemCount(nSlot)
if nOldCount == 0 then if nOldCount == 0 then
print( "Nothing to equip" ) print("Nothing to equip")
elseif fnEquipFunction() then elseif fnEquipFunction() then
local nNewCount = turtle.getItemCount( nSlot ) local nNewCount = turtle.getItemCount(nSlot)
if nNewCount > 0 then if nNewCount > 0 then
print( "Items swapped" ) print("Items swapped")
else else
print( "Item equipped" ) print("Item equipped")
end end
else else
print( "Item not equippable" ) print("Item not equippable")
end end
end end
local nSlot = tonumber( tArgs[1] ) local nSlot = tonumber(tArgs[1])
local sSide = tArgs[2] local sSide = tArgs[2]
if sSide == "left" then if sSide == "left" then
equip( nSlot, turtle.equipLeft ) equip(nSlot, turtle.equipLeft)
elseif sSide == "right" then elseif sSide == "right" then
equip( nSlot, turtle.equipRight ) equip(nSlot, turtle.equipRight)
else else
printUsage() printUsage()
return return

View File

@ -1,18 +1,18 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
if #tArgs ~= 1 then if #tArgs ~= 1 then
print( "Usage: excavate <diameter>" ) print("Usage: excavate <diameter>")
return return
end end
-- Mine in a quarry pattern until we hit something we can't dig -- Mine in a quarry pattern until we hit something we can't dig
local size = tonumber( tArgs[1] ) local size = tonumber(tArgs[1])
if size < 1 then if size < 1 then
print( "Excavate diameter must be positive" ) print("Excavate diameter must be positive")
return return
end end
@ -26,8 +26,8 @@ local xDir, zDir = 0, 1
local goTo -- Filled in further down local goTo -- Filled in further down
local refuel -- Filled in further down local refuel -- Filled in further down
local function unload( _bKeepOneFuelStack ) local function unload(_bKeepOneFuelStack)
print( "Unloading items..." ) print("Unloading items...")
for n = 1, 16 do for n = 1, 16 do
local nCount = turtle.getItemCount(n) local nCount = turtle.getItemCount(n)
if nCount > 0 then if nCount > 0 then
@ -49,22 +49,22 @@ end
local function returnSupplies() local function returnSupplies()
local x, y, z, xd, zd = xPos, depth, zPos, xDir, zDir local x, y, z, xd, zd = xPos, depth, zPos, xDir, zDir
print( "Returning to surface..." ) print("Returning to surface...")
goTo( 0, 0, 0, 0, -1 ) goTo(0, 0, 0, 0, -1)
local fuelNeeded = 2 * (x + y + z) + 1 local fuelNeeded = 2 * (x + y + z) + 1
if not refuel( fuelNeeded ) then if not refuel(fuelNeeded) then
unload( true ) unload(true)
print( "Waiting for fuel" ) print("Waiting for fuel")
while not refuel( fuelNeeded ) do while not refuel(fuelNeeded) do
os.pullEvent( "turtle_inventory" ) os.pullEvent("turtle_inventory")
end end
else else
unload( true ) unload(true)
end end
print( "Resuming mining..." ) print("Resuming mining...")
goTo( x, y, z, xd, zd ) goTo(x, y, z, xd, zd)
end end
local function collect() local function collect()
@ -81,18 +81,18 @@ local function collect()
if nTotalItems > collected then if nTotalItems > collected then
collected = nTotalItems collected = nTotalItems
if math.fmod(collected + unloaded, 50) == 0 then if math.fmod(collected + unloaded, 50) == 0 then
print( "Mined " .. collected + unloaded .. " items." ) print("Mined " .. collected + unloaded .. " items.")
end end
end end
if bFull then if bFull then
print( "No empty slots left." ) print("No empty slots left.")
return false return false
end end
return true return true
end end
function refuel( ammount ) function refuel(ammount)
local fuelLevel = turtle.getFuelLevel() local fuelLevel = turtle.getFuelLevel()
if fuelLevel == "unlimited" then if fuelLevel == "unlimited" then
return true return true
@ -123,7 +123,7 @@ end
local function tryForwards() local function tryForwards()
if not refuel() then if not refuel() then
print( "Not enough Fuel" ) print("Not enough Fuel")
returnSupplies() returnSupplies()
end end
@ -141,7 +141,7 @@ local function tryForwards()
returnSupplies() returnSupplies()
end end
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
@ -152,7 +152,7 @@ end
local function tryDown() local function tryDown()
if not refuel() then if not refuel() then
print( "Not enough Fuel" ) print("Not enough Fuel")
returnSupplies() returnSupplies()
end end
@ -170,13 +170,13 @@ local function tryDown()
returnSupplies() returnSupplies()
end end
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
depth = depth + 1 depth = depth + 1
if math.fmod( depth, 10 ) == 0 then if math.fmod(depth, 10) == 0 then
print( "Descended " .. depth .. " metres." ) print("Descended " .. depth .. " metres.")
end end
return true return true
@ -192,14 +192,14 @@ local function turnRight()
xDir, zDir = zDir, -xDir xDir, zDir = zDir, -xDir
end end
function goTo( x, y, z, xd, zd ) function goTo(x, y, z, xd, zd)
while depth > y do while depth > y do
if turtle.up() then if turtle.up() then
depth = depth - 1 depth = depth - 1
elseif turtle.digUp() or turtle.attackUp() then elseif turtle.digUp() or turtle.attackUp() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
@ -213,7 +213,7 @@ function goTo( x, y, z, xd, zd )
elseif turtle.dig() or turtle.attack() then elseif turtle.dig() or turtle.attack() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
elseif xPos < x then elseif xPos < x then
@ -226,7 +226,7 @@ function goTo( x, y, z, xd, zd )
elseif turtle.dig() or turtle.attack() then elseif turtle.dig() or turtle.attack() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
end end
@ -241,7 +241,7 @@ function goTo( x, y, z, xd, zd )
elseif turtle.dig() or turtle.attack() then elseif turtle.dig() or turtle.attack() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
elseif zPos < z then elseif zPos < z then
@ -254,7 +254,7 @@ function goTo( x, y, z, xd, zd )
elseif turtle.dig() or turtle.attack() then elseif turtle.dig() or turtle.attack() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
end end
@ -265,7 +265,7 @@ function goTo( x, y, z, xd, zd )
elseif turtle.digDown() or turtle.attackDown() then elseif turtle.digDown() or turtle.attackDown() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
@ -275,11 +275,11 @@ function goTo( x, y, z, xd, zd )
end end
if not refuel() then if not refuel() then
print( "Out of Fuel" ) print("Out of Fuel")
return return
end end
print( "Excavating..." ) print("Excavating...")
local reseal = false local reseal = false
turtle.select(1) turtle.select(1)
@ -341,16 +341,16 @@ while not done do
end end
end end
print( "Returning to surface..." ) print("Returning to surface...")
-- Return to where we started -- Return to where we started
goTo( 0, 0, 0, 0, -1 ) goTo(0, 0, 0, 0, -1)
unload( false ) unload(false)
goTo( 0, 0, 0, 0, 1 ) goTo(0, 0, 0, 0, 1)
-- Seal the hole -- Seal the hole
if reseal then if reseal then
turtle.placeDown() turtle.placeDown()
end end
print( "Mined " .. collected + unloaded .. " items total." ) print("Mined " .. collected + unloaded .. " items total.")

View File

@ -1,11 +1,11 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 1 then if #tArgs < 1 then
print( "Usage: go <direction> <distance>" ) print("Usage: go <direction> <distance>")
return return
end end
@ -29,7 +29,7 @@ while nArg <= #tArgs do
local sDirection = tArgs[nArg] local sDirection = tArgs[nArg]
local nDistance = 1 local nDistance = 1
if nArg < #tArgs then if nArg < #tArgs then
local num = tonumber( tArgs[nArg + 1] ) local num = tonumber(tArgs[nArg + 1])
if num then if num then
nDistance = num nDistance = num
nArg = nArg + 1 nArg = nArg + 1
@ -43,15 +43,15 @@ while nArg <= #tArgs do
if fnHandler() then if fnHandler() then
nDistance = nDistance - 1 nDistance = nDistance - 1
elseif turtle.getFuelLevel() == 0 then elseif turtle.getFuelLevel() == 0 then
print( "Out of fuel" ) print("Out of fuel")
return return
else else
sleep(0.5) sleep(0.5)
end end
end end
else else
print( "No such direction: " .. sDirection ) print("No such direction: " .. sDirection)
print( "Try: forward, back, up, down" ) print("Try: forward, back, up, down")
return return
end end

View File

@ -1,18 +1,18 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
local nLimit = 1 local nLimit = 1
if #tArgs > 1 then if #tArgs > 1 then
print( "Usage: refuel [number]" ) print("Usage: refuel [number]")
return return
elseif #tArgs > 0 then elseif #tArgs > 0 then
if tArgs[1] == "all" then if tArgs[1] == "all" then
nLimit = nil nLimit = nil
else else
nLimit = tonumber( tArgs[1] ) nLimit = tonumber(tArgs[1])
if not nLimit then if not nLimit then
print("Invalid limit, expected a number or \"all\"") print("Invalid limit, expected a number or \"all\"")
return return
@ -29,17 +29,17 @@ if turtle.getFuelLevel() ~= "unlimited" then
local nCount = turtle.getItemCount(n) local nCount = turtle.getItemCount(n)
if nCount > 0 then if nCount > 0 then
turtle.select( n ) turtle.select(n)
if turtle.refuel( nLimit ) and nLimit then if turtle.refuel(nLimit) and nLimit then
local nNewCount = turtle.getItemCount(n) local nNewCount = turtle.getItemCount(n)
nLimit = nLimit - (nCount - nNewCount) nLimit = nLimit - (nCount - nNewCount)
end end
end end
end end
print( "Fuel level is " .. turtle.getFuelLevel() ) print("Fuel level is " .. turtle.getFuelLevel())
if turtle.getFuelLevel() == turtle.getFuelLimit() then if turtle.getFuelLevel() == turtle.getFuelLimit() then
print( "Fuel limit reached" ) print("Fuel limit reached")
end end
else else
print( "Fuel level is unlimited" ) print("Fuel level is unlimited")
end end

View File

@ -1,18 +1,18 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
if #tArgs ~= 1 then if #tArgs ~= 1 then
print( "Usage: tunnel <length>" ) print("Usage: tunnel <length>")
return return
end end
-- Mine in a quarry pattern until we hit something we can't dig -- Mine in a quarry pattern until we hit something we can't dig
local length = tonumber( tArgs[1] ) local length = tonumber(tArgs[1])
if length < 1 then if length < 1 then
print( "Tunnel length must be positive" ) print("Tunnel length must be positive")
return return
end end
local collected = 0 local collected = 0
@ -20,7 +20,7 @@ local collected = 0
local function collect() local function collect()
collected = collected + 1 collected = collected + 1
if math.fmod(collected, 25) == 0 then if math.fmod(collected, 25) == 0 then
print( "Mined " .. collected .. " items." ) print("Mined " .. collected .. " items.")
end end
end end
@ -81,11 +81,11 @@ local function refuel()
end end
if not tryRefuel() then if not tryRefuel() then
print( "Add more fuel to continue." ) print("Add more fuel to continue.")
while not tryRefuel() do while not tryRefuel() do
os.pullEvent( "turtle_inventory" ) os.pullEvent("turtle_inventory")
end end
print( "Resuming Tunnel." ) print("Resuming Tunnel.")
end end
end end
@ -99,7 +99,7 @@ local function tryUp()
elseif turtle.attackUp() then elseif turtle.attackUp() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
return true return true
@ -115,7 +115,7 @@ local function tryDown()
elseif turtle.attackDown() then elseif turtle.attackDown() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
return true return true
@ -131,13 +131,13 @@ local function tryForward()
elseif turtle.attack() then elseif turtle.attack() then
collect() collect()
else else
sleep( 0.5 ) sleep(0.5)
end end
end end
return true return true
end end
print( "Tunnelling..." ) print("Tunnelling...")
for n = 1, length do for n = 1, length do
turtle.placeDown() turtle.placeDown()
@ -156,11 +156,11 @@ for n = 1, length do
if n < length then if n < length then
tryDig() tryDig()
if not tryForward() then if not tryForward() then
print( "Aborting Tunnel." ) print("Aborting Tunnel.")
break break
end end
else else
print( "Tunnel complete." ) print("Tunnel complete.")
end end
end end
@ -182,5 +182,5 @@ turtle.turnRight()
turtle.turnRight() turtle.turnRight()
]] ]]
print( "Tunnel complete." ) print("Tunnel complete.")
print( "Mined " .. collected .. " items total." ) print("Mined " .. collected .. " items total.")

View File

@ -1,11 +1,11 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 1 then if #tArgs < 1 then
print( "Usage: turn <direction> <turns>" ) print("Usage: turn <direction> <turns>")
return return
end end
@ -21,7 +21,7 @@ while nArg <= #tArgs do
local sDirection = tArgs[nArg] local sDirection = tArgs[nArg]
local nDistance = 1 local nDistance = 1
if nArg < #tArgs then if nArg < #tArgs then
local num = tonumber( tArgs[nArg + 1] ) local num = tonumber(tArgs[nArg + 1])
if num then if num then
nDistance = num nDistance = num
nArg = nArg + 1 nArg = nArg + 1
@ -32,11 +32,11 @@ while nArg <= #tArgs do
local fnHandler = tHandlers[string.lower(sDirection)] local fnHandler = tHandlers[string.lower(sDirection)]
if fnHandler then if fnHandler then
for _ = 1, nDistance do for _ = 1, nDistance do
fnHandler( nArg ) fnHandler(nArg)
end end
else else
print( "No such direction: " .. sDirection ) print("No such direction: " .. sDirection)
print( "Try: left, right" ) print("Try: left, right")
return return
end end
end end

View File

@ -1,11 +1,11 @@
if not turtle then if not turtle then
printError( "Requires a Turtle" ) printError("Requires a Turtle")
return return
end end
local tArgs = { ... } local tArgs = { ... }
local function printUsage() local function printUsage()
print( "Usage: unequip <side>" ) print("Usage: unequip <side>")
end end
if #tArgs ~= 1 then if #tArgs ~= 1 then
@ -13,31 +13,31 @@ if #tArgs ~= 1 then
return return
end end
local function unequip( fnEquipFunction ) local function unequip(fnEquipFunction)
for nSlot = 1, 16 do for nSlot = 1, 16 do
local nOldCount = turtle.getItemCount( nSlot ) local nOldCount = turtle.getItemCount(nSlot)
if nOldCount == 0 then if nOldCount == 0 then
turtle.select( nSlot ) turtle.select(nSlot)
if fnEquipFunction() then if fnEquipFunction() then
local nNewCount = turtle.getItemCount( nSlot ) local nNewCount = turtle.getItemCount(nSlot)
if nNewCount > 0 then if nNewCount > 0 then
print( "Item unequipped" ) print("Item unequipped")
return return
else else
print( "Nothing to unequip" ) print("Nothing to unequip")
return return
end end
end end
end end
end end
print( "No space to unequip item" ) print("No space to unequip item")
end end
local sSide = tArgs[1] local sSide = tArgs[1]
if sSide == "left" then if sSide == "left" then
unequip( turtle.equipLeft ) unequip(turtle.equipLeft)
elseif sSide == "right" then elseif sSide == "right" then
unequip( turtle.equipRight ) unequip(turtle.equipRight)
else else
printUsage() printUsage()
return return

View File

@ -1,18 +1,18 @@
local tArgs = { ... } local tArgs = { ... }
if #tArgs < 1 then if #tArgs < 1 then
print( "Usage: type <path>" ) print("Usage: type <path>")
return return
end end
local sPath = shell.resolve( tArgs[1] ) local sPath = shell.resolve(tArgs[1])
if fs.exists( sPath ) then if fs.exists(sPath) then
if fs.isDir( sPath ) then if fs.isDir(sPath) then
print( "directory" ) print("directory")
else else
print( "file" ) print("file")
end end
else else
print( "No such path" ) print("No such path")
end end

View File

@ -22,130 +22,130 @@ end
if http then if http then
sPath = sPath .. ":/rom/programs/http" sPath = sPath .. ":/rom/programs/http"
end end
shell.setPath( sPath ) shell.setPath(sPath)
help.setPath( "/rom/help" ) help.setPath("/rom/help")
-- Setup aliases -- Setup aliases
shell.setAlias( "ls", "list" ) shell.setAlias("ls", "list")
shell.setAlias( "dir", "list" ) shell.setAlias("dir", "list")
shell.setAlias( "cp", "copy" ) shell.setAlias("cp", "copy")
shell.setAlias( "mv", "move" ) shell.setAlias("mv", "move")
shell.setAlias( "rm", "delete" ) shell.setAlias("rm", "delete")
shell.setAlias( "clr", "clear" ) shell.setAlias("clr", "clear")
shell.setAlias( "rs", "redstone" ) shell.setAlias("rs", "redstone")
shell.setAlias( "sh", "shell" ) shell.setAlias("sh", "shell")
if term.isColor() then if term.isColor() then
shell.setAlias( "background", "bg" ) shell.setAlias("background", "bg")
shell.setAlias( "foreground", "fg" ) shell.setAlias("foreground", "fg")
end end
-- Setup completion functions -- Setup completion functions
local function completePastebinPut(shell, text, previous) local function completePastebinPut(shell, text, previous)
if previous[2] == "put" then if previous[2] == "put" then
return fs.complete( text, shell.dir(), true, false ) return fs.complete(text, shell.dir(), true, false)
end end
end end
shell.setCompletionFunction( "rom/programs/alias.lua", completion.build(nil, completion.program) ) shell.setCompletionFunction("rom/programs/alias.lua", completion.build(nil, completion.program))
shell.setCompletionFunction( "rom/programs/cd.lua", completion.build(completion.dir) ) shell.setCompletionFunction("rom/programs/cd.lua", completion.build(completion.dir))
shell.setCompletionFunction( "rom/programs/copy.lua", completion.build( shell.setCompletionFunction("rom/programs/copy.lua", completion.build(
{ completion.dirOrFile, true }, { completion.dirOrFile, true },
completion.dirOrFile completion.dirOrFile
) ) ))
shell.setCompletionFunction( "rom/programs/delete.lua", completion.build({ completion.dirOrFile, many = true }) ) shell.setCompletionFunction("rom/programs/delete.lua", completion.build({ completion.dirOrFile, many = true }))
shell.setCompletionFunction( "rom/programs/drive.lua", completion.build(completion.dir) ) shell.setCompletionFunction("rom/programs/drive.lua", completion.build(completion.dir))
shell.setCompletionFunction( "rom/programs/edit.lua", completion.build(completion.file) ) shell.setCompletionFunction("rom/programs/edit.lua", completion.build(completion.file))
shell.setCompletionFunction( "rom/programs/eject.lua", completion.build(completion.peripheral) ) shell.setCompletionFunction("rom/programs/eject.lua", completion.build(completion.peripheral))
shell.setCompletionFunction( "rom/programs/gps.lua", completion.build({ completion.choice, { "host", "host ", "locate" } }) ) shell.setCompletionFunction("rom/programs/gps.lua", completion.build({ completion.choice, { "host", "host ", "locate" } }))
shell.setCompletionFunction( "rom/programs/help.lua", completion.build(completion.help) ) shell.setCompletionFunction("rom/programs/help.lua", completion.build(completion.help))
shell.setCompletionFunction( "rom/programs/id.lua", completion.build(completion.peripheral) ) shell.setCompletionFunction("rom/programs/id.lua", completion.build(completion.peripheral))
shell.setCompletionFunction( "rom/programs/label.lua", completion.build( shell.setCompletionFunction("rom/programs/label.lua", completion.build(
{ completion.choice, { "get", "get ", "set ", "clear", "clear " } }, { completion.choice, { "get", "get ", "set ", "clear", "clear " } },
completion.peripheral completion.peripheral
) ) ))
shell.setCompletionFunction( "rom/programs/list.lua", completion.build(completion.dir) ) shell.setCompletionFunction("rom/programs/list.lua", completion.build(completion.dir))
shell.setCompletionFunction( "rom/programs/mkdir.lua", completion.build({ completion.dir, many = true }) ) shell.setCompletionFunction("rom/programs/mkdir.lua", completion.build({ completion.dir, many = true }))
shell.setCompletionFunction( "rom/programs/monitor.lua", completion.build( shell.setCompletionFunction("rom/programs/monitor.lua", completion.build(
{ completion.peripheral, true }, { completion.peripheral, true },
completion.program completion.program
) ) ))
shell.setCompletionFunction( "rom/programs/move.lua", completion.build( shell.setCompletionFunction("rom/programs/move.lua", completion.build(
{ completion.dirOrFile, true }, { completion.dirOrFile, true },
completion.dirOrFile completion.dirOrFile
) ) ))
shell.setCompletionFunction( "rom/programs/redstone.lua", completion.build( shell.setCompletionFunction("rom/programs/redstone.lua", completion.build(
{ completion.choice, { "probe", "set ", "pulse " } }, { completion.choice, { "probe", "set ", "pulse " } },
completion.side completion.side
) ) ))
shell.setCompletionFunction( "rom/programs/rename.lua", completion.build( shell.setCompletionFunction("rom/programs/rename.lua", completion.build(
{ completion.dirOrFile, true }, { completion.dirOrFile, true },
completion.dirOrFile completion.dirOrFile
) ) ))
shell.setCompletionFunction( "rom/programs/shell.lua", completion.build(completion.program) ) shell.setCompletionFunction("rom/programs/shell.lua", completion.build(completion.program))
shell.setCompletionFunction( "rom/programs/type.lua", completion.build(completion.dirOrFile) ) shell.setCompletionFunction("rom/programs/type.lua", completion.build(completion.dirOrFile))
shell.setCompletionFunction( "rom/programs/set.lua", completion.build({ completion.setting, true }) ) shell.setCompletionFunction("rom/programs/set.lua", completion.build({ completion.setting, true }))
shell.setCompletionFunction( "rom/programs/advanced/bg.lua", completion.build(completion.program) ) shell.setCompletionFunction("rom/programs/advanced/bg.lua", completion.build(completion.program))
shell.setCompletionFunction( "rom/programs/advanced/fg.lua", completion.build(completion.program) ) shell.setCompletionFunction("rom/programs/advanced/fg.lua", completion.build(completion.program))
shell.setCompletionFunction( "rom/programs/fun/dj.lua", completion.build( shell.setCompletionFunction("rom/programs/fun/dj.lua", completion.build(
{ completion.choice, { "play", "play ", "stop " } }, { completion.choice, { "play", "play ", "stop " } },
completion.peripheral completion.peripheral
) ) ))
shell.setCompletionFunction( "rom/programs/fun/advanced/paint.lua", completion.build(completion.file) ) shell.setCompletionFunction("rom/programs/fun/advanced/paint.lua", completion.build(completion.file))
shell.setCompletionFunction( "rom/programs/http/pastebin.lua", completion.build( shell.setCompletionFunction("rom/programs/http/pastebin.lua", completion.build(
{ completion.choice, { "put ", "get ", "run " } }, { completion.choice, { "put ", "get ", "run " } },
completePastebinPut completePastebinPut
) ) ))
shell.setCompletionFunction( "rom/programs/rednet/chat.lua", completion.build({ completion.choice, { "host ", "join " } }) ) shell.setCompletionFunction("rom/programs/rednet/chat.lua", completion.build({ completion.choice, { "host ", "join " } }))
shell.setCompletionFunction( "rom/programs/command/exec.lua", completion.build(completion.command) ) shell.setCompletionFunction("rom/programs/command/exec.lua", completion.build(completion.command))
shell.setCompletionFunction( "rom/programs/http/wget.lua", completion.build({ completion.choice, { "run " } }) ) shell.setCompletionFunction("rom/programs/http/wget.lua", completion.build({ completion.choice, { "run " } }))
if turtle then if turtle then
shell.setCompletionFunction( "rom/programs/turtle/go.lua", completion.build( shell.setCompletionFunction("rom/programs/turtle/go.lua", completion.build(
{ completion.choice, { "left", "right", "forward", "back", "down", "up" }, true, many = true } { completion.choice, { "left", "right", "forward", "back", "down", "up" }, true, many = true }
) ) ))
shell.setCompletionFunction( "rom/programs/turtle/turn.lua", completion.build( shell.setCompletionFunction("rom/programs/turtle/turn.lua", completion.build(
{ completion.choice, { "left", "right" }, true, many = true } { completion.choice, { "left", "right" }, true, many = true }
) ) ))
shell.setCompletionFunction( "rom/programs/turtle/equip.lua", completion.build( shell.setCompletionFunction("rom/programs/turtle/equip.lua", completion.build(
nil, nil,
{ completion.choice, { "left", "right" } } { completion.choice, { "left", "right" } }
) ) ))
shell.setCompletionFunction( "rom/programs/turtle/unequip.lua", completion.build( shell.setCompletionFunction("rom/programs/turtle/unequip.lua", completion.build(
{ completion.choice, { "left", "right" } } { completion.choice, { "left", "right" } }
) ) ))
end end
-- Run autorun files -- Run autorun files
if fs.exists( "/rom/autorun" ) and fs.isDir( "/rom/autorun" ) then if fs.exists("/rom/autorun") and fs.isDir("/rom/autorun") then
local tFiles = fs.list( "/rom/autorun" ) local tFiles = fs.list("/rom/autorun")
for _, sFile in ipairs( tFiles ) do for _, sFile in ipairs(tFiles) do
if string.sub( sFile, 1, 1 ) ~= "." then if string.sub(sFile, 1, 1) ~= "." then
local sPath = "/rom/autorun/" .. sFile local sPath = "/rom/autorun/" .. sFile
if not fs.isDir( sPath ) then if not fs.isDir(sPath) then
shell.run( sPath ) shell.run(sPath)
end end
end end
end end
end end
local function findStartups( sBaseDir ) local function findStartups(sBaseDir)
local tStartups = nil local tStartups = nil
local sBasePath = "/" .. fs.combine( sBaseDir, "startup" ) local sBasePath = "/" .. fs.combine(sBaseDir, "startup")
local sStartupNode = shell.resolveProgram( sBasePath ) local sStartupNode = shell.resolveProgram(sBasePath)
if sStartupNode then if sStartupNode then
tStartups = { sStartupNode } tStartups = { sStartupNode }
end end
-- It's possible that there is a startup directory and a startup.lua file, so this has to be -- It's possible that there is a startup directory and a startup.lua file, so this has to be
-- executed even if a file has already been found. -- executed even if a file has already been found.
if fs.isDir( sBasePath ) then if fs.isDir(sBasePath) then
if tStartups == nil then if tStartups == nil then
tStartups = {} tStartups = {}
end end
for _, v in pairs( fs.list( sBasePath ) ) do for _, v in pairs(fs.list(sBasePath)) do
local sPath = "/" .. fs.combine( sBasePath, v ) local sPath = "/" .. fs.combine(sBasePath, v)
if not fs.isDir( sPath ) then if not fs.isDir(sPath) then
tStartups[ #tStartups + 1 ] = sPath tStartups[#tStartups + 1] = sPath
end end
end end
end end
@ -153,19 +153,19 @@ local function findStartups( sBaseDir )
end end
-- Show MOTD -- Show MOTD
if settings.get( "motd.enable" ) then if settings.get("motd.enable") then
shell.run( "motd" ) shell.run("motd")
end end
-- Run the user created startup, either from disk drives or the root -- Run the user created startup, either from disk drives or the root
local tUserStartups = nil local tUserStartups = nil
if settings.get( "shell.allow_startup" ) then if settings.get("shell.allow_startup") then
tUserStartups = findStartups( "/" ) tUserStartups = findStartups("/")
end end
if settings.get( "shell.allow_disk_startup" ) then if settings.get("shell.allow_disk_startup") then
for _, sName in pairs( peripheral.getNames() ) do for _, sName in pairs(peripheral.getNames()) do
if disk.isPresent( sName ) and disk.hasData( sName ) then if disk.isPresent(sName) and disk.hasData(sName) then
local startups = findStartups( disk.getMountPath( sName ) ) local startups = findStartups(disk.getMountPath(sName))
if startups then if startups then
tUserStartups = startups tUserStartups = startups
break break
@ -174,7 +174,7 @@ if settings.get( "shell.allow_disk_startup" ) then
end end
end end
if tUserStartups then if tUserStartups then
for _, v in pairs( tUserStartups ) do for _, v in pairs(tUserStartups) do
shell.run( v ) shell.run(v)
end end
end end

View File

@ -238,8 +238,8 @@ local function matches(eq, exact, left, right)
-- If we've already explored/are exploring the left and right then return -- If we've already explored/are exploring the left and right then return
if eq[left] and eq[left][right] then return true end if eq[left] and eq[left][right] then return true end
if not eq[left] then eq[left] = {[right] = true} else eq[left][right] = true end if not eq[left] then eq[left] = { [right] = true } else eq[left][right] = true end
if not eq[right] then eq[right] = {[left] = true} else eq[right][left] = true end if not eq[right] then eq[right] = { [left] = true } else eq[right][left] = true end
-- Verify all pairs in left are equal to those in right -- Verify all pairs in left are equal to those in right
for k, v in pairs(left) do for k, v in pairs(left) do

View File

@ -15,7 +15,7 @@ describe("The exec program", function()
it("runs a command", function() it("runs a command", function()
stub(_G, "commands", { stub(_G, "commands", {
exec = function() return true, {"Hello World!"} end, exec = function() return true, { "Hello World!" } end,
}) })
expect(capture(stub, "/rom/programs/command/exec.lua computercraft")) expect(capture(stub, "/rom/programs/command/exec.lua computercraft"))
@ -24,7 +24,7 @@ describe("The exec program", function()
it("reports command failures", function() it("reports command failures", function()
stub(_G, "commands", { stub(_G, "commands", {
exec = function() return false, {"Hello World!"} end, exec = function() return false, { "Hello World!" } end,
}) })
expect(capture(stub, "/rom/programs/command/exec.lua computercraft")) expect(capture(stub, "/rom/programs/command/exec.lua computercraft"))

View File

@ -49,7 +49,7 @@ describe("The pastebin program", function()
it("upload a program to pastebin", function() it("upload a program to pastebin", function()
setup_request() setup_request()
local file = fs.open( "testup", "w" ) local file = fs.open("testup", "w")
file.close() file.close()
expect(capture(stub, "pastebin", "put", "testup")) expect(capture(stub, "pastebin", "put", "testup"))