mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 05:33:00 +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:
		| @@ -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. | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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(",") | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -1,2 +1,2 @@ | |||||||
| term.clear() | term.clear() | ||||||
| term.setCursorPos( 1, 1 ) | term.setCursorPos(1, 1) | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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() | ||||||
|   | |||||||
| @@ -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" | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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() | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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.") | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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.") | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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")) | ||||||
|   | |||||||
| @@ -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")) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 SquidDev
					SquidDev