Compare commits
3 Commits
23173506b9
...
fc127f8d3e
Author | SHA1 | Date | |
---|---|---|---|
fc127f8d3e | |||
2327dc9c18 | |||
0cdd70e917 |
197
lib/vtansi.lua
Normal file
197
lib/vtansi.lua
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
local vtansi = {}
|
||||||
|
function vtansi.vtemu(gpu) -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal
|
||||||
|
local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF}
|
||||||
|
local mx, my = gpu.maxResolution()
|
||||||
|
local cx, cy = 1, 1
|
||||||
|
local pc = " "
|
||||||
|
local lc = ""
|
||||||
|
local mode = 0 -- 0 normal, 1 escape, 2 command
|
||||||
|
local lw = true
|
||||||
|
local sx, sy = 1,1
|
||||||
|
local cs = ""
|
||||||
|
local bg, fg = 0, 0xFFFFFF
|
||||||
|
|
||||||
|
-- setup
|
||||||
|
gpu.setResolution(mx,my)
|
||||||
|
gpu.fill(1,1,mx,my," ")
|
||||||
|
local function checkCursor()
|
||||||
|
if cx > mx and lw then
|
||||||
|
cx, cy = 1, cy+1
|
||||||
|
end
|
||||||
|
if cy > my then
|
||||||
|
gpu.copy(1,2,mx,my-1,0,-1)
|
||||||
|
gpu.fill(1,my,mx,1," ")
|
||||||
|
cy=my
|
||||||
|
end
|
||||||
|
if cy < 1 then cy = 1 end
|
||||||
|
if cx < 1 then cx = 1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function termwrite(s)
|
||||||
|
local wb = ""
|
||||||
|
local lb, ec = nil, nil
|
||||||
|
local function flushwb()
|
||||||
|
while wb:len() > 0 do
|
||||||
|
checkCursor()
|
||||||
|
local wl = wb:sub(1,mx-cx+1)
|
||||||
|
wb = wb:sub(wl:len()+1)
|
||||||
|
gpu.set(cx, cy, wl)
|
||||||
|
cx = cx + wl:len()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local rs = ""
|
||||||
|
s=s:gsub("\8","\27[D")
|
||||||
|
pc = gpu.get(cx,cy)
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
gpu.set(cx,cy,pc)
|
||||||
|
for cc in s:gmatch(".") do
|
||||||
|
if mode == 0 then
|
||||||
|
if cc == "\n" then
|
||||||
|
flushwb()
|
||||||
|
cx,cy = 1, cy+1
|
||||||
|
elseif cc == "\t" then
|
||||||
|
wb=wb..(" "):rep(8*((cx+9)//8))
|
||||||
|
elseif cc == "\27" then
|
||||||
|
flushwb()
|
||||||
|
mode = 1
|
||||||
|
else
|
||||||
|
wb = wb .. cc
|
||||||
|
end
|
||||||
|
elseif mode == 1 then
|
||||||
|
if cc == "[" then
|
||||||
|
mode = 2
|
||||||
|
else
|
||||||
|
mode = 0
|
||||||
|
end
|
||||||
|
elseif mode == 2 then
|
||||||
|
if cc:match("[%d;]") then
|
||||||
|
cs = cs .. cc
|
||||||
|
else
|
||||||
|
mode = 0
|
||||||
|
local tA = {}
|
||||||
|
for s in cs:gmatch("%d+") do
|
||||||
|
tA[#tA+1] = tonumber(s)
|
||||||
|
end
|
||||||
|
if cc == "H" then
|
||||||
|
cx, cy = tA[1] or 1, tA[2] or 1
|
||||||
|
elseif cc == "A" then
|
||||||
|
cy = cy - (tA[1] or 1)
|
||||||
|
elseif cc == "B" then
|
||||||
|
cy = cy + (tA[1] or 1)
|
||||||
|
elseif cc == "C" then
|
||||||
|
cx = cx + (tA[1] or 1)
|
||||||
|
elseif cc == "D" then
|
||||||
|
cx = cx - (tA[1] or 1)
|
||||||
|
elseif cc == "s" then
|
||||||
|
sx, sy = cx, cy
|
||||||
|
elseif cc == "u" then
|
||||||
|
cx, cy = sx, sy
|
||||||
|
elseif cc == "n" and tA[1] == 6 then
|
||||||
|
rs = string.format("%s\27[%d;%dR",rs,cx,cy)
|
||||||
|
elseif cc == "K" and tA[1] == 1 then
|
||||||
|
gpu.fill(1,cy,cx,1," ")
|
||||||
|
elseif cc == "K" and tA[1] == 2 then
|
||||||
|
gpu.fill(cx,cy,mx,1," ")
|
||||||
|
elseif cc == "K" then
|
||||||
|
gpu.fill(1,cy,mx,1," ")
|
||||||
|
elseif cc == "J" and tA[1] == 1 then
|
||||||
|
gpu.fill(1,1,mx,cy," ")
|
||||||
|
elseif cc == "J" and tA[1] == 2 then
|
||||||
|
gpu.fill(1,1,mx,my," ")
|
||||||
|
cx, cy = 1, 1
|
||||||
|
elseif cc == "J" then
|
||||||
|
gpu.fill(1,cy,mx,my," ")
|
||||||
|
elseif cc == "m" then
|
||||||
|
for _,num in ipairs(tA) do
|
||||||
|
if num == 0 then
|
||||||
|
fg,bg,ec,lb = 0xFFFFFF,0,true,true
|
||||||
|
elseif num == 7 then
|
||||||
|
local nfg,nbg = bg, fg
|
||||||
|
fg, bg = nfg, nbg
|
||||||
|
elseif num > 29 and num < 38 then
|
||||||
|
fg = colours[num-29]
|
||||||
|
elseif num > 39 and num < 48 then
|
||||||
|
bg = colours[num-39]
|
||||||
|
elseif num == 100 then -- disable local echo
|
||||||
|
ec = false
|
||||||
|
elseif num == 101 then -- disable line mode
|
||||||
|
lb = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
end
|
||||||
|
cs = ""
|
||||||
|
checkCursor()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
flushwb()
|
||||||
|
checkCursor()
|
||||||
|
pc = gpu.get(cx,cy)
|
||||||
|
gpu.setForeground(bg)
|
||||||
|
gpu.setBackground(fg)
|
||||||
|
gpu.set(cx,cy,pc)
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
return rs, lb, ec
|
||||||
|
end
|
||||||
|
|
||||||
|
return termwrite
|
||||||
|
end
|
||||||
|
|
||||||
|
function vtansi.vtsession(gpua,scra) -- creates a process to handle the GPU and screen address combination *gpua*/*scra*. Returns read, write and "close" functions.
|
||||||
|
local gpu = component.proxy(gpua)
|
||||||
|
gpu.bind(scra)
|
||||||
|
local write = vtansi.vtemu(gpu)
|
||||||
|
local kba = {}
|
||||||
|
for k,v in ipairs(component.invoke(scra,"getKeyboards")) do
|
||||||
|
kba[v]=true
|
||||||
|
end
|
||||||
|
local buf, lbuf, echo = "", true, true
|
||||||
|
os.spawn(function() dprint(pcall(function()
|
||||||
|
while true do
|
||||||
|
local ty,ka,ch = coroutine.yield()
|
||||||
|
if ty == "key_down" and kba[ka] then
|
||||||
|
if ch == 13 then ch = 10 end
|
||||||
|
if ch == 8 and lbuf then
|
||||||
|
if buf:len() > 0 then
|
||||||
|
if echo then write("\8 \8") end
|
||||||
|
buf = buf:sub(1,-2)
|
||||||
|
end
|
||||||
|
elseif ch > 0 then
|
||||||
|
if echo then write(string.char(ch)) end
|
||||||
|
buf=buf..string.char(ch)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)) end,string.format("ttyd[%s:%s]",gpua:sub(1,8),scra:sub(1,8)))
|
||||||
|
local function bread(n)
|
||||||
|
local r
|
||||||
|
if lbuf then
|
||||||
|
while not buf:find("\n") do
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
local n = buf:find("\n")
|
||||||
|
r, buf = buf:sub(1,n), buf:sub(n+1)
|
||||||
|
else
|
||||||
|
r = buf
|
||||||
|
buf = ""
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
local function bwrite(d)
|
||||||
|
local ba, lb, ec = write(d)
|
||||||
|
buf = buf .. ba
|
||||||
|
if lb ~= nil then
|
||||||
|
lbuf = lb
|
||||||
|
end
|
||||||
|
if ec ~= nil then
|
||||||
|
echo = ec
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return bread, bwrite, function() io.write("\27[2J\27[H") end
|
||||||
|
end
|
||||||
|
return vtansi
|
@ -7,7 +7,6 @@
|
|||||||
--#include "module/devfs.lua"
|
--#include "module/devfs.lua"
|
||||||
--#include "module/devfs/syslog.lua"
|
--#include "module/devfs/syslog.lua"
|
||||||
--#include "module/loadfile.lua"
|
--#include "module/loadfile.lua"
|
||||||
--#include "module/vt-task.lua"
|
|
||||||
|
|
||||||
os.spawn(function()
|
os.spawn(function()
|
||||||
os.setenv("PWD","/boot")
|
os.setenv("PWD","/boot")
|
||||||
|
@ -13,8 +13,8 @@ function os.spawnfile(p,n,...) -- spawns a new process from file *p* with name *
|
|||||||
end
|
end
|
||||||
_G.package = {}
|
_G.package = {}
|
||||||
package.loaded = {computer=computer,component=component,fs=fs,buffer=buffer}
|
package.loaded = {computer=computer,component=component,fs=fs,buffer=buffer}
|
||||||
function require(f) -- searches for a library with name *f* and returns what the library returns, if possible
|
function require(f,force) -- searches for a library with name *f* and returns what the library returns, if possible. if *force* is set, loads the library even if it is cached
|
||||||
if not package.loaded[f] then
|
if not package.loaded[f] or force then
|
||||||
local lib = os.getenv("LIB") or "/boot/lib"
|
local lib = os.getenv("LIB") or "/boot/lib"
|
||||||
for d in lib:gmatch("[^\n]+") do
|
for d in lib:gmatch("[^\n]+") do
|
||||||
if fs.exists(d.."/"..f) then
|
if fs.exists(d.."/"..f) then
|
||||||
@ -29,3 +29,6 @@ function require(f) -- searches for a library with name *f* and returns what the
|
|||||||
end
|
end
|
||||||
error("library not found: "..f)
|
error("library not found: "..f)
|
||||||
end
|
end
|
||||||
|
function reload(f)
|
||||||
|
return require(f,true)
|
||||||
|
end
|
||||||
|
@ -58,4 +58,11 @@ function os.getenv(k) -- gets a process' *k* environment variable
|
|||||||
return tTasks[cPid].e[k]
|
return tTasks[cPid].e[k]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
function os.setTimeout(n)
|
||||||
|
if type(n) == "number" and n >= 0 then
|
||||||
|
nTimeout = n
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
local gpus,screens,ttyn,pids = {}, {}, 0, {}
|
local gpus,screens,ttyn,pids = {}, {}, 0, {}
|
||||||
local basepid = nil
|
local basepid = nil
|
||||||
local shell = require "shell"
|
local shell = require "shell"
|
||||||
|
local vtansi = require "vtansi"
|
||||||
local function scan()
|
local function scan()
|
||||||
local w,di = pcall(computer.getDeviceInfo)
|
local w,di = pcall(computer.getDeviceInfo)
|
||||||
if w then
|
if w then
|
||||||
@ -44,7 +45,7 @@ local function allocate()
|
|||||||
dprint(k)
|
dprint(k)
|
||||||
local sA = nextScreen(v[2])
|
local sA = nextScreen(v[2])
|
||||||
if v[1] == false and sA then
|
if v[1] == false and sA then
|
||||||
local r,w = vtemu(k,sA)
|
local r,w = vtansi.vtsession(k,sA)
|
||||||
devfs.register("tty"..tostring(ttyn), function() return r,w,function() end end)
|
devfs.register("tty"..tostring(ttyn), function() return r,w,function() end end)
|
||||||
gpus[k][1] = true
|
gpus[k][1] = true
|
||||||
screens[sA][1] = true
|
screens[sA][1] = true
|
||||||
|
Loading…
Reference in New Issue
Block a user