More terminal improvements. Yes. Again.

This commit is contained in:
20kdc 2020-04-02 14:33:14 +01:00
parent ca4b6e5df2
commit c9157a1b7c
5 changed files with 112 additions and 164 deletions

View File

@ -93,7 +93,7 @@ return {
}, },
["app-kmt"] = { ["app-kmt"] = {
desc = "Line-terminal for MUDs & such", desc = "Line-terminal for MUDs & such",
v = 1, v = 2,
deps = { deps = {
"neo", "neo",
"zzz-license-pd" "zzz-license-pd"

View File

@ -10,11 +10,11 @@ local termClose
if not ok then if not ok then
termId = nil termId = nil
neo.executeAsync("svc-t", function (res) assert(neo.executeAsync("svc-t", function (res)
termId = res.access termId = res.access
termClose = res.close termClose = res.close
neo.scheduleTimer(0) neo.scheduleTimer(0)
end, "luashell") end, "luashell"))
while not termId do while not termId do
coroutine.yield() coroutine.yield()
end end
@ -32,7 +32,7 @@ event.listen("k.procdie", function (_, _, pid)
end end
end) end)
TERM.write(([[ TERM.write([[
KittenOS NEO Shell Usage Notes KittenOS NEO Shell Usage Notes
Prefixing = is an alias for 'return '. Prefixing = is an alias for 'return '.
@ -46,7 +46,7 @@ os.exit(): quit the shell
=listCmdApps(): -t- (terminal) apps =listCmdApps(): -t- (terminal) apps
event: useful for setting up listeners event: useful for setting up listeners
without breaking shell functionality without breaking shell functionality
]]):gsub("[\r]*\n", "\r\n")) ]])
function listCmdApps() function listCmdApps()
local apps = {} local apps = {}

View File

@ -30,7 +30,9 @@ local console = {}
-- This must not go below 3. -- This must not go below 3.
local conW = 40 local conW = 40
local conCX, conCY = 1, 1 local conCX, conCY = 1, 1
local conCV = false -- Performance
local consoleShown = {}
local conCYShown
for i = 1, 14 do for i = 1, 14 do
console[i] = (" "):rep(conW) console[i] = (" "):rep(conW)
end end
@ -70,6 +72,9 @@ local window = neo.requireAccess("x.neo.pub.window", "window")(conW, #console +
local function setSize(w, h) local function setSize(w, h)
conW = w conW = w
for i = 1, #console do
consoleShown[i] = nil
end
while #console < h do while #console < h do
table.insert(console, "") table.insert(console, "")
end end
@ -101,7 +106,7 @@ end
local function draw(i) local function draw(i)
if console[i] then if console[i] then
window.span(1, i, console[i], 0, 0xFFFFFF) window.span(1, i, console[i], 0, 0xFFFFFF)
if i == conCY and conCV then if i == conCY and not leText then
window.span(conCX, i, unicode.sub(console[i], conCX, conCX), 0xFFFFFF, 0) window.span(conCX, i, unicode.sub(console[i], conCX, conCX), 0xFFFFFF, 0)
end end
elseif leText then elseif leText then
@ -109,7 +114,13 @@ local function draw(i)
end end
end end
local function drawDisplay() local function drawDisplay()
for i = 1, #console do draw(i) end for i = 1, #console do
if consoleShown[i] ~= console[i] or i == conCY or i == conCYShown then
draw(i)
consoleShown[i] = console[i]
end
end
conCYShown = conCY
end end
-- Terminal Visual -- -- Terminal Visual --
@ -147,6 +158,8 @@ local function writeData(data)
end end
if char == "\r" then if char == "\r" then
conCX = 1 conCX = 1
elseif char == "\x00" then
-- caused by TELNET \r rules
elseif char == "\n" then elseif char == "\n" then
conCX = 1 conCX = 1
writeFF() writeFF()
@ -171,6 +184,7 @@ local function writeData(data)
end end
local function writeANSI(s) local function writeANSI(s)
--neo.emergency("svc-t.ansi: " .. s)
-- This supports just about enough to get by. -- This supports just about enough to get by.
if s == "c" then if s == "c" then
for i = 1, #console do for i = 1, #console do
@ -186,13 +200,18 @@ local function writeANSI(s)
if cmd == "H" or cmd == "f" then if cmd == "H" or cmd == "f" then
local p = s:find(";") local p = s:find(";")
if not p then if not p then
conCX, conCY = 1, 1 conCY = np
conCX = 1
else else
conCY = tonumber(s:sub(2, p - 1)) or 1 conCY = tonumber(s:sub(2, p - 1)) or 1
conCX = tonumber(s:sub(p + 1, -2)) or 1 conCX = tonumber(s:sub(p + 1, -2)) or 1
end end
elseif cmd == "K" then elseif cmd == "K" then
console[conCY] = unicode.sub(console[conCY], 1, conCX - 1) .. (" "):rep(1 + conW - conCX) console[conCY] = unicode.sub(console[conCY], 1, conCX - 1) .. (" "):rep(1 + conW - conCX)
elseif cmd == "J" then
for i = 1, #console do
console[i] = (" "):rep(conW)
end
elseif cmd == "A" then elseif cmd == "A" then
conCY = conCY - np conCY = conCY - np
elseif cmd == "B" then elseif cmd == "B" then
@ -372,10 +391,24 @@ local function key(a, c)
-- Line Editing not active. -- Line Editing not active.
-- For now support a bare minimum. -- For now support a bare minimum.
for _, v in pairs(sendSigs) do for _, v in pairs(sendSigs) do
if control then if a == "\x03" then
if a == 99 then v("telnet", "\xFF\xF4")
v("telnet", "\xFF\xF4") elseif c == 199 then
end v("data", "\x1b[H")
elseif c == 201 then
v("data", "\x1b[5~")
elseif c == 207 then
v("data", "\x1b[F")
elseif c == 209 then
v("data", "\x1b[6~")
elseif c == 203 then
v("data", "\x1b[D")
elseif c == 205 then
v("data", "\x1b[C")
elseif c == 200 then
v("data", "\x1b[A")
elseif c == 208 then
v("data", "\x1b[B")
elseif a == "\r" then elseif a == "\r" then
v("data", "\r\n") v("data", "\r\n")
elseif a then elseif a then

View File

@ -3,8 +3,8 @@ ocemu {
components { components {
{"gpu", "c1-gpu-tier3", 0, 160, 50, 3}, {"gpu", "c1-gpu-tier3", 0, 160, 50, 3},
{"gpu", "c1-gpu-tier1", 0, 50, 16, 1}, {"gpu", "c1-gpu-tier1", 0, 50, 16, 1},
-- {"screen_sdl2", "c1-screen-tier3", -1, 160, 50, 3}, {"screen_sdl2", "c1-screen-tier3", -1, 160, 50, 3},
{"screen_sdl2", "c1-screen-tier1", -1, 50, 16, 1}, -- {"screen_sdl2", "c1-screen-tier1", -1, 50, 16, 1},
{"modem", "c1-modem", 1, false}, {"modem", "c1-modem", 1, false},
{"eeprom", "c1-eeprom", 9, "lua/bios.lua"}, {"eeprom", "c1-eeprom", 9, "lua/bios.lua"},
{"filesystem", "c1-tmpfs", -1, "tmpfs", "tmpfs", false, 5}, {"filesystem", "c1-tmpfs", -1, "tmpfs", "tmpfs", false, 5},

View File

@ -1,181 +1,96 @@
-- This is released into the public domain. -- This is released into the public domain.
-- No warranty is provided, implied or otherwise. -- No warranty is provided, implied or otherwise.
-- app-kmt.lua : LC emergency plan -- app-kmt.lua : just a utility now
-- Authors: 20kdc -- Authors: 20kdc
local lcOverride = false
local l15 = "20kdc.duckdns.org:8888"
-- unicode.safeTextFormat'd lines
local console = {
"┎┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┒",
"┋ ┃ ┃╲ ╱┃ ▀▀┃▀▀ ┋",
"┋ ┃╳ ┃ ╲ ┃ ┃ ┋",
"┋ ┃ ╲ ┃ ╲╱ ┃ ┃ ┋",
"┋ ┋",
"┋ KittenOS NEO MUD Terminal ┋",
"┖┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┚",
":Type text, Enter key sends.",
":'>' is 'from you', '<' 'to you'.",
":':' is 'internal message'.",
":Control-Arrows resizes window.",
-- ":F5/F6 copies/pastes current line.",
":",
":",
":Enter target server:port",
-- 14
}
--++++++++++++++++++++++++++++++++++++++++
-- sW must not go below 3.
-- sH must not go below 2.
local sW, sH = 40, 15
local inet = neo.requireAccess("c.internet", "internet").list()() local inet = neo.requireAccess("c.internet", "internet").list()()
local windows = neo.requireAccess("x.neo.pub.window", "windows")
local window = windows(sW, sH)
local tcp = nil local _, _, termId = ...
local dummyTcp = {read = function() return "" end, write = function() end, close = function() end} local ok = pcall(function ()
local tcpBuf = "" assert(string.sub(termId, 1, 12) == "x.neo.pub.t/")
end)
local function fmtLine(s) local termClose
s = unicode.safeTextFormat(s)
local l = unicode.len(s)
return unicode.sub(s .. (" "):rep(sW - l), -sW)
end
local function line(i) if not ok then
if i ~= sH then termId = nil
assert(console[i], "console" .. i) assert(neo.executeAsync("svc-t", function (res)
window.span(1, i, fmtLine(console[i]), 0xFFFFFF, 0) termId = res.access
else termClose = res.close
window.span(1, i, fmtLine(l15), 0, 0xFFFFFF) neo.scheduleTimer(0)
end, "kmt"))
while true do
if coroutine.yield() == "k.timer" then break end
end end
end end
local term = neo.requireAccess(termId, "terminal")
local function incoming(s) term.write([[
local function shift(f)
for i = 1, #console - 1 do
console[i] = console[i + 1]
end
console[#console] = f
end KittenOS NEO MUD Terminal
-- Need to break this safely.
shift("") export TERM=ansi-generic <- IMPORTANT!!!
for i = 1, unicode.len(s) do Enter target server:port...
local ch = unicode.sub(s, i, i) ]])
if unicode.wlen(console[#console] .. ch) > sW then
shift(" ")
end
console[#console] = console[#console] .. ch
end
for i = 1, #console do
line(i)
end
end
local function submitLine() local targetBuffer = ""
incoming(">" .. l15)
if not tcp then
tcp = inet.connect(l15)
if not tcp then
incoming(":The connection could not be created.")
tcp = dummyTcp
else
if not tcp.finishConnect() then
incoming(":Warning: finishConnect = false")
end
neo.scheduleTimer(os.uptime() + 0.1)
end
else
-- PRJblackstar doesn't need \r but others might
tcp.write(l15 .. "\r\n")
end
l15 = ""
line(sH)
end
if lcOverride then neo.scheduleTimer(0)
submitLine()
end
local function clipEnt(tx)
tx = tx:gsub("\r", "")
local ci = tx:find("\n") or (#tx + 1)
tx = tx:sub(1, ci - 1)
l15 = tx
line(sH)
end
local control = false
while true do while true do
local e = {coroutine.yield()} local e = {coroutine.yield()}
if e[1] == "k.timer" then if e[1] == "k.timer" then
while true do while tcp do
local b, e = tcp.read(neo.readBufSize) local b, e = tcp.read(neo.readBufSize)
if not b then if not b then
if e then if e then
incoming(":Warning: " .. e) term.write("\nkmt: " .. tostring(e) .. "\n")
tcp.close() tcp.close()
tcp = dummyTcp tcp = nil
end end
break
elseif b == "" then elseif b == "" then
break break
else else
tcpBuf = tcpBuf .. b:gsub("\r", "") term.write(b)
while true do
local nlp = tcpBuf:find("\n")
if nlp then
incoming("<" .. tcpBuf:sub(1, nlp - 1))
tcpBuf = tcpBuf:sub(nlp + 1)
else
break
end
end
end end
end end
neo.scheduleTimer(os.uptime() + 0.1) neo.scheduleTimer(os.uptime() + 0.049)
elseif e[1] == "x.neo.pub.window" then elseif e[1] == "k.procdie" then
if e[3] == "close" then if e[3] == term.pid then
if tcp then break
tcp.close() end
end elseif e[1] == termId then
return if targetBuffer and e[2] == "data" then
elseif e[3] == "clipboard" then targetBuffer = targetBuffer .. e[3]:gsub("\r", "")
clipEnt(e[4]) local p = targetBuffer:find("\n")
elseif e[3] == "key" then if p then
if e[5] == 29 or e[5] == 157 then local ok, res, rer = pcall(inet.connect, targetBuffer:sub(1, p - 1))
control = e[6] targetBuffer = targetBuffer:sub(p + 1):gsub("\n", "\r\n")
elseif e[6] then if not ok then
if not control then -- Likes to return this kind
if e[4] == 8 or e[4] == 127 then term.write("kmt: " .. tostring(res) .. "\n")
l15 = unicode.sub(l15, 1, -2) elseif not res then
elseif e[4] == 13 then -- Could theoretically return this kind
submitLine() term.write("kmt: " .. tostring(rer) .. "\n")
elseif e[4] >= 32 then else
l15 = l15 .. unicode.char(e[4]) -- Hopefully this kind
end term.write("kmt: Connecting...\n")
line(sH) tcp = res
elseif e[5] == 203 and sW > 8 then tcp.write(targetBuffer)
sW = sW - 1 targetBuffer = nil
window.setSize(sW, sH)
elseif e[5] == 200 and sH > 2 then
sH = sH - 1
table.remove(console, 1)
window.setSize(sW, sH)
elseif e[5] == 205 then
sW = sW + 1
window.setSize(sW, sH)
elseif e[5] == 208 then
sH = sH + 1
table.insert(console, 1, "")
window.setSize(sW, sH)
end end
end end
elseif e[3] == "line" then elseif tcp and e[2] == "data" or e[2] == "telnet" then
line(e[4]) tcp.write(e[3])
end end
end end
end end
if tcp then
tcp.close()
end