mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 09:03:32 +02:00
173 lines
4.4 KiB
Lua
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
|