1
0
mirror of https://github.com/kepler155c/opus synced 2025-05-05 17:04:13 +00:00

transition to kernel

This commit is contained in:
kepler155c@gmail.com 2018-01-13 23:40:53 -05:00
parent bd37b57780
commit 9de9452dd3
15 changed files with 157 additions and 180 deletions

View File

@ -1,23 +1,21 @@
local Util = require('util')
local colors = _G.colors local colors = _G.colors
local term = _G.term local term = _G.term
local _gsub = string.gsub local _gsub = string.gsub
local Terminal = { } local Terminal = { }
function Terminal.scrollable(win, size) function Terminal.scrollable(win, parent)
local w, h = win.getSize() local w, h = win.getSize()
local _, ph = parent.getSize()
local scrollPos = 0 local scrollPos = 0
local scp = win.setCursorPos local scp = win.setCursorPos
win.setCursorPos = function(x, y) win.setCursorPos = function(x, y)
_G._p = y
if y > scrollPos + ph then
win.scrollTo(y - ph)
end
scp(x, y) scp(x, y)
if y > scrollPos + h then
win.scrollTo(y - h)
elseif y < scrollPos then
win.scrollTo(y - 2)
end
end end
win.scrollUp = function() win.scrollUp = function()
@ -29,75 +27,15 @@ function Terminal.scrollable(win, size)
end end
win.scrollTo = function(p) win.scrollTo = function(p)
p = math.min(math.max(p, 0), size) p = math.min(math.max(p, 0), h - ph)
if p ~= scrollPos then if p ~= scrollPos then
scrollPos = p scrollPos = p
win.reposition(1, -scrollPos + 1, w, h + size) win.reposition(1, -scrollPos + 1, w, h)
end end
end end
win.reposition(1, 1, w, h + size, true)
end end
function Terminal.scrollable2(ct, size)
local w, h = ct.getSize()
local win = _G.window.create(ct, 1, 1, w, h + size, true)
local oldWin = Util.shallowCopy(win)
local scrollPos = 0
local function drawScrollbar(oldPos, newPos)
local x, y = oldWin.getCursorPos()
local pos = math.floor(oldPos / size * (h - 1))
oldWin.setCursorPos(w, oldPos + pos + 1)
oldWin.write(' ')
pos = math.floor(newPos / size * (h - 1))
oldWin.setCursorPos(w, newPos + pos + 1)
oldWin.write('#')
oldWin.setCursorPos(x, y)
end
win.setCursorPos = function(x, y)
oldWin.setCursorPos(x, y)
if y > scrollPos + h then
win.scrollTo(y - h)
elseif y < scrollPos then
win.scrollTo(y - 2)
end
end
win.scrollUp = function()
win.scrollTo(scrollPos - 1)
end
win.scrollDown = function()
win.scrollTo(scrollPos + 1)
end
win.scrollTo = function(p)
p = math.min(math.max(p, 0), size)
if p ~= scrollPos then
drawScrollbar(scrollPos, p)
scrollPos = p
--local w, h = win.getSize()
win.reposition(1, -scrollPos + 1, w, h + size)
end
end
win.clear = function()
oldWin.clear()
scrollPos = 0
end
drawScrollbar(0, 0)
return win
end
function Terminal.toGrayscale(ct) function Terminal.toGrayscale(ct)
local scolors = { local scolors = {
[ colors.white ] = colors.white, [ colors.white ] = colors.white,
[ colors.orange ] = colors.lightGray, [ colors.orange ] = colors.lightGray,
@ -183,7 +121,7 @@ function Terminal.mirror(ct, dt)
if dt[k] then if dt[k] then
dt[k](...) dt[k](...)
end end
return unpack(ret) return table.unpack(ret)
end end
end end
end end

View File

@ -25,7 +25,7 @@ local page = UI.Page {
{ heading = 'Time', key = 'timestamp' }, { heading = 'Time', key = 'timestamp' },
}, },
values = multishell.getTabs(), values = multishell.getTabs(),
sortColumn = 'title', sortColumn = 'uid',
autospace = true, autospace = true,
}, },
accelerators = { accelerators = {

View File

@ -14,7 +14,7 @@ local shell = _ENV.shell
local term = _G.term local term = _G.term
local window = _G.window local window = _G.window
local parentTerm = term.current() local parentTerm = kernel.terminal.parent -- term.current()
local w,h = parentTerm.getSize() local w,h = parentTerm.getSize()
local overviewId local overviewId
local tabsDirty = false local tabsDirty = false
@ -128,6 +128,7 @@ function multishell.openTab(tab)
end end
printError('Press enter to close') printError('Press enter to close')
tab.isDead = true tab.isDead = true
tab.hidden = false
while true do while true do
local e, code = os.pullEventRaw('key') local e, code = os.pullEventRaw('key')
if e == 'terminate' or e == 'key' and code == keys.enter then if e == 'terminate' or e == 'key' and code == keys.enter then
@ -137,7 +138,7 @@ function multishell.openTab(tab)
end end
end) end)
kernel.run(routine) kernel.launch(routine)
if tab.focused then if tab.focused then
multishell.setFocus(tab.uid) multishell.setFocus(tab.uid)

