diff --git a/src/main/java/li/cil/oc/server/component/InternetCard.scala b/src/main/java/li/cil/oc/server/component/InternetCard.scala index 743c586ff..e1cc764ac 100644 --- a/src/main/java/li/cil/oc/server/component/InternetCard.scala +++ b/src/main/java/li/cil/oc/server/component/InternetCard.scala @@ -134,7 +134,7 @@ class InternetCard extends ManagedComponent { def isTcpEnabled(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.httpEnabled) @Callback(doc = """function(address:string[, port:number]):number -- Opens a new TCP connection. Returns the handle of the connection.""") - def connect(context: Context, args: Arguments): Array[AnyRef] = { + def connect(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { val address = args.checkString(0) val port = if (args.count > 1) args.checkInteger(1) else -1 if (!Settings.get.tcpEnabled) { @@ -153,8 +153,8 @@ class InternetCard extends ManagedComponent { result(handle) } - @Callback(doc = """function(handle:number) -- Closes an open socket stream.""") - def close(context: Context, args: Arguments): Array[AnyRef] = { + @Callback(direct = true, doc = """function(handle:number) -- Closes an open socket stream.""") + def close(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { val handle = args.checkInteger(0) connections.remove(handle) match { case Some(socket) => socket.close() @@ -164,7 +164,7 @@ class InternetCard extends ManagedComponent { } @Callback(doc = """function(handle:number, data:string):number -- Tries to write data to the socket stream. Returns the number of bytes written.""") - def write(context: Context, args: Arguments): Array[AnyRef] = { + def write(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { val handle = args.checkInteger(0) val value = args.checkByteArray(1) connections.get(handle) match { @@ -176,7 +176,7 @@ class InternetCard extends ManagedComponent { } @Callback(doc = """function(handle:number, n:number):string -- Tries to read data from the socket stream. Returns the read byte array.""") - def read(context: Context, args: Arguments): Array[AnyRef] = { + def read(context: Context, args: Arguments): Array[AnyRef] = this.synchronized { val handle = args.checkInteger(0) val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.checkInteger(1))) connections.get(handle) match { @@ -222,7 +222,7 @@ class InternetCard extends ManagedComponent { } } - override def onDisconnect(node: Node) { + override def onDisconnect(node: Node) = this.synchronized { super.onDisconnect(node) if (owner.isDefined && (node == this.node || node.host.isInstanceOf[Context] && (node.host.asInstanceOf[Context] == owner.get))) { owner = None @@ -236,7 +236,7 @@ class InternetCard extends ManagedComponent { } } - override def onMessage(message: Message) { + override def onMessage(message: Message) = this.synchronized { super.onMessage(message) message.data match { case Array() if (message.name == "computer.stopped" || message.name == "computer.started") && owner.isDefined && message.source.address == owner.get.node.address => diff --git a/src/main/resources/assets/opencomputers/lua/component/internet/bin/pastebin.lua b/src/main/resources/assets/opencomputers/lua/component/internet/bin/pastebin.lua index 604f1c1d7..685428499 100644 --- a/src/main/resources/assets/opencomputers/lua/component/internet/bin/pastebin.lua +++ b/src/main/resources/assets/opencomputers/lua/component/internet/bin/pastebin.lua @@ -16,7 +16,7 @@ local args, options = shell.parse(...) local function get(pasteId, filename) local f, reason = io.open(filename, "w") if not f then - io.stderr:write("Failed opening file for writing: ", reason) + io.stderr:write("Failed opening file for writing: " .. reason) return end @@ -33,12 +33,12 @@ local function get(pasteId, filename) end f:close() - io.write("Saved data to ", filename, "\n") + io.write("Saved data to " .. filename .. "\n") else io.write("failed.\n") f:close() fs.remove(filename) - io.stderr:write("HTTP request failed: ", response, "\n") + io.stderr:write("HTTP request failed: " .. response .. "\n") end end @@ -48,7 +48,7 @@ function encode(code) code = string.gsub(code, "([^%w ])", function (c) return string.format("%%%02X", string.byte(c)) end) - code = string.gsub (code, " ", "+") + code = string.gsub(code, " ", "+") end return code end @@ -74,14 +74,14 @@ function put(path) if configFile then local result, reason = pcall(configFile) if not result then - io.stderr:write("Failed loading config: ", reason) + io.stderr:write("Failed loading config: " .. reason) end end config.key = config.key or "fd92bd40a84c127eeb6804b146793c97" local file, reason = io.open(path, "r") if not file then - io.stderr:write("Failed opening file for reading: ", reason) + io.stderr:write("Failed opening file for reading: " .. reason) return end @@ -109,8 +109,8 @@ function put(path) else io.write("success.\n") local pasteId = string.match(info, "[^/]+$") - io.write("Uploaded as ", info, "\n") - io.write('Run "pastebin get ', pasteId, '" to download anywhere.') + io.write("Uploaded as " .. info .. "\n") + io.write('Run "pastebin get ' .. pasteId .. '" to download anywhere.') end else io.write("failed.\n") diff --git a/src/main/resources/assets/opencomputers/lua/component/internet/bin/wget.lua b/src/main/resources/assets/opencomputers/lua/component/internet/bin/wget.lua index e2b16448b..36122de81 100644 --- a/src/main/resources/assets/opencomputers/lua/component/internet/bin/wget.lua +++ b/src/main/resources/assets/opencomputers/lua/component/internet/bin/wget.lua @@ -47,7 +47,7 @@ end local f, reason = io.open(filename, "wb") if not f then - io.stderr:write("failed opening file for writing: ", reason) + io.stderr:write("failed opening file for writing: " .. reason) return end @@ -65,7 +65,7 @@ if result then f:close() if not options.q then - io.write("Saved data to ", filename, "\n") + io.write("Saved data to " .. filename .. "\n") end else if not options.q then @@ -73,5 +73,5 @@ else end f:close() fs.remove(filename) - io.stderr:write("HTTP request failed: ", response, "\n") + io.stderr:write("HTTP request failed: " .. response .. "\n") end \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/component/internet/lib/internet.lua b/src/main/resources/assets/opencomputers/lua/component/internet/lib/internet.lua index b73b88011..ce102aff0 100644 --- a/src/main/resources/assets/opencomputers/lua/component/internet/lib/internet.lua +++ b/src/main/resources/assets/opencomputers/lua/component/internet/lib/internet.lua @@ -109,13 +109,7 @@ function internet.socket(address, port) -- the __gc metamethod. So we start a timer to do the yield/cleanup. local function cleanup(self) if not self.handle then return end - -- save non-gc'ed values as upvalues - local inet = self.inet - local handle = self.handle - local function close() - inet.close(handle) - end - event.timer(0, close) + pcall(self.inet.close, self.handle) end local metatable = {__index = socketStream, __gc = cleanup, diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/alias.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/alias.lua index 4c7ad2658..f48ac3f38 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/alias.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/alias.lua @@ -4,7 +4,7 @@ local args = shell.parse(...) if #args == 0 then for name, value in shell.aliases() do - io.write(name, " ", value, "\n") + io.write(name .. " " .. value .. "\n") end elseif #args == 1 then local value = shell.getAlias(args[1]) @@ -15,5 +15,5 @@ elseif #args == 1 then end else shell.setAlias(args[1], args[2]) - io.write("alias created: ", args[1], " -> ", args[2]) + io.write("alias created: " .. args[1] .. " -> " .. args[2]) end \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/besh.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/besh.lua index 2fbb109dc..0e6287f17 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/besh.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/besh.lua @@ -253,7 +253,7 @@ local function execute(command, env, ...) for i = 1, #commands do local program, args, input, output, mode = table.unpack(commands[i]) local reason - threads[i], reason = shell.load(program, env, function() + threads[i], reason = process.load(shell.resolve(program, "lua"), env, function() if input then local file, reason = io.open(shell.resolve(input)) if not file then diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/components.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/components.lua index 54c4f707c..6c5388b1e 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/components.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/components.lua @@ -1,5 +1,5 @@ local component = require("component") for address, name in component.list() do - io.write(name, "\t", address, "\n") + io.write(name .. "\t" .. address .. "\n") end \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/ls.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/ls.lua index 5be963a2c..d79fbe330 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/ls.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/ls.lua @@ -18,7 +18,7 @@ for i = 1, #dirs do end local list, reason = fs.list(path) if not list then - io.write(reason, "\n") + io.write(reason .. "\n") else local function setColor(c) if component.gpu.getForeground() ~= c then @@ -40,7 +40,7 @@ for i = 1, #dirs do setColor(0x99CCFF) for _, d in ipairs(lsd) do if options.a or d:sub(1, 1) ~= "." then - io.write(d, "\t") + io.write(d .. "\t") if options.l or io.output() ~= io.stdout then io.write("\n") end @@ -55,7 +55,7 @@ for i = 1, #dirs do setColor(0xFFFFFF) end if options.a or f:sub(1, 1) ~= "." then - io.write(f, "\t") + io.write(f .. "\t") if options.l then setColor(0xFFFFFF) io.write(fs.size(fs.concat(path, f)), "\n") diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/lua.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/lua.lua index dbc6f368d..61d65ed37 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/lua.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/lua.lua @@ -16,11 +16,11 @@ local env = setmetatable({}, {__index = function(t, k) end}) component.gpu.setForeground(0xFFFFFF) -io.write("Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio\n") +term.write("Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio\n") component.gpu.setForeground(0xFFFF00) -io.write("Enter a statement and hit enter to evaluate it.\n") -io.write("Prefix an expression with '=' to show its value.\n") -io.write("Press Ctrl+C to exit the interpreter.\n") +term.write("Enter a statement and hit enter to evaluate it.\n") +term.write("Prefix an expression with '=' to show its value.\n") +term.write("Press Ctrl+C to exit the interpreter.\n") component.gpu.setForeground(0xFFFFFF) while term.isAvailable() do @@ -46,16 +46,16 @@ while term.isAvailable() do if type(result[2]) == "table" and result[2].reason == "terminated" then os.exit(result[2].code) end - io.stderr:write(tostring(result[2]), "\n") + io.stderr:write(tostring(result[2]) .. "\n") else for i = 2, result.n do - io.write(text.serialize(result[i], true), "\t") + term.write(text.serialize(result[i], true) .. "\t") end - if result.n > 1 then - io.write("\n") + if term.getCursor() > 1 then + term.write("\n") end end else - io.stderr:write(reason, "\n") + io.stderr:write(tostring(reason) .. "\n") end end diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/mkdir.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/mkdir.lua index 833db7b2c..2b3c077c3 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/mkdir.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/mkdir.lua @@ -18,6 +18,6 @@ for i = 1, #args do reason = "unknown reason" end end - io.stderr:write(path, ": ", reason, "\n") + io.stderr:write(path .. ": " .. reason .. "\n") end end diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/redstone.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/redstone.lua index 8fd7978a2..a50ae7ba5 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/redstone.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/redstone.lua @@ -50,8 +50,8 @@ if options.b then end rs.setBundledOutput(side, color, value) end - io.write("in: ", rs.getBundledInput(side, color), "\n") - io.write("out: ", rs.getBundledOutput(side, color)) + io.write("in: " .. rs.getBundledInput(side, color) .. "\n") + io.write("out: " .. rs.getBundledOutput(side, color)) else if #args > 1 then local value = args[2] @@ -62,6 +62,6 @@ else end rs.setOutput(side, value) end - io.write("in: ", rs.getInput(side), "\n") - io.write("out: ", rs.getOutput(side)) + io.write("in: " .. rs.getInput(side) .. "\n") + io.write("out: " .. rs.getOutput(side)) end diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/rm.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/rm.lua index 72abfad63..612ae8cad 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/rm.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/rm.lua @@ -9,6 +9,6 @@ end for i = 1, #args do local path = shell.resolve(args[i]) if not os.remove(path) then - io.stderr:write(path, ": no such file, or permission denied\n") + io.stderr:write(path .. ": no such file, or permission denied\n") end end diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/set.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/set.lua index 0a049dcda..0632d3c5c 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/set.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/set.lua @@ -2,7 +2,7 @@ local args = {...} if #args < 1 then for k,v in pairs(os.getenv()) do - io.write(k, "='", string.gsub(v, "'", [['"'"']]), "'\n") + io.write(k .. "='" .. string.gsub(v, "'", [['"'"']]) .. "'\n") end else local count = 0 diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/sh.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/sh.lua index f5547cfc9..2ec7094d8 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/sh.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/sh.lua @@ -6,45 +6,133 @@ local shell = require("shell") local term = require("term") local text = require("text") -local args, options = shell.parse(...) -local history = {} - -if options.v or not process.running(2) then - io.write(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)\n") +local function expand(value) + return value:gsub("%$(%w+)", os.getenv):gsub("%$%b{}", + function(match) return os.getenv(expand(match:sub(3, -2))) or match end) end -while true do - if not term.isAvailable() then -- don't clear unless we lost the term - while not term.isAvailable() do - event.pull("term_available") - end - term.clear() - if options.v then - io.write(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)\n") +local function evaluate(value) + local init, result = 1, "" + repeat + local match = value:match("^%b''", init) + if match then -- single quoted string. no variable expansion. + match = match:sub(2, -2) + init = init + 2 + result = result .. match + else + match = value:match('^%b""', init) + if match then -- double quoted string. + match = match:sub(2, -2) + init = init + 2 + else + -- plaintext? + match = value:match("^([^']+)%b''", init) + if not match then -- unmatched single quote. + match = value:match('^([^"]+)%b""', init) + if not match then -- unmatched double quote. + match = value:sub(init) + end + end + end + result = result .. expand(match) end + init = init + #match + until init > #value + return result +end + +local function execute(command, ...) + local parts, reason = text.tokenize(command) + if not parts then + return false, reason + elseif #parts == 0 then + return true end - while term.isAvailable() do - local foreground = component.gpu.setForeground(0xFF0000) - term.write(os.getenv("PS1") or "# ") - component.gpu.setForeground(foreground) - local command = term.read(history) - if not command then - io.write("exit\n") - return -- eof - end - while #history > 10 do - table.remove(history, 1) - end - command = text.trim(command) - if command == "exit" then - return - elseif command ~= "" then - local result, reason = os.execute(command) - if not result then - io.stderr:write(reason .. "\n") - elseif term.getCursor() > 1 then - io.write("\n") + local program, args = shell.resolveAlias(parts[1], table.pack(select(2, table.unpack(parts)))) + program = evaluate(program) + local program, reason = shell.resolve(program, "lua") + if not program then + return false, reason + end + for i = 1, args.n do + args[i] = evaluate(args[i]) + end + for _, arg in ipairs(table.pack(...)) do + table.insert(args, arg) + end + table.insert(args, 1, true) + args.n = #args + local thread, reason = process.load(shell.resolve(program, "lua"), env, nil, command) + if not thread then + return false, reason + end + local result = nil + -- Emulate CC behavior by making yields a filtered event.pull() + while args[1] and coroutine.status(thread) ~= "dead" do + result = table.pack(coroutine.resume(thread, table.unpack(args, 2, args.n))) + if coroutine.status(thread) ~= "dead" then + if type(result[2]) == "string" then + args = table.pack(pcall(event.pull, table.unpack(result, 2, result.n))) + else + args = {true, n=1} end end end + if not args[1] then + return false, args[2] + end + if not result[1] and type(result[2]) == "table" and result[2].reason == "terminated" then + if result[2].code then + return true + else + return false, "terminated" + end + end + return table.unpack(result, 1, result.n) +end + +local args, options = shell.parse(...) +local history = {} + +if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then + -- interactive shell. + while true do + if not term.isAvailable() then -- don't clear unless we lost the term + while not term.isAvailable() do + event.pull("term_available") + end + term.clear() + end + while term.isAvailable() do + local foreground = component.gpu.setForeground(0xFF0000) + term.write(expand(os.getenv("PS1") or "$ ")) + component.gpu.setForeground(foreground) + local command = term.read(history) + if not command then + term.write("exit\n") + return -- eof + end + while #history > 10 do + table.remove(history, 1) + end + command = text.trim(command) + if command == "exit" then + return + elseif command ~= "" then + local result, reason = execute(command) + if not result then + io.stderr:write(reason .. "\n") + elseif term.getCursor() > 1 then + term.write("\n") + end + end + end + end +else + -- execute command. + local result = table.pack(execute(table.unpack(args))) + if not result[1] then + error(result[2]) + end + return table.unpack(result, 2) end \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/unalias.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/unalias.lua index 47bbed0e5..33bb6a094 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/unalias.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/unalias.lua @@ -11,5 +11,5 @@ if not result then io.stderr:write("no such alias") else shell.setAlias(args[1], nil) - io.write("alias removed: ", args[1], " -> ", result) + io.write("alias removed: " .. args[1] .. " -> " .. result) end \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/rom/bin/which.lua b/src/main/resources/assets/opencomputers/lua/rom/bin/which.lua index 911b81e3c..a9cb77898 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/bin/which.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/bin/which.lua @@ -14,8 +14,8 @@ for i = 1, #args do result, reason = shell.resolve(args[i], "lua") end if result then - io.write(result, "\n") + io.write(result .. "\n") else - io.stderr:write(args[i], ": ", reason, "\n") + io.stderr:write(args[i] .. ": " .. reason .. "\n") end end \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/rom/init.lua b/src/main/resources/assets/opencomputers/lua/rom/init.lua index d193e8cd1..48cc1be29 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/init.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/init.lua @@ -1,17 +1,20 @@ local component = require("component") local computer = require("computer") +local event = require("event") for c, t in component.list() do computer.pushSignal("component_added", c, t) end os.sleep(0.5) -- Allow signal processing by libraries. - -require("term").clear() - computer.pushSignal("init") -- so libs know components are initialized. + while true do - local result, reason = os.execute(os.getenv("SHELL")) + require("term").clear() + io.write(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)\n") + local result, reason = os.execute(os.getenv("SHELL") .. " -") if not result then - print(reason) + io.stderr:write((reason or "unknown error") .. "\n") + print("Press any key to continue.") + event.pull("key") end end \ No newline at end of file diff --git a/src/main/resources/assets/opencomputers/lua/rom/lib/buffer.lua b/src/main/resources/assets/opencomputers/lua/rom/lib/buffer.lua index e6e311784..d844d64cf 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/lib/buffer.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/lib/buffer.lua @@ -10,7 +10,8 @@ function buffer.new(mode, stream) bufferRead = "", bufferWrite = "", bufferSize = math.max(512, math.min(8 * 1024, computer.freeMemory() / 8)), - bufferMode = "full" + bufferMode = "full", + readTimeout = math.huge } mode = mode or "r" for i = 1, unicode.len(mode) do @@ -58,7 +59,12 @@ function buffer:lines(...) end function buffer:read(...) + local timeout = computer.uptime() + self.readTimeout + local function readChunk() + if computer.uptime() > timeout then + error("timeout") + end local result, reason = self.stream:read(self.bufferSize) if result then self.bufferRead = self.bufferRead .. result @@ -213,6 +219,14 @@ function buffer:setvbuf(mode, size) return self.bufferMode, self.bufferSize end +function buffer:getTimeout() + return self.readTimeout +end + +function buffer:setTimeout(value) + self.readTimeout = tonumber(value) +end + function buffer:write(...) if self.closed then return nil, "bad file descriptor" diff --git a/src/main/resources/assets/opencomputers/lua/rom/lib/shell.lua b/src/main/resources/assets/opencomputers/lua/rom/lib/shell.lua index d21026ba5..aa25f5463 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/lib/shell.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/lib/shell.lua @@ -1,7 +1,8 @@ local event = require("event") local fs = require("filesystem") -local unicode = require("unicode") +local process = require("process") local text = require("text") +local unicode = require("unicode") local shell = {} local aliases = {} @@ -130,39 +131,11 @@ function shell.resolve(path, ext) end function shell.execute(command, env, ...) - checkArg(1, command, "string") - local parts, reason = text.tokenize(command) - if not parts then + local sh, reason = loadfile(shell.resolve(os.getenv("SHELL"), "lua"), "t", env) + if not sh then return false, reason end - if #parts == 0 then - return true - end - local program, args = shell.resolveAlias(parts[1], table.pack(select(2, table.unpack(parts)))) - table.insert(args, 1, true) - for _, arg in ipairs(table.pack(...)) do - table.insert(args, arg) - end - args.n = #args - local thread, reason = shell.load(program, env, nil, command) - if not thread then - return false, reason - end - local result = nil - -- Emulate CC behavior by making yields a filtered event.pull() - while args[1] and coroutine.status(thread) ~= "dead" do - result = table.pack(coroutine.resume(thread, table.unpack(args, 2, args.n))) - if coroutine.status(thread) ~= "dead" then - if type(result[2]) == "string" then - args = table.pack(pcall(event.pull, table.unpack(result, 2, result.n))) - else - args = {true, n=1} - end - end - end - if not args[1] then - return false, args[2] - end + local result = table.pack(pcall(sh, command, ...)) if not result[1] and type(result[2]) == "table" and result[2].reason == "terminated" then if result[2].code then return true @@ -173,21 +146,15 @@ function shell.execute(command, env, ...) return table.unpack(result, 1, result.n) end -function shell.load(path, env, init, name) - local path, reason = shell.resolve(path, "lua") - if not path then - return nil, reason - end - return require("process").load(path, env, init, name) -end - function shell.parse(...) local params = table.pack(...) local args = {} local options = {} for i = 1, params.n do local param = params[i] - if unicode.sub(param, 1, 1) == "-" then + if type(param) == "string" and unicode.sub(param, 1, 2) == "--" then + options[unicode.sub(param, 3)] = true + elseif type(param) == "string" and unicode.sub(param, 1, 1) == "-" then for j = 2, unicode.len(param) do options[unicode.sub(param, j, j)] = true end diff --git a/src/main/resources/assets/opencomputers/lua/rom/lib/term.lua b/src/main/resources/assets/opencomputers/lua/rom/lib/term.lua index 2298b0b2c..111097326 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/lib/term.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/lib/term.lua @@ -340,12 +340,14 @@ function term.write(value, wrap) term.setCursorBlink(false) local line, nl = value repeat + local wrapAfter, margin = math.huge, math.huge if wrap then - line, value, nl = text.wrap(value, w - (cursorX - 1), w) + wrapAfter, margin = w - (cursorX - 1), w end + line, value, nl = text.wrap(value, wrapAfter, margin) component.gpu.set(cursorX, cursorY, line) cursorX = cursorX + unicode.len(line) - if nl or cursorX > w then + if nl or (cursorX > w and wrap) then cursorX = 1 cursorY = cursorY + 1 end diff --git a/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua b/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua index 5e17aa8b3..c8d4c2510 100644 --- a/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua +++ b/src/main/resources/assets/opencomputers/lua/rom/lib/text.lua @@ -10,7 +10,8 @@ function text.detab(value, tabWidth) local spaces = tabWidth - match:len() % tabWidth return match .. string.rep(" ", spaces) end - return value:gsub("([^\n]-)\t", rep) + local result = value:gsub("([^\n]-)\t", rep) -- truncate results + return result end function text.padRight(value, length) @@ -43,6 +44,7 @@ end function text.wrap(value, width, maxWidth) checkArg(1, value, "string") checkArg(2, width, "number") + checkArg(3, maxWidth, "number") local line, nl = value:match("([^\r\n]*)([\r\n]?)") -- read until newline if unicode.len(line) > width then -- do we even need to wrap? local partial = unicode.sub(line, 1, width)