From c4c3811376c2a694f8d0a7ab732f643ba9c149a7 Mon Sep 17 00:00:00 2001 From: payonel Date: Tue, 22 Aug 2017 11:22:06 -0700 Subject: [PATCH 1/9] revert removal of process.running -- some scripts still use it --- .../assets/opencomputers/loot/openos/lib/process.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua index 169fd73bf..38c8a2e3d 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/process.lua @@ -150,4 +150,11 @@ function process.internal.continue(co, ...) return table.unpack(result, 2, result.n) end +function process.running(level) -- kept for backwards compat, prefer process.info + local info = process.info(level) + if info then + return info.path, info.env, info.command + end +end + return process From a1512451fe9a4d781a5fd74cbcb61c0ae5ff3c8e Mon Sep 17 00:00:00 2001 From: payonel Date: Wed, 23 Aug 2017 12:24:05 -0700 Subject: [PATCH 2/9] support s and u vt100 codes strangely, the real terminal appears to treat [su] the exact same as [78] even though the specification says [su] is position only --- .../opencomputers/loot/openos/bin/echo.lua | 3 +++ .../opencomputers/loot/openos/lib/vt100.lua | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua index f18ce4c5b..59dbc8a5c 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua @@ -8,6 +8,9 @@ if options.help then end if options.e then for index,arg in ipairs(args) do + -- use lua load here to interpret escape sequences such as \27 + -- instead of writing my own language to interpret them myself + -- note that in a real terminal, \e is used for \27 args[index] = assert(load("return \"" .. arg:gsub('"', [[\"]]) .. "\""))() end end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua index 4e6111b50..8e0972530 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua @@ -137,10 +137,8 @@ rules[{"[DEM]"}] = function(window, dir) end end --- 7 save cursor position and attributes --- 8 restore cursor position and attributes -rules[{"[78]"}] = function(window, restore) - if restore == "8" then +local function save_attributes(window, save) + if save then local data = window.saved or {1, 1, {0x0}, {0xffffff}} window.x = data[1] window.y = data[2] @@ -151,6 +149,18 @@ rules[{"[78]"}] = function(window, restore) end end +-- 7 save cursor position and attributes +-- 8 restore cursor position and attributes +rules[{"[78]"}] = function(window, restore) + save_attributes(window, restore == "8") +end + +-- s save cursor position +-- u restore cursor position +rules[{"%[", "[su]"}] = function(window, _, restore) + save_attributes(window, restore == "u") +end + function vt100.parse(window) local ansi = window.ansi_escape window.ansi_escape = nil From fc486d4bd28c08cf25bc4719a0618bd83b33e800 Mon Sep 17 00:00:00 2001 From: payonel Date: Thu, 7 Sep 2017 08:40:30 -0700 Subject: [PATCH 3/9] openos 1.6.8 update Changes * thread: fix coma state issue where thread would not resume * thread: add thread.current(), returns current thread [ the init thread is still technically not a thread ] * tty: simplify the api with read, and separate all stream methods from the library * sleep: /bin/sleep will now show blinking cursor and can be interrupted * echo: use io.write instead of print. print loads slightly more resources --- .../opencomputers/loot/openos/bin/echo.lua | 8 +- .../opencomputers/loot/openos/bin/sh.lua | 2 +- .../opencomputers/loot/openos/bin/sleep.lua | 10 +- .../opencomputers/loot/openos/boot/03_io.lua | 16 +-- .../loot/openos/lib/core/boot.lua | 2 +- .../loot/openos/lib/core/lua_shell.lua | 7 +- .../opencomputers/loot/openos/lib/term.lua | 17 ++- .../opencomputers/loot/openos/lib/thread.lua | 104 ++++++++++++++---- .../opencomputers/loot/openos/lib/tty.lua | 85 ++++++++------ 9 files changed, 169 insertions(+), 82 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua index 59dbc8a5c..3986ea031 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/echo.lua @@ -1,9 +1,11 @@ local args, options = require("shell").parse(...) if options.help then - print([[`echo` writes the provided string(s) to the standard output. + io.write([[ +`echo` writes the provided string(s) to the standard output. -n do not output the trialing newline -e enable interpretation of backslash escapes - --help display this help and exit]]) + --help display this help and exit +]]) return end if options.e then @@ -16,5 +18,5 @@ if options.e then end io.write(table.concat(args," ")) if not options.n then - print() + io.write("\n") end diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/sh.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/sh.lua index 01f627e4c..d1b5bdb4e 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/sh.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/sh.lua @@ -23,7 +23,7 @@ if #args == 0 then end io.write(sh.expand(os.getenv("PS1") or "$ ")) end - local command = tty:read(input_handler) + local command = tty.read(input_handler) if command then command = text.trim(command) if command == "exit" then diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua index 43e2d5222..b7c682233 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua @@ -1,4 +1,5 @@ -local shell = require('shell') +local shell = require("shell") +local tty = require("tty") local args, options = shell.parse(...) if options.help then @@ -50,4 +51,9 @@ for _,v in ipairs(args) do total_time = total_time + time_type_multiplier(time_type) * interval end -os.sleep(total_time) +local stdin_stream = io.stdin.stream +if stdin_stream.pull then + return stdin_stream:pull(nil, total_time, "interrupted") +else + os.sleep(total_time) +end diff --git a/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua b/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua index 1a8fa061b..f223b0d00 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/boot/03_io.lua @@ -1,14 +1,14 @@ local buffer = require("buffer") -local tty = require("tty") +local tty_stream = require("tty").stream -local core_stdin = buffer.new("r", tty) -local core_stdout = buffer.new("w", tty) +local core_stdin = buffer.new("r", tty_stream) +local core_stdout = buffer.new("w", tty_stream) local core_stderr = buffer.new("w", setmetatable( { write = function(_, str) - return tty:write("\27[31m"..str.."\27[37m") + return tty_stream:write("\27[31m"..str.."\27[37m") end - }, {__index=tty})) + }, {__index=tty_stream})) core_stdout:setvbuf("no") core_stderr:setvbuf("no") @@ -16,9 +16,9 @@ core_stdin.tty = true core_stdout.tty = true core_stderr.tty = true -core_stdin.close = tty.close -core_stdout.close = tty.close -core_stderr.close = tty.close +core_stdin.close = tty_stream.close +core_stdout.close = tty_stream.close +core_stderr.close = tty_stream.close local io_mt = getmetatable(io) or {} io_mt.__index = function(_, k) diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/core/boot.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/core/boot.lua index c0be1655b..775eca3f5 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/core/boot.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/core/boot.lua @@ -1,7 +1,7 @@ -- called from /init.lua local raw_loadfile = ... -_G._OSVERSION = "OpenOS 1.6.7" +_G._OSVERSION = "OpenOS 1.6.8" local component = component local computer = computer diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua index ad7997a63..48bdeeacd 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/core/lua_shell.lua @@ -10,12 +10,11 @@ end local env -- forward declare for binding in metamethod env = setmetatable({}, { - __index = function(t, k) + __index = function(_, k) _ENV[k] = _ENV[k] or optrequire(k) return _ENV[k] end, - __pairs = function(self) - local t = self + __pairs = function(t) return function(_, key) local k, v = next(t, key) if not k and t == env then @@ -94,7 +93,7 @@ io.write("Press Ctrl+D to exit the interpreter.\n\27[37m") while tty.isAvailable() do io.write(env._PROMPT) - local command = tty:read(read_handler) + local command = tty.read(read_handler) if not command then -- eof return end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua index 3ce1df9ff..c7466d0ca 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua @@ -70,7 +70,7 @@ end local function build_horizontal_reader(cursor) cursor.clear_tail = function(self) local w,_,dx,dy,x,y = tty.getViewport() - local _,s2=tty.internal.split(self) + local _,s2=tty.split(self) local wlen = math.min(unicode.wlen(s2),w-x+1) tty.gpu().fill(x+dx,y+dy,wlen,1," ") end @@ -198,15 +198,16 @@ function term.read(history, dobreak, hint, pwchar, filter) local handler = history handler.hint = handler.hint or hint - local cursor = tty.internal.build_vertical_reader() + local cursor = tty.build_vertical_reader() if handler.nowrap then build_horizontal_reader(cursor) end inject_filter(handler, filter) inject_mask(cursor, dobreak, pwchar or history.pwchar) + handler.cursor = cursor - return tty:read(handler, cursor) + return tty.read(handler) end function term.getGlobalArea(window) @@ -228,7 +229,15 @@ function term.pull(...) timeout = table.remove(args, 1) args.n = args.n - 1 end - return tty.pull(nil, timeout, table.unpack(args, 1, args.n)) + local stdin_stream = io.stdin.stream + if stdin_stream.pull then + return stdin_stream:pull(nil, timeout, table.unpack(args, 1, args.n)) + end + -- if stdin does not have pull() we can build the result + local result = io.read(1) + if result then + return "clipboard", nil, result + end end function term.bind(gpu, window) diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua index 317b28a7e..b1d860fd8 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua @@ -77,17 +77,27 @@ local function get_box_thread_handle(handles, bCreate) end function box_thread:resume() - if self:status() ~= "suspended" then - return nil, "cannot resume " .. self:status() .. " thread" + local mt = getmetatable(self) + if mt.__status ~= "suspended" then + return nil, "cannot resume " .. mt.__status .. " thread" + end + mt.__status = "running" + -- register the thread to wake up + if coroutine.status(self.pco.root) == "suspended" and not mt.reg then + mt.register(0) end - getmetatable(self).__status = "running" end function box_thread:suspend() - if self:status() ~= "running" then - return nil, "cannot suspend " .. self:status() .. " thread" + local mt = getmetatable(self) + if mt.__status ~= "running" then + return nil, "cannot suspend " .. mt.__status .. " thread" + end + mt.__status = "suspended" + local pco_status = coroutine.status(self.pco.root) + if pco_status == "running" or pco_status == "normal" then + mt.coma() end - getmetatable(self).__status = "suspended" end function box_thread:status() @@ -113,29 +123,27 @@ function box_thread:attach(parent) if not proc then return nil, "thread failed to attach, process not found" end if mt.attached == proc then return self end -- already attached - local waiting_handler if mt.attached then local prev_btHandle = assert(get_box_thread_handle(mt.attached.data.handles), "thread panic: no thread handle") for i,h in ipairs(prev_btHandle) do if h == self then table.remove(prev_btHandle, i) - if mt.id then - waiting_handler = assert(mt.attached.data.handlers[mt.id], "thread panic: no event handler") - mt.attached.data.handlers[mt.id] = nil - end break end end end + -- registration happens on the attached proc, unregister before reparenting + local waiting_handler = mt.unregister() + -- attach to parent or the current process mt.attached = proc - local handles = proc.data.handles -- this process may not have a box_thread manager handle - local btHandle = get_box_thread_handle(handles, true) + local btHandle = get_box_thread_handle(proc.data.handles, true) table.insert(btHandle, self) + -- register on the new parent if waiting_handler then -- event-waiting mt.register(waiting_handler.timeout - computer.uptime()) end @@ -143,6 +151,23 @@ function box_thread:attach(parent) return self end +function thread.current() + local proc = process.findProcess() + local thread_root + while proc do + if thread_root then + for _,bt in ipairs(get_box_thread_handle(proc.data.handles) or {}) do + if bt.pco.root == thread_root then + return bt + end + end + else + thread_root = proc.data.coroutine_handler.root + end + proc = proc.parent + end +end + function thread.create(fp, ...) checkArg(1, fp, "function") @@ -153,8 +178,8 @@ function thread.create(fp, ...) mt.__status = "running" local fp_co = t.pco.create(fp) -- run fp_co until dead - -- pullSignal will yield_all past this point - -- but yield will return here, we pullSignal from here to yield_all + -- pullSignal will yield_past this point + -- but yield will return here, we pullSignal from here to yield_past local args = table.pack(...) while true do local result = table.pack(t.pco.resume(fp_co, table.unpack(args, 1, args.n))) @@ -188,7 +213,7 @@ function thread.create(fp, ...) --special resume to keep track of process death function mt.private_resume(...) - mt.id = nil + mt.unregister() -- this thread may have been killed if t:status() == "dead" then return end local result = table.pack(t.pco.resume(t.pco.root, ...)) @@ -209,17 +234,50 @@ function thread.create(fp, ...) timeout, -- wait for the time specified by the caller 1, -- we only want this thread to wake up once mt.attached.data.handlers) -- optional arg, to specify our own handlers + mt.reg = mt.attached.data.handlers[mt.id] + end + + function mt.unregister() + local id = mt.id + local reg = mt.reg + mt.id = nil + mt.reg = nil + -- before just removing a handler, make sure it is still ours + if id and mt.attached and mt.attached.data.handlers[id] == reg then + mt.attached.data.handlers[id] = nil + return reg + end + end + + function mt.coma() + mt.unregister() -- we should not wake up again (until resumed) + while mt.__status == "suspended" do + t.pco.yield_past(t.pco.root, 0) + end end function mt.process.data.pull(_, timeout) + --[==[ + yield_past(root) will yield until out of this thread + registration puts in a callback to resume this thread + + Subsequent registrations are necessary in case the thread is suspended + This thread yields when suspended, entering a coma state + -> coma state: yield without registration + + resume will regsiter a wakeup call, breaks coma + + subsequent yields need not specify a timeout because + we already legitimately resumed only to find out we had been suspended + + 3 places register for wake up + 1. computer.pullSignal [this path] + 2. t:attach(proc) will unregister and re-register + 3. t:resume() of a suspended thread + ]==] mt.register(timeout) - -- yield_past(root) will yield until out of this thread - -- the callback will resume this stack - local event_data - repeat - event_data = table.pack(t.pco.yield_past(t.pco.root, timeout)) - -- during sleep, we may have been suspended - until t:status() ~= "suspended" + local event_data = table.pack(t.pco.yield_past(t.pco.root, timeout)) + mt.coma() return table.unpack(event_data, 1, event_data.n) end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua index 131975a8a..163bc0ce0 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua @@ -16,7 +16,7 @@ tty.window = y = 1, } -tty.internal = {} +tty.stream = {} function tty.key_down_handler(handler, cursor, char, code) local data = cursor.data @@ -101,7 +101,7 @@ function tty.isAvailable() return not not (gpu and gpu.getScreen()) end -function tty.pull(cursor, timeout, ...) +function tty.stream:pull(cursor, timeout, ...) local blink = tty.getCursorBlink() timeout = timeout or math.huge local blink_timeout = blink and .5 or math.huge @@ -171,7 +171,7 @@ function tty.pull(cursor, timeout, ...) end end -function tty.internal.split(cursor) +function tty.split(cursor) local data, index = cursor.data, cursor.index local dlen = unicode.len(data) index = math.max(0, math.min(index, dlen)) @@ -179,7 +179,7 @@ function tty.internal.split(cursor) return unicode.sub(data, 1, index), tail == 0 and "" or unicode.sub(data, -tail) end -function tty.internal.build_vertical_reader() +function tty.build_vertical_reader() local x, y = tty.getCursor() return { @@ -194,7 +194,7 @@ function tty.internal.build_vertical_reader() move = function(self, n) local win = tty.window self.index = math.min(math.max(0, self.index + n), unicode.len(self.data)) - local s1, s2 = tty.internal.split(self) + local s1, s2 = tty.split(self) s2 = unicode.sub(s2.." ", 1, 1) local data_remaining = ("_"):rep(self.promptx - 1)..s1..s2 win.y = self.prompty - self.sy @@ -221,7 +221,7 @@ function tty.internal.build_vertical_reader() tty.gpu().fill(cx + dx, ey + dy, width - cx + 1, 1, " ") end, update = function(self, arg) - local s1, s2 = tty.internal.split(self) + local s1, s2 = tty.split(self) if type(arg) == "string" then self.data = s1 .. arg .. s2 self.index = self.index + unicode.len(arg) @@ -256,28 +256,30 @@ function tty.internal.build_vertical_reader() self.data = "" end, draw = function(self, text) - self.sy = self.sy + tty:write(text) + self.sy = self.sy + tty.stream:write(text) end } end --- PLEASE do not use this method directly, use io.read or tty.read -function tty.read(_, handler, cursor) - checkArg(1, handler, "table", "number") - checkArg(2, cursor, "table", "nil") +function tty.read(handler) + tty.window.handler = handler - if not io.stdin.tty then - return io.stdin:readLine(false) - end + local result = table.pack(pcall(io.read)) + tty.window.handler = nil - if type(handler) ~= "table" then - handler = {} - end + return select(2, assert(table.unpack(result))) +end + +-- PLEASE do not use this method directly, use io.read or term.read +function tty.stream:read() + local handler = tty.window.handler or {} + local cursor = handler.cursor or tty.build_vertical_reader() + + tty.window.handler = nil handler.index = 0 - cursor = cursor or tty.internal.build_vertical_reader() while true do - local name, address, char, code = tty.pull(cursor) + local name, address, char, code = tty.stream:pull(cursor) -- we may have lost tty during the pull if not tty.isAvailable() then return @@ -288,7 +290,7 @@ function tty.read(_, handler, cursor) local main_kb = tty.keyboard() local main_sc = tty.screen() if name == "interrupted" then - tty:write("^C\n") + tty.stream:write("^C\n") return false elseif address == main_kb or address == main_sc then local handler_method = handler[name] or @@ -321,10 +323,7 @@ function tty.setCursor(x, y) end -- PLEASE do not use this method directly, use io.write or term.write -function tty.write(_, value) - if not io.stdout.tty then - return io.write(value) - end +function tty.stream:write(value) local gpu = tty.gpu() if not gpu then return @@ -446,10 +445,12 @@ function tty.bind(gpu) end end local window = tty.window - window.gpu = gpu - window.keyboard = nil -- without a keyboard bound, always use the screen's main keyboard (1st) + if not window.gpu or window.gpu == gpu then + window.gpu = gpu + window.keyboard = nil -- without a keyboard bound, always use the screen's main keyboard (1st) + tty.getViewport() + end screen_reset(gpu) - tty.getViewport() end function tty.keyboard() @@ -492,17 +493,29 @@ function tty.screen() return gpu.getScreen() end -function tty.scroll(number) +function tty.scroll(lines) local gpu = tty.gpu() if not gpu then return 0 end local width, height, dx, dy, x, y = tty.getViewport() - local lines = number or (y - height) - if lines == 0 -- if zero scroll length is requested, do nothing - or not number and lines < 0 then -- do not auto scroll back up, only down - return 0 + -- nil lines indicates a request to auto scroll + -- auto scroll is when the cursor has gone below the bottom on the terminal + -- and the text is scroll up, pulling the cursor back into view + + -- lines<0 scrolls up (text down) + -- lines>0 scrolls down (text up) + + -- no lines count given, the user is asking to auto scroll y back into view + if not lines then + if y < 1 then + lines = y - 1 -- y==0 scrolls back -1 + elseif y > height then + lines = y - height -- y==height+1 scroll forward 1 + else + return 0 -- do nothing + end end lines = math.min(lines, height) @@ -516,16 +529,16 @@ function tty.scroll(number) gpu.copy(dx + 1, dy + 1 + math.max(0, lines), width, box_height, 0, -lines) gpu.fill(dx + 1, fill_top, width, abs_lines, ' ') - tty.setCursor(x, math.min(y, height)) + tty.setCursor(x, math.max(1, math.min(y, height))) return lines end -- stream methods local function bfd() return nil, "tty: invalid operation" end -tty.close = bfd -tty.seek = bfd -tty.handle = "tty" +tty.stream.close = bfd +tty.stream.seek = bfd +tty.stream.handle = "tty" require("package").delay(tty, "/lib/core/full_tty.lua") From ae501a859d06a6354ca34eef0ec0d28a9ff37c85 Mon Sep 17 00:00:00 2001 From: payonel Date: Thu, 7 Sep 2017 10:34:47 -0700 Subject: [PATCH 4/9] return true from thread method as per documented specification --- .../resources/assets/opencomputers/loot/openos/lib/thread.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua index b1d860fd8..5c62cee07 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/thread.lua @@ -86,6 +86,7 @@ function box_thread:resume() if coroutine.status(self.pco.root) == "suspended" and not mt.reg then mt.register(0) end + return true end function box_thread:suspend() @@ -98,6 +99,7 @@ function box_thread:suspend() if pco_status == "running" or pco_status == "normal" then mt.coma() end + return true end function box_thread:status() From 81ffb2187b8c20246bd4b6637b6fae8ef4d9b0ce Mon Sep 17 00:00:00 2001 From: payonel Date: Thu, 7 Sep 2017 18:13:15 -0700 Subject: [PATCH 5/9] Merged contribution from BillyJimson https://github.com/MightyPirates/OpenComputers/pull/2324 --- src/main/resources/assets/opencomputers/robot.names | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/opencomputers/robot.names b/src/main/resources/assets/opencomputers/robot.names index 1635f27cc..09d81f2bc 100644 --- a/src/main/resources/assets/opencomputers/robot.names +++ b/src/main/resources/assets/opencomputers/robot.names @@ -73,6 +73,7 @@ Laire # Perry Rhodan Loader 1340 # Borderlands 2 LordFokas # Contributor Marvin # Hitchhiker's Guide to the Galaxy +Mawhrin-skel # The Player of Games (Iain M Banks) Michiyo # Contributor *Mute # Analogue: A Hate Story / Hate Plus Mycroft Holmes # The Moon Is a Harsh Mistress @@ -87,6 +88,7 @@ Replicator # Stargate Robby # Forbidden Planet Roomba # Under your couch... wait. Rosie # The Jetsons +Skaffen-Amtiskaw # Use of weapons (Iain M Banks) Shakey # The first general-purpose mobile robot that could reason about its actions. SHODAN # System Shock Skynet # Terminator From eaf2b0cf8a6f0dbbfd7a553b5c25dd0cc698f6ba Mon Sep 17 00:00:00 2001 From: payonel Date: Fri, 8 Sep 2017 00:49:50 -0700 Subject: [PATCH 6/9] ignore the robot magic filesystem with install, and small /bin/sleep fix /bin/sleep ^c was printing an error because it was returning the event data, which prompts was interpretting as error details [unexpected] use a .prop file to have the robot component magic fs be ignored when running `install` --- .../resources/assets/opencomputers/loot/openos/bin/sleep.lua | 4 ++-- .../resources/assets/opencomputers/lua/component/robot/.prop | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/lua/component/robot/.prop diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua index b7c682233..f8091f2fa 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua @@ -53,7 +53,7 @@ end local stdin_stream = io.stdin.stream if stdin_stream.pull then - return stdin_stream:pull(nil, total_time, "interrupted") + stdin_stream:pull(nil, total_time, "interrupted") else - os.sleep(total_time) + require("event").pull(total_time, "interrupted") end diff --git a/src/main/resources/assets/opencomputers/lua/component/robot/.prop b/src/main/resources/assets/opencomputers/lua/component/robot/.prop new file mode 100644 index 000000000..57d53fa41 --- /dev/null +++ b/src/main/resources/assets/opencomputers/lua/component/robot/.prop @@ -0,0 +1 @@ +{ignore=true} From 1bc6e84af2d3810d8008b415508d49916a19a2a9 Mon Sep 17 00:00:00 2001 From: payonel Date: Thu, 7 Sep 2017 20:26:16 -0700 Subject: [PATCH 7/9] use a growing vector of string parts to serialize a string, returning table.concat when done --- .../loot/openos/lib/serialization.lua | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua index c59c664ed..b609f7ff1 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua @@ -17,40 +17,41 @@ function serialization.serialize(value, pretty) ["until"]=true, ["while"]=true} local id = "^[%a_][%w_]*$" local ts = {} - local function s(v, l) - local t = type(v) + local result_pack = {} + local function recurse(current_value, depth) + local t = type(current_value) if t == "nil" then - return "nil" + table.insert(result_pack, "nil") elseif t == "boolean" then - return v and "true" or "false" + table.insert(result_pack, current_value and "true" or "false") elseif t == "number" then - if v ~= v then - return "0/0" - elseif v == math.huge then - return "math.huge" - elseif v == -math.huge then - return "-math.huge" + if current_value ~= current_value then + table.insert(result_pack, "0/0") + elseif current_value == math.huge then + table.insert(result_pack, "math.huge") + elseif current_value == -math.huge then + table.insert(result_pack, "-math.huge") else - return tostring(v) + table.insert(result_pack, tostring(current_value)) end elseif t == "string" then - return string.format("%q", v):gsub("\\\n","\\n") - elseif t == "table" and pretty and getmetatable(v) and getmetatable(v).__tostring then - return tostring(v) + table.insert(result_pack, (string.format("%q", current_value):gsub("\\\n","\\n"))) + elseif t == "table" and pretty and getmetatable(current_value) and getmetatable(current_value).__tostring then + table.insert(result_pack, tostring(current_value)) elseif t == "table" then - if ts[v] then + if ts[current_value] then if pretty then - return "recursion" + table.insert(result_pack, "recursion") + return else error("tables with cycles are not supported") end end - ts[v] = true - local i, r = 1, nil + ts[current_value] = true local f if pretty then local ks, sks, oks = {}, {}, {} - for k in local_pairs(v) do + for k in local_pairs(current_value) do if type(k) == "number" then table.insert(ks, k) elseif type(k) == "string" then @@ -72,44 +73,53 @@ function serialization.serialize(value, pretty) n = n + 1 local k = ks[n] if k ~= nil then - return k, v[k] + return k, current_value[k] else return nil end end) else - f = table.pack(local_pairs(v)) + f = table.pack(local_pairs(current_value)) end + local i = 1 + local first = true + table.insert(result_pack, "{") for k, v in table.unpack(f) do - if r then - r = r .. "," .. (pretty and ("\n" .. string.rep(" ", l)) or "") - else - r = "{" + if not first then + table.insert(result_pack, ",") + if pretty then + table.insert(result_pack, "\n" .. string.rep(" ", depth)) + end end + first = nil local tk = type(k) if tk == "number" and k == i then i = i + 1 - r = r .. s(v, l + 1) + recurse(v, depth + 1) else if tk == "string" and not kw[k] and string.match(k, id) then - r = r .. k + table.insert(result_pack, k) else - r = r .. "[" .. s(k, l + 1) .. "]" + table.insert(result_pack, "[") + recurse(k, depth + 1) + table.insert(result_pack, "]") end - r = r .. "=" .. s(v, l + 1) + table.insert(result_pack, "=") + recurse(v, depth + 1) end end - ts[v] = nil -- allow writing same table more than once - return (r or "{") .. "}" + ts[current_value] = nil -- allow writing same table more than once + table.insert(result_pack, "}") else if pretty then - return tostring(v) + table.insert(result_pack, tostring(current_value)) else error("unsupported type: " .. t) end end end - local result = s(value, 1) + recurse(value, 1) + local result = table.concat(result_pack) local limit = type(pretty) == "number" and pretty or 10 if pretty then local truncate = 0 From 8af5c0d05651a9fbc64dccaa768904702d1e2bd0 Mon Sep 17 00:00:00 2001 From: payonel Date: Thu, 7 Sep 2017 21:15:34 -0700 Subject: [PATCH 8/9] further serialization cleanup --- .../loot/openos/lib/serialization.lua | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua index b609f7ff1..d2ab295b9 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/serialization.lua @@ -20,11 +20,7 @@ function serialization.serialize(value, pretty) local result_pack = {} local function recurse(current_value, depth) local t = type(current_value) - if t == "nil" then - table.insert(result_pack, "nil") - elseif t == "boolean" then - table.insert(result_pack, current_value and "true" or "false") - elseif t == "number" then + if t == "number" then if current_value ~= current_value then table.insert(result_pack, "0/0") elseif current_value == math.huge then @@ -36,7 +32,10 @@ function serialization.serialize(value, pretty) end elseif t == "string" then table.insert(result_pack, (string.format("%q", current_value):gsub("\\\n","\\n"))) - elseif t == "table" and pretty and getmetatable(current_value) and getmetatable(current_value).__tostring then + elseif + t == "nil" or + t == "boolean" or + pretty and (t ~= "table" or (getmetatable(current_value) or {}).__tostring) then table.insert(result_pack, tostring(current_value)) elseif t == "table" then if ts[current_value] then @@ -111,17 +110,13 @@ function serialization.serialize(value, pretty) ts[current_value] = nil -- allow writing same table more than once table.insert(result_pack, "}") else - if pretty then - table.insert(result_pack, tostring(current_value)) - else - error("unsupported type: " .. t) - end + error("unsupported type: " .. t) end end recurse(value, 1) local result = table.concat(result_pack) - local limit = type(pretty) == "number" and pretty or 10 if pretty then + local limit = type(pretty) == "number" and pretty or 10 local truncate = 0 while limit > 0 and truncate do truncate = string.find(result, "\n", truncate + 1, true) From d8033669ebcf32b945bcb3249dc7484b72468242 Mon Sep 17 00:00:00 2001 From: payonel Date: Sun, 10 Sep 2017 00:58:54 -0700 Subject: [PATCH 9/9] optimizations and fixes * /bin/cat chunk based [huge performance and memory savings, can handle enormous files now] * /bin/sleep blinks now * removed unnecessary methods from tty * cursor blinking and scrolling terminal improvements * fixed bad term call to tty write --- .../opencomputers/loot/openos/bin/cat.lua | 10 +- .../opencomputers/loot/openos/bin/rm.lua | 2 +- .../opencomputers/loot/openos/bin/sleep.lua | 12 +- .../opencomputers/loot/openos/etc/profile.lua | 1 - .../loot/openos/lib/core/full_tty.lua | 4 - .../opencomputers/loot/openos/lib/term.lua | 56 ++++--- .../opencomputers/loot/openos/lib/tty.lua | 151 ++++++++---------- .../opencomputers/loot/openos/lib/vt100.lua | 4 +- 8 files changed, 115 insertions(+), 125 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua index 6a943ab78..c1e9818f8 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua @@ -17,18 +17,18 @@ for i = 1, #args do if args[i] == "-" then file, reason = io.stdin, "missing stdin" else - file, reason = io.open(shell.resolve(args[i])) + file, reason = fs.open(shell.resolve(args[i])) end if not file then io.stderr:write(string.format("cat: %s: %s\n", args[i], tostring(reason))) ec = 1 else repeat - local line = file:read("*L") - if line then - io.write(line) + local chunk = file:read(2048) + if chunk then + io.write(chunk) end - until not line + until not chunk file:close() end end diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/rm.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/rm.lua index d77d6a322..48ed9d0c8 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/rm.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/rm.lua @@ -68,7 +68,7 @@ local function confirm() if bForce then return true end - local r = io.read("*l") + local r = io.read() return r == 'y' or r == 'yes' end diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua index f8091f2fa..7201bf73b 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/sleep.lua @@ -51,9 +51,11 @@ for _,v in ipairs(args) do total_time = total_time + time_type_multiplier(time_type) * interval end -local stdin_stream = io.stdin.stream -if stdin_stream.pull then - stdin_stream:pull(nil, total_time, "interrupted") -else - require("event").pull(total_time, "interrupted") +local ins = io.stdin.stream +local pull = ins.pull +local start = 1 +if not pull then + pull = require("event").pull + start = 2 end +pull(select(start, ins, total_time, "interrupted")) diff --git a/src/main/resources/assets/opencomputers/loot/openos/etc/profile.lua b/src/main/resources/assets/opencomputers/loot/openos/etc/profile.lua index 76c7ecca3..0fe8487e2 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/etc/profile.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/etc/profile.lua @@ -7,7 +7,6 @@ if tty.isAvailable() then io.write("\27[40m\27[37m") tty.clear() end - tty.setCursorBlink(true) end dofile("/etc/motd") diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/core/full_tty.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/core/full_tty.lua index 9347e8537..c52eae35b 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/core/full_tty.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/core/full_tty.lua @@ -85,7 +85,3 @@ function tty.on_tab(handler, cursor) cursor:move(-tail) end end - -function tty:size() - return #(self.window.ansi_response or "") -end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua index c7466d0ca..aa42c04c5 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua @@ -87,15 +87,16 @@ local function build_horizontal_reader(cursor) cursor.draw = function(_, text) local nowrap = tty.window.nowrap tty.window.nowrap = true - tty:write(text) + tty.stream:write(text) tty.window.nowrap = nowrap end - cursor.scroll = function(self) + cursor.scroll = function(self, goback, prev_x) local win = tty.window - local gpu,data,px,i = win.gpu, self.data, self.promptx, self.index - local w,_,dx,dy,x,y = tty.getViewport() - win.x = math.max(self.promptx, math.min(w, x)) - local available,sx,sy = w-px+1,px+dx,y+dy + win.x = goback and prev_x or win.x + local x = win.x + local w = win.width + local data,px,i = self.data, self.promptx, self.index + local available = w-px+1 if x > w then local blank if i == unicode.len(data) then @@ -107,14 +108,19 @@ local function build_horizontal_reader(cursor) local rev = unicode.reverse(data) local ending = unicode.wtrunc(rev, available+1) data = unicode.reverse(ending) - gpu.set(sx,sy,data..blank) - win.x=math.min(w,self.promptx+unicode.wlen(data)) + win.x = self.promptx + self:draw(data..blank) + -- wide chars may place the cursor not exactly at the end + win.x = math.min(w, self.promptx + unicode.wlen(data)) + -- x could be negative, we scroll it back into view elseif x < self.promptx then data = unicode.sub(data, self.index+1) if unicode.wlen(data) > available then data = unicode.wtrunc(data,available+1) end - gpu.set(sx,sy,data) + win.x = self.promptx + self:draw(data) + win.x = math.max(px, math.min(w, x)) end end cursor.clear = function(self) @@ -135,25 +141,15 @@ local function inject_filter(handler, filter) end end - local mt = - { - __newindex = function(tbl, key, value) - if key == "key_down" then - local tty_key_down = value - value = function(_handler, cursor, char, code) - if code == keys.enter or code == keys.numpadenter then - if not filter(cursor.data) then - computer.beep(2000, 0.1) - return false -- ignore - end - end - return tty_key_down(_handler, cursor, char, code) - end + handler.key_down = function(self, cursor, char, code) + if code == keys.enter or code == keys.numpadenter then + if not filter(cursor.data) then + computer.beep(2000, 0.1) + return false -- ignore end - rawset(tbl, key, value) end - } - setmetatable(handler, mt) + return tty.key_down_handler(self, cursor, char, code) + end end end @@ -222,6 +218,14 @@ function term.clearLine(window) window.x = 1 end +function term.setCursorBlink(enabled) + tty.window.blink = enabled +end + +function term.getCursorBlink() + return tty.window.blink +end + function term.pull(...) local args = table.pack(...) local timeout = nil diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua index 163bc0ce0..588f7f385 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tty.lua @@ -92,7 +92,7 @@ function tty.gpu() end function tty.clear() - tty.scroll(math.huge) + tty.stream.scroll(math.huge) tty.setCursor(1, 1) end @@ -101,73 +101,62 @@ function tty.isAvailable() return not not (gpu and gpu.getScreen()) end -function tty.stream:pull(cursor, timeout, ...) - local blink = tty.getCursorBlink() - timeout = timeout or math.huge - local blink_timeout = blink and .5 or math.huge - local gpu = tty.gpu() +function tty.stream:blink(done) local width, height, dx, dy, x, y = tty.getViewport() - - if gpu then - if x < 1 or x > width or y < 1 or y > height then - if cursor then - cursor:move(0) - cursor:scroll() - else - gpu = nil - end - end - x, y = tty.getCursor() - x, y = x + dx, y + dy + local gpu = tty.gpu() + if not gpu or x < 1 or x > width or y < 1 or y > height then + return true end - - local bgColor, bgIsPalette - local fgColor, fgIsPalette - local char_at_cursor - if gpu then + x, y = x + dx, y + dy + local blinked, bgColor, bgIsPalette, fgColor, fgIsPalette, char_at_cursor = table.unpack(self.blink_cache or {}) + if done == nil then -- reset + blinked = false bgColor, bgIsPalette = gpu.getBackground() -- it can happen during a type of race condition when a screen is removed if not bgColor then - return nil, "interrupted" + return end fgColor, fgIsPalette = gpu.getForeground() char_at_cursor = gpu.get(x, y) end + if not blinked and not done then + gpu.setForeground(bgColor, bgIsPalette) + gpu.setBackground(fgColor, fgIsPalette) + gpu.set(x, y, char_at_cursor) + gpu.setForeground(fgColor, fgIsPalette) + gpu.setBackground(bgColor, bgIsPalette) + blinked = true + elseif blinked and (done or tty.window.blink) then + gpu.set(x, y, char_at_cursor) + blinked = false + end + + self.blink_cache = table.pack(blinked, bgColor, bgIsPalette, fgColor, fgIsPalette, char_at_cursor) + return true +end + +function tty.stream:pull(timeout, ...) + timeout = timeout or math.huge + local blink_timeout = tty.window.blink and .5 or math.huge + + -- it can happen during a type of race condition when a screen is removed + if not self:blink() then + return nil, "interrupted" + end + -- get the next event - local blinked = false - local done = false - local signal while true do - if gpu then - if not blinked and not done then - gpu.setForeground(bgColor, bgIsPalette) - gpu.setBackground(fgColor, fgIsPalette) - gpu.set(x, y, char_at_cursor) - gpu.setForeground(fgColor, fgIsPalette) - gpu.setBackground(bgColor, bgIsPalette) - blinked = true - elseif blinked and (done or blink) then - gpu.set(x, y, char_at_cursor) - blinked = false - end - end + local signal = table.pack(event.pull(math.min(blink_timeout, timeout), ...)) + + timeout = timeout - blink_timeout + local done = signal.n > 1 or timeout < blink_timeout + self:blink(done) if done then return table.unpack(signal, 1, signal.n) end - - -- if vt100 ansi codes have anything buffered for read, return that first - if tty.window.ansi_response then - signal = {"clipboard", tty.keyboard(), tty.window.ansi_response, n=3} - tty.window.ansi_response = nil - else - signal = table.pack(event.pull(math.min(blink_timeout, timeout), ...)) - end - - timeout = timeout - blink_timeout - done = signal.n > 1 or timeout < blink_timeout end end @@ -180,16 +169,20 @@ function tty.split(cursor) end function tty.build_vertical_reader() - local x, y = tty.getCursor() return { - promptx = x, - prompty = y, + promptx = tty.window.x, + prompty = tty.window.y, index = 0, data = "", sy = 0, - scroll = function(self) - self.sy = self.sy + tty.scroll() + scroll = function(self, goback, prev_x, prev_y) + local width, x = tty.window.width, tty.getCursor() - 1 + tty.setCursor(x % width + 1, tty.window.y + math.floor(x / width)) + self:draw("") + if goback then + tty.setCursor(prev_x, prev_y - self.sy) + end end, move = function(self, n) local win = tty.window @@ -242,11 +235,10 @@ function tty.build_vertical_reader() end -- redraw suffix - if s2 ~= "" then - local ps, px, py = self.sy, tty.getCursor() - self:draw(s2) - tty.setCursor(px, py - (self.sy - ps)) - end + local prev_x, prev_y = tty.getCursor() + prev_y = prev_y + self.sy -- scroll will remove it + self:draw(s2) + self:scroll(s2 ~= "", prev_x, prev_y) end, clear = function(self) self:move(-math.huge) @@ -264,9 +256,9 @@ end function tty.read(handler) tty.window.handler = handler - local result = table.pack(pcall(io.read)) + local stdin = io.stdin + local result = table.pack(pcall(stdin.readLine, stdin, false)) tty.window.handler = nil - return select(2, assert(table.unpack(result))) end @@ -279,7 +271,7 @@ function tty.stream:read() handler.index = 0 while true do - local name, address, char, code = tty.stream:pull(cursor) + local name, address, char, code = self:pull() -- we may have lost tty during the pull if not tty.isAvailable() then return @@ -290,7 +282,7 @@ function tty.stream:read() local main_kb = tty.keyboard() local main_sc = tty.screen() if name == "interrupted" then - tty.stream:write("^C\n") + self:write("^C\n") return false elseif address == main_kb or address == main_sc then local handler_method = handler[name] or @@ -369,7 +361,7 @@ function tty.stream:write(value) -- scroll before parsing next line -- the value may only have been a newline - sy = sy + tty.scroll() + sy = sy + self.scroll() -- we may have needed to scroll one last time [nowrap adjustments] if #value == 0 then break @@ -385,15 +377,18 @@ function tty.stream:write(value) local tail = "" local wlen_needed = unicode.wlen(segment) local wlen_remaining = window.width - x + 1 - if not window.nowrap and wlen_remaining < wlen_needed then + if wlen_remaining < wlen_needed then segment = unicode.wtrunc(segment, wlen_remaining + 1) - wlen_needed = unicode.wlen(segment) + local wlen_used = unicode.wlen(segment) -- we can clear the line because we already know remaining < needed - tail = (" "):rep(wlen_remaining - wlen_needed) - -- we have to reparse the delimeter - ei = #segment - -- fake a newline - delim = "\n" + tail = (" "):rep(wlen_remaining - wlen_used) + if not window.nowrap then + -- we have to reparse the delimeter + ei = #segment + -- fake a newline + delim = "\n" + wlen_needed = wlen_used + end end gpu.set(gpu_x, gpu_y, segment..tail) x = x + wlen_needed @@ -419,14 +414,6 @@ function tty.stream:write(value) return sy end -function tty.setCursorBlink(enabled) - tty.window.blink = enabled -end - -function tty.getCursorBlink() - return tty.window.blink -end - local gpu_intercept = {} function tty.bind(gpu) checkArg(1, gpu, "table") @@ -493,7 +480,7 @@ function tty.screen() return gpu.getScreen() end -function tty.scroll(lines) +function tty.stream.scroll(lines) local gpu = tty.gpu() if not gpu then return 0 diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua index 8e0972530..fc06ad8f6 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/vt100.lua @@ -120,7 +120,9 @@ end -- [6n get the cursor position [ EscLine;ColumnR Response: cursor is at v,h ] rules[{"%[", "6", "n"}] = function(window) - window.ansi_response = string.format("%s%d;%dR", string.char(0x1b), window.y, window.x) + -- this solution puts the response on stdin, but it isn't echo'd + -- I'm personally fine with the lack of echo + io.stdin.bufferRead = string.format("%s%s%d;%dR", io.stdin.bufferRead, string.char(0x1b), window.y, window.x) end -- D scroll up one line -- moves cursor down