IonutParau 687cfebd00 testing version of LuaBIOS and OpenOS
people were having issues getting them to work so now we promote consistency
2025-06-28 20:41:49 +02:00

173 lines
4.4 KiB
Lua

local tty = require("tty")
local computer = require("computer")
local process = require("process")
local event = require("event")
local core_cursor = require("core/cursor")
local kb = require("keyboard")
local keys = kb.keys
local term = setmetatable({internal={}}, {__index=tty})
local function as_window(window, func, ...)
local data = process.info().data
if not data.window or not window then
return func(...)
end
local prev = rawget(data, "window")
data.window = window
local ret = table.pack(func(...))
data.window = prev
return table.unpack(ret, 1, ret.n)
end
function term.internal.open(...)
local dx, dy, w, h = ...
local window = {fullscreen=select("#",...) == 0, blink = true, output_buffer = ""}
-- support legacy code using direct manipulation of w and h
-- (e.g. wocchat) instead of using setViewport
setmetatable(window,
{
__index = function(tbl, key)
key = key == "w" and "width" or key == "h" and "height" or key
return rawget(tbl, key)
end,
__newindex = function(tbl, key, value)
key = key == "w" and "width" or key == "h" and "height" or key
return rawset(tbl, key, value)
end
})
-- first time we open a pty the current tty.window must become the process window
if rawget(tty, "window") then
for _,p in pairs(process.list) do
if not p.parent then
p.data.window = tty.window
break
end
end
tty.window = nil
setmetatable(tty,
{
__index = function(_, key)
if key == "window" then
return process.info().data.window
end
end
})
end
as_window(window, tty.setViewport, w, h, dx, dy, 1, 1)
as_window(window, tty.bind, tty.gpu())
return window
end
local function create_cursor(history, ops)
local cursor = history or {}
cursor.hint = ops.hint or cursor.hint
local filter = ops.filter or cursor.filter
if filter then
if type(filter) == "string" then
local filter_text = filter
filter = function(text)
return text:match(filter_text)
end
end
function cursor:handle(name, char, code)
if name == "key_down" and (code == keys.enter or code == keys.numpadenter) then
if not filter(self.data) then
computer.beep(2000, 0.1)
return true -- handled
end
end
return self.super.handle(self, name, char, code)
end
end
local pwchar = ops.pwchar or cursor.pwchar
local nobreak = ops.dobreak == false or cursor.dobreak == false
if pwchar or nobreak then
if type(pwchar) == "string" then
local pwchar_text = pwchar
pwchar = function(text)
return text:gsub(".", pwchar_text)
end
end
function cursor:echo(arg, ...)
if pwchar and type(arg) == "string" and #arg > 0 and not arg:match("^\27") then -- "" is used for scrolling
arg = pwchar(arg)
elseif nobreak and arg == "\n" then
arg = ""
end
return self.super.echo(self, arg, ...)
end
end
return core_cursor.new(cursor, cursor.nowrap and core_cursor.horizontal)
end
-- cannot use term.write = io.write because io.write invokes metatable
function term.write(value, wrap)
io.stdout:flush()
local previous_nowrap = tty.window.nowrap
tty.window.nowrap = wrap == false
io.write(value)
io.stdout:flush()
tty.window.nowrap = previous_nowrap
end
function term.read(history, dobreak, hint, pwchar, filter)
tty.window.cursor = create_cursor(history, {
dobreak = dobreak,
pwchar = pwchar,
filter = filter,
hint = hint
})
return io.stdin:readLine(false)
end
function term.getGlobalArea()
local w,h,dx,dy = tty.getViewport()
return dx+1,dy+1,w,h
end
function term.clearLine()
term.write("\27[2K\27[999D")
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 = math.huge
if type(args[1]) == "number" then
timeout = computer.uptime() + table.remove(args, 1)
args.n = args.n - 1
end
local cursor = core_cursor.new()
while timeout >= computer.uptime() do
cursor:echo()
local s = table.pack(event.pull(.5, table.unpack(args, 1, args.n)))
cursor:echo(not s[1])
if s.n > 1 then return table.unpack(s, 1, s.n) end
end
end
function term.bind(gpu, window)
return as_window(window, tty.bind, gpu)
end
term.scroll = tty.stream.scroll
term.internal.run_in_window = as_window
return term