View File

@ -26,7 +26,6 @@ if options.title then
multishell.setTitle(multishell.getCurrent(), options.title) multishell.setTitle(multishell.getCurrent(), options.title)
end end
print('connecting...')
local socket, msg = Socket.connect(remoteId, 23) local socket, msg = Socket.connect(remoteId, 23)
if not socket then if not socket then
@ -44,6 +43,7 @@ socket:write({
height = h, height = h,
isColor = ct.isColor(), isColor = ct.isColor(),
program = args, program = args,
pos = { ct.getCursorPos() },
}) })
Event.addRoutine(function() Event.addRoutine(function()
@ -58,8 +58,8 @@ Event.addRoutine(function()
end end
end) end)
ct.clear() --ct.clear()
ct.setCursorPos(1, 1) --ct.setCursorPos(1, 1)
local filter = Util.transpose { local filter = Util.transpose {
'char', 'paste', 'key', 'key_up', 'terminate', 'char', 'paste', 'key', 'key_up', 'terminate',
@ -77,10 +77,10 @@ while true do
end end
if not socket.connected then if not socket.connected then
print() -- print()
print('Connection lost') -- print('Connection lost')
print('Press enter to exit') -- print('Press enter to exit')
pcall(read) -- pcall(read)
break break
end end
end end

View File

@ -23,6 +23,7 @@ local terminal = term.current()
local w, h = term.getSize() local w, h = term.getSize()
local kernelWindow = window.create(terminal, 1, 1, w, h, false) local kernelWindow = window.create(terminal, 1, 1, w, h, false)
term.redirect(kernelWindow) term.redirect(kernelWindow)
kernelWindow.parent = terminal
local splashWindow local splashWindow
local function showStatus(status, ...) local function showStatus(status, ...)
@ -152,11 +153,19 @@ local function createShellEnvironment(Util)
sandboxEnv.LUA_PATH = config.lua_path sandboxEnv.LUA_PATH = config.lua_path
end end
local function loadExtensions(Util) local function loadExtensions()
local dir = 'sys/extensions' local dir = 'sys/extensions'
for _,file in ipairs(fs.list(dir)) do local files = fs.list(dir)
table.sort(files)
for _,file in ipairs(files) do
showStatus('Loading ' .. file) showStatus('Loading ' .. file)
local s, m = Util.run(makeEnv(), 'sys/apps/shell', fs.combine(dir, file)) local s, m = kernel.run({
title = file:match('%d.(%S+).lua'),
hidden = true,
path = 'sys/apps/shell',
args = { fs.combine(dir, file) },
terminal = kernelWindow,
})
if not s then if not s then
error(m) error(m)
end end
@ -191,7 +200,7 @@ local s, m = pcall(function()
showStatus('Reticulating splines') showStatus('Reticulating splines')
Util.run(makeEnv(), 'sys/kernel.lua') Util.run(makeEnv(), 'sys/kernel.lua')
loadExtensions(Util) loadExtensions()
showStatus('Mounting file systems') showStatus('Mounting file systems')
fs.loadTab('usr/etc/fstab') fs.loadTab('usr/etc/fstab')
@ -199,15 +208,15 @@ local s, m = pcall(function()
splashWindow.setVisible(false) splashWindow.setVisible(false)
if args[1] then if args[1] then
kernelWindow.setVisible(true) kernelWindow.setVisible(true)
kernelWindow.setVisible(false)
end end
--term.clear()
--term.redirect(terminal)
_G.kernel.run(_G.kernel.newRoutine({ term.redirect(terminal)
_G.kernel.run({
path = 'sys/apps/shell', path = 'sys/apps/shell',
args = args[1] and args or { 'sys/apps/multishell' }, args = args[1] and args or { 'sys/apps/multishell' },
terminal = terminal, })
}))
end) end)
if not s then if not s then
@ -217,7 +226,7 @@ if not s then
_G.printError(m .. '\n') _G.printError(m .. '\n')
else else
if _G.kernel.routines[1] then if _G.kernel.routines[1] then
_G.kernel.start(terminal, kernelWindow) _G.kernel.start()
end end
end end

View File

@ -4,7 +4,7 @@ local Peripheral = require('peripheral')
_G.device = Peripheral.getList() _G.device = Peripheral.getList()
_G.device.terminal = _G.term.current() _G.device.terminal = _G.kernel.terminal.parent
_G.device.terminal.side = 'terminal' _G.device.terminal.side = 'terminal'
_G.device.terminal.type = 'terminal' _G.device.terminal.type = 'terminal'
_G.device.terminal.name = 'terminal' _G.device.terminal.name = 'terminal'

View File

@ -3,9 +3,10 @@ _G.requireInjector()
local Event = require('event') local Event = require('event')
local Util = require('util') local Util = require('util')
_G.network = { }
local device = _G.device local device = _G.device
local fs = _G.fs local fs = _G.fs
local multishell = _ENV.multishell
local network = _G.network local network = _G.network
local os = _G.os local os = _G.os
local printError = _G.printError local printError = _G.printError
@ -14,10 +15,6 @@ if not device.wireless_modem then
return return
end end
if multishell and multishell.setTitle then
multishell.setTitle(multishell.getCurrent(), 'Net Daemon')
end
print('Net daemon started') print('Net daemon started')
for _,file in pairs(fs.list('sys/network')) do for _,file in pairs(fs.list('sys/network')) do
@ -42,6 +39,4 @@ end
os.queueEvent('network_down') os.queueEvent('network_down')
Event.pullEvent('network_down') Event.pullEvent('network_down')
Util.clear(_G.network) Util.clear(network)
print('Net daemon stopped')

View File

@ -0,0 +1,11 @@
local kernel = _G.kernel
kernel.hook('device_attach', function(_, eventData)
if eventData[1] == 'wireless_modem' then
kernel.run({
title = 'Net daemon',
path = 'sys/extensions/netdaemon.lua',
hidden = true,
})
end
end)

View File

@ -1,13 +0,0 @@
local kernel = _G.kernel
_G.network = { }
kernel.hook('device_attach', function(_, eventData)
if eventData[1] == 'wireless_modem' then
local routine = kernel.newRoutine({
path = 'sys/services/network.lua',
hidden = true
})
kernel.run(routine)
end
end)

View File

@ -12,6 +12,7 @@ _G.kernel = {
hooks = { }, hooks = { },
routines = { }, routines = { },
terminal = _G.term.current(), terminal = _G.term.current(),
window = _G.term.current(),
} }
local kernel = _G.kernel local kernel = _G.kernel
@ -25,7 +26,7 @@ local focusedRoutineEvents = Util.transpose {
} }
_G.debug = function(pattern, ...) _G.debug = function(pattern, ...)
local oldTerm = term.redirect(kernel.terminal) local oldTerm = term.redirect(kernel.window)
Util.print(pattern, ...) Util.print(pattern, ...)
term.redirect(oldTerm) term.redirect(oldTerm)
end end
@ -65,7 +66,7 @@ function Routine:resume(event, ...)
end end
if not self.filter or self.filter == event or event == "terminate" then if not self.filter or self.filter == event or event == "terminate" then
term.redirect(self.terminal) local previousTerm = term.redirect(self.terminal)
local previous = kernel.running local previous = kernel.running
kernel.running = self -- stupid shell set title kernel.running = self -- stupid shell set title
@ -73,6 +74,8 @@ function Routine:resume(event, ...)
kernel.running = previous kernel.running = previous
self.terminal = term.current() self.terminal = term.current()
term.redirect(previousTerm)
if ok then if ok then
self.filter = result self.filter = result
else else
@ -103,16 +106,15 @@ function kernel.newRoutine(args)
local routine = setmetatable(args, { __index = Routine }) local routine = setmetatable(args, { __index = Routine })
routine.uid = kernel.UID routine.uid = kernel.UID
routine.timestamp = os.clock()
routine.env = args.env or Util.shallowCopy(sandboxEnv)
routine.terminal = args.terminal or kernel.terminal
routine.window = args.window or kernel.window
return routine return routine
end end
function kernel.run(routine) function kernel.launch(routine)
routine.timestamp = os.clock()
routine.terminal = routine.terminal or kernel.terminal
routine.window = routine.window or kernel.window
routine.env = Util.shallowCopy(routine.env or sandboxEnv)
routine.co = routine.co or coroutine.create(function() routine.co = routine.co or coroutine.create(function()
local result, err local result, err
@ -131,11 +133,15 @@ function kernel.run(routine)
table.insert(kernel.routines, routine) table.insert(kernel.routines, routine)
local previousTerm = term.current()
local s, m = routine:resume() local s, m = routine:resume()
term.redirect(previousTerm)
return s, m return not s and s or routine.uid, m
end
function kernel.run(args)
local routine = kernel.newRoutine(args)
kernel.launch(routine)
return routine
end end
function kernel.raise(uid) function kernel.raise(uid)
@ -207,10 +213,7 @@ function kernel.event(event, eventData)
end end
end end
function kernel.start(terminal, kernelWindow) function kernel.start()
kernel.window = kernelWindow
kernel.terminal = kernel.window
local s, m = pcall(function() local s, m = pcall(function()
repeat repeat
local eventData = { os.pullEventRaw() } local eventData = { os.pullEventRaw() }
@ -221,9 +224,8 @@ function kernel.start(terminal, kernelWindow)
kernel.window.setVisible(true) kernel.window.setVisible(true)
if not s then if not s then
term.redirect(kernel.window)
print('\nCrash detected\n') print('\nCrash detected\n')
_G.printError(m) _G.printError(m)
end end
term.redirect(terminal) term.redirect(kernel.terminal)
end end

View File

@ -2,15 +2,11 @@ local Event = require('event')
local Socket = require('socket') local Socket = require('socket')
local Util = require('util') local Util = require('util')
local multishell = _ENV.multishell local kernel = _G.kernel
local os = _G.os
local term = _G.term local term = _G.term
local window = _G.window
local function telnetHost(socket) local function telnetHost(socket)
_G.requireInjector()
local Event = require('event')
local methods = { 'clear', 'clearLine', 'setCursorPos', 'write', 'blit', local methods = { 'clear', 'clearLine', 'setCursorPos', 'write', 'blit',
'setTextColor', 'setTextColour', 'setBackgroundColor', 'setTextColor', 'setTextColour', 'setBackgroundColor',
'setBackgroundColour', 'scroll', 'setCursorBlink', } 'setBackgroundColour', 'scroll', 'setCursorBlink', }
@ -21,11 +17,12 @@ local function telnetHost(socket)
return return
end end
socket.term = term.current() local win = window.create(_G.device.terminal, 1, 1, termInfo.width, termInfo.height, false)
local oldWindow = Util.shallowCopy(socket.term) win.setCursorPos(table.unpack(termInfo.pos))
for _,k in pairs(methods) do for _,k in pairs(methods) do
socket.term[k] = function(...) local fn = win[k]
win[k] = function(...)
if not socket.queue then if not socket.queue then
socket.queue = { } socket.queue = { }
@ -39,34 +36,36 @@ local function telnetHost(socket)
f = k, f = k,
args = { ... }, args = { ... },
}) })
oldWindow[k](...) fn(...)
end end
end end
socket.term.getSize = function() local shellThread = kernel.run({
return termInfo.width, termInfo.height terminal = win,
window = win,
title = 'Telnet client',
hidden = true,
co = coroutine.create(function()
Util.run(_ENV, 'sys/apps/shell', table.unpack(termInfo.program))
if socket.queue then
socket:write(socket.queue)
end end
socket:close()
local shellThread = Event.addRoutine(function()
os.run(_ENV, 'sys/apps/shell', table.unpack(termInfo.program))
Event.exitPullEvents()
end) end)
})
Event.addRoutine(function() Event.addRoutine(function()
while true do while true do
local data = socket:read() local data = socket:read()
if not data then if not data then
Event.exitPullEvents() shellThread:resume('terminate')
break break
end end
local previousTerm = term.current()
shellThread:resume(table.unpack(data)) shellThread:resume(table.unpack(data))
term.redirect(previousTerm)
end end
end) end)
Event.pullEvents()
socket:close()
shellThread:terminate()
end end
Event.addRoutine(function() Event.addRoutine(function()
@ -76,11 +75,8 @@ Event.addRoutine(function()
print('telnet: connection from ' .. socket.dhost) print('telnet: connection from ' .. socket.dhost)
multishell.openTab({ Event.addRoutine(function()
fn = telnetHost, telnetHost(socket)
args = { socket }, end)
title = 'Telnet Client',
hidden = true,
})
end end
end) end)

View File

@ -3,7 +3,7 @@ local Socket = require('socket')
local Util = require('util') local Util = require('util')
local os = _G.os local os = _G.os
local terminal = _ENV.multishell.term local terminal = _G.device.terminal
local function vncHost(socket) local function vncHost(socket)
local methods = { 'blit', 'clear', 'clearLine', 'setCursorPos', 'write', local methods = { 'blit', 'clear', 'clearLine', 'setCursorPos', 'write',

View File

@ -11,22 +11,60 @@ local keyboard = _G.device.keyboard
local multishell = _ENV.multishell local multishell = _ENV.multishell
local os = _G.os local os = _G.os
local term = _G.term local term = _G.term
local window = _G.window
if multishell and multishell.setTitle then if multishell and multishell.setTitle then
multishell.setTitle(multishell.getCurrent(), 'System Log') multishell.setTitle(multishell.getCurrent(), 'System Log')
end end
-- jump through a lot of hoops to get around window api limitations
-- mainly failing to provide access to window buffer or knowledge of parent
-- need: window.getParent()
-- window.copy(target)
local terminal = _G.kernel.terminal.parent
local w, h = kernel.window.getSize()
local win = window.create(kernel.window, 1, 1, w, h + 50, false)
-- copy windows contents from parent window to child
local oblit, oscp = terminal.blit, terminal.setCursorPos
kernel.window.setVisible(false)
terminal.blit = function(...)
win.blit(...)
end
terminal.setCursorPos = function(...)
win.setCursorPos(...)
end
kernel.window.setVisible(true)
-- position and resize window for multishell (but don't update screen)
terminal.blit = function() end
terminal.setCursorPos = function() end
kernel.window.reposition(1, 2, w, h - 1)
-- restore original terminal
terminal.blit = oblit
terminal.setCursorPos = oscp
-- add scrolling methods
Terminal.scrollable(win, kernel.window)
-- update kernel with new window, set this tab with the new kernal window
local routine = kernel.getCurrent() local routine = kernel.getCurrent()
local previousId for _,r in pairs(kernel.routines) do
if r.terminal == kernel.terminal then
kernel.window.reposition(1, 2) r.terminal = win
Terminal.scrollable(kernel.window, 50) r.window = win
end
routine.terminal = kernel.window end
routine.window = kernel.window kernel.terminal = win
kernel.window = win
routine.terminal = win
routine.window = win
term.redirect(routine.window) term.redirect(routine.window)
local previousId
kernel.hook('mouse_scroll', function(_, eventData) kernel.hook('mouse_scroll', function(_, eventData)
local dir, y = eventData[1], eventData[3] local dir, y = eventData[1], eventData[3]