mirror of https://github.com/kepler155c/opus
kernel improvements
This commit is contained in:
parent
71bbd2d457
commit
b0db0b86bd
|
@ -42,17 +42,16 @@ local function telnetHost(socket, mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
local shellThread = kernel.run({
|
local shellThread = kernel.run({
|
||||||
terminal = win,
|
|
||||||
window = win,
|
window = win,
|
||||||
title = mode .. ' client',
|
title = mode .. ' client',
|
||||||
hidden = true,
|
hidden = true,
|
||||||
co = coroutine.create(function()
|
fn = function()
|
||||||
Util.run(_ENV, Alt.get('shell'), table.unpack(termInfo.program))
|
Util.run(kernel.makeEnv(), Alt.get('shell'), table.unpack(termInfo.program))
|
||||||
if socket.queue then
|
if socket.queue then
|
||||||
socket:write(socket.queue)
|
socket:write(socket.queue)
|
||||||
end
|
end
|
||||||
socket:close()
|
socket:close()
|
||||||
end)
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
Event.addRoutine(function()
|
Event.addRoutine(function()
|
||||||
|
|
|
@ -26,7 +26,7 @@ local function systemLog()
|
||||||
if y > 1 then
|
if y > 1 then
|
||||||
local currentTab = kernel.getFocused()
|
local currentTab = kernel.getFocused()
|
||||||
if currentTab == routine then
|
if currentTab == routine then
|
||||||
if currentTab.terminal.scrollUp and not currentTab.terminal.noAutoScroll then
|
if currentTab.terminal.scrollUp then
|
||||||
if dir == -1 then
|
if dir == -1 then
|
||||||
currentTab.terminal.scrollUp()
|
currentTab.terminal.scrollUp()
|
||||||
else
|
else
|
||||||
|
|
|
@ -104,12 +104,12 @@ function nativefs.delete(node, dir)
|
||||||
-- if a file is mounted over an existing directory
|
-- if a file is mounted over an existing directory
|
||||||
-- ie. sys/apps/MOUNT.LUA
|
-- ie. sys/apps/MOUNT.LUA
|
||||||
-- then sys and sys/apps are created as temp nodes
|
-- then sys and sys/apps are created as temp nodes
|
||||||
-- therefore, trying to delete sys will was only
|
-- therefore, trying to delete sys was only
|
||||||
-- removing the node and not deleting the directory
|
-- removing the node and not deleting the directory
|
||||||
-- Need a better way to backfill nodes in a way
|
-- Need a better way to backfill nodes in a way
|
||||||
-- that preserves the vfs functionality
|
-- that preserves the vfs functionality
|
||||||
|
|
||||||
-- perhaps a flag that denotes that this is a
|
-- perhaps a flag that denotes that this
|
||||||
-- file/directory is the actual mount
|
-- file/directory is the actual mount
|
||||||
|
|
||||||
-- this hack will not fix
|
-- this hack will not fix
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
local Blit = require('opus.ui.blit')
|
local Blit = require('opus.ui.blit')
|
||||||
local Config = require('opus.config')
|
local Config = require('opus.config')
|
||||||
local trace = require('opus.trace')
|
|
||||||
local Util = require('opus.util')
|
local Util = require('opus.util')
|
||||||
|
|
||||||
local colors = _G.colors
|
local colors = _G.colors
|
||||||
|
@ -103,48 +102,25 @@ function multishell.launch( tProgramEnv, sProgramPath, ... )
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
local function xprun(env, path, ...)
|
|
||||||
setmetatable(env, { __index = _G })
|
|
||||||
local fn, m = loadfile(path, env)
|
|
||||||
if fn then
|
|
||||||
return trace(fn, ...)
|
|
||||||
end
|
|
||||||
return fn, m
|
|
||||||
end
|
|
||||||
|
|
||||||
function multishell.openTab(tab)
|
function multishell.openTab(tab)
|
||||||
if not tab.title and tab.path then
|
if not tab.title and tab.path then
|
||||||
tab.title = fs.getName(tab.path):match('([^%.]+)')
|
tab.title = fs.getName(tab.path):match('([^%.]+)')
|
||||||
end
|
end
|
||||||
tab.title = tab.title or 'untitled'
|
tab.title = tab.title or 'untitled'
|
||||||
tab.window = tab.window or window.create(parentTerm, 1, 2, w, h - 1, false)
|
tab.window = tab.window or window.create(parentTerm, 1, 2, w, h - 1, false)
|
||||||
tab.terminal = tab.terminal or tab.window
|
tab.onExit = function(self, result, err)
|
||||||
|
|
||||||
local routine = kernel.newRoutine(tab)
|
|
||||||
|
|
||||||
routine.co = coroutine.create(function()
|
|
||||||
local result, err
|
|
||||||
|
|
||||||
if tab.fn then
|
|
||||||
result, err = Util.runFunction(routine.env, tab.fn, table.unpack(tab.args or { } ))
|
|
||||||
elseif tab.path then
|
|
||||||
result, err = xprun(routine.env, tab.path, table.unpack(tab.args or { } ))
|
|
||||||
else
|
|
||||||
err = 'multishell: invalid tab'
|
|
||||||
end
|
|
||||||
|
|
||||||
if not result and err and err ~= 'Terminated' or (err and err ~= 0) then
|
if not result and err and err ~= 'Terminated' or (err and err ~= 0) then
|
||||||
tab.terminal.setBackgroundColor(colors.black)
|
self.terminal.setBackgroundColor(colors.black)
|
||||||
if tonumber(err) then
|
if tonumber(err) then
|
||||||
tab.terminal.setTextColor(colors.orange)
|
self.terminal.setTextColor(colors.orange)
|
||||||
print('Process exited with error code: ' .. err)
|
print('Process exited with error code: ' .. err)
|
||||||
elseif err then
|
elseif err then
|
||||||
printError(tostring(err))
|
printError(tostring(err))
|
||||||
end
|
end
|
||||||
tab.terminal.setTextColor(colors.white)
|
self.terminal.setTextColor(colors.white)
|
||||||
print('\nPress enter to close')
|
print('\nPress enter to close')
|
||||||
routine.isDead = true
|
self.isDead = true
|
||||||
routine.hidden = false
|
self.hidden = false
|
||||||
redrawMenu()
|
redrawMenu()
|
||||||
while true do
|
while true do
|
||||||
local e, code = os.pullEventRaw('key')
|
local e, code = os.pullEventRaw('key')
|
||||||
|
@ -153,9 +129,9 @@ function multishell.openTab(tab)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
|
|
||||||
kernel.launch(routine)
|
local routine = kernel.run(tab)
|
||||||
|
|
||||||
if tab.focused then
|
if tab.focused then
|
||||||
multishell.setFocus(routine.uid)
|
multishell.setFocus(routine.uid)
|
||||||
|
@ -256,9 +232,10 @@ kernel.hook('multishell_redraw', function()
|
||||||
|
|
||||||
if currentTab then
|
if currentTab then
|
||||||
if currentTab.sx then
|
if currentTab.sx then
|
||||||
|
local textColor = currentTab.isDead and _colors.errorColor or _colors.focusTextColor
|
||||||
blit:write(currentTab.sx - 1,
|
blit:write(currentTab.sx - 1,
|
||||||
' ' .. currentTab.title:sub(1, currentTab.width - 1) .. ' ',
|
' ' .. currentTab.title:sub(1, currentTab.width - 1) .. ' ',
|
||||||
_colors.focusBackgroundColor, _colors.focusTextColor)
|
_colors.focusBackgroundColor, textColor)
|
||||||
end
|
end
|
||||||
if not currentTab.noTerminate then
|
if not currentTab.noTerminate then
|
||||||
blit:write(w, closeInd, nil, _colors.focusTextColor)
|
blit:write(w, closeInd, nil, _colors.focusTextColor)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
local Array = require('opus.array')
|
local Array = require('opus.array')
|
||||||
local Terminal = require('opus.terminal')
|
local Terminal = require('opus.terminal')
|
||||||
|
local trace = require('opus.trace')
|
||||||
local Util = require('opus.util')
|
local Util = require('opus.util')
|
||||||
|
|
||||||
_G.kernel = {
|
_G.kernel = {
|
||||||
|
@ -67,8 +68,6 @@ function kernel.unhook(event, fn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local Routine = { }
|
|
||||||
|
|
||||||
local function switch(routine, previous)
|
local function switch(routine, previous)
|
||||||
if routine then
|
if routine then
|
||||||
if previous and previous.window then
|
if previous and previous.window then
|
||||||
|
@ -86,6 +85,8 @@ local function switch(routine, previous)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local Routine = { }
|
||||||
|
|
||||||
function Routine:resume(event, ...)
|
function Routine:resume(event, ...)
|
||||||
if not self.co or coroutine.status(self.co) == 'dead' then
|
if not self.co or coroutine.status(self.co) == 'dead' then
|
||||||
return
|
return
|
||||||
|
@ -95,38 +96,33 @@ function Routine:resume(event, ...)
|
||||||
local previousTerm = 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
|
||||||
local ok, result = coroutine.resume(self.co, event, ...)
|
local ok, result = coroutine.resume(self.co, event, ...)
|
||||||
kernel.running = previous
|
kernel.running = previous
|
||||||
|
|
||||||
if ok then
|
self.filter = result
|
||||||
self.filter = result
|
|
||||||
else
|
|
||||||
_G.printError(result)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.terminal = term.current()
|
self.terminal = term.current()
|
||||||
term.redirect(previousTerm)
|
term.redirect(previousTerm)
|
||||||
|
|
||||||
if not ok and self.haltOnError then
|
|
||||||
error(result, -1)
|
|
||||||
end
|
|
||||||
if coroutine.status(self.co) == 'dead' then
|
|
||||||
Array.removeByValue(kernel.routines, self)
|
|
||||||
if self.onDestroy then
|
|
||||||
pcall(self.onDestroy, self)
|
|
||||||
end
|
|
||||||
if #kernel.routines > 0 then
|
|
||||||
switch(kernel.routines[1])
|
|
||||||
end
|
|
||||||
if self.haltOnExit then
|
|
||||||
kernel.halt()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ok, result
|
return ok, result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- override if any post processing is required
|
||||||
|
-- routine:cleanup must be called explicitly if overridden
|
||||||
|
function Routine:onExit(status, message) -- self, status, message
|
||||||
|
if not status and message ~= 'Terminated' then
|
||||||
|
_G.printError(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Routine:cleanup()
|
||||||
|
Array.removeByValue(kernel.routines, self)
|
||||||
|
if #kernel.routines > 0 then
|
||||||
|
switch(kernel.routines[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function kernel.getFocused()
|
function kernel.getFocused()
|
||||||
return kernel.routines[1]
|
return kernel.routines[1]
|
||||||
end
|
end
|
||||||
|
@ -147,17 +143,26 @@ function kernel.newRoutine(args)
|
||||||
local routine = setmetatable({
|
local routine = setmetatable({
|
||||||
uid = kernel.UID,
|
uid = kernel.UID,
|
||||||
timestamp = os.clock(),
|
timestamp = os.clock(),
|
||||||
terminal = kernel.window,
|
|
||||||
window = kernel.window,
|
window = kernel.window,
|
||||||
title = 'untitled',
|
title = 'untitled',
|
||||||
}, { __index = Routine })
|
}, { __index = Routine })
|
||||||
|
|
||||||
Util.merge(routine, args)
|
Util.merge(routine, args)
|
||||||
routine.env = args.env or shell.makeEnv()
|
routine.env = args.env or shell.makeEnv()
|
||||||
|
routine.terminal = routine.terminal or routine.window
|
||||||
|
|
||||||
return routine
|
return routine
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function xprun(env, path, ...)
|
||||||
|
setmetatable(env, { __index = _G })
|
||||||
|
local fn, m = loadfile(path, env)
|
||||||
|
if fn then
|
||||||
|
return trace(fn, ...)
|
||||||
|
end
|
||||||
|
return fn, m
|
||||||
|
end
|
||||||
|
|
||||||
function kernel.launch(routine)
|
function kernel.launch(routine)
|
||||||
routine.co = routine.co or coroutine.create(function()
|
routine.co = routine.co or coroutine.create(function()
|
||||||
local result, err
|
local result, err
|
||||||
|
@ -165,14 +170,13 @@ function kernel.launch(routine)
|
||||||
if routine.fn then
|
if routine.fn then
|
||||||
result, err = Util.runFunction(routine.env, routine.fn, table.unpack(routine.args or { } ))
|
result, err = Util.runFunction(routine.env, routine.fn, table.unpack(routine.args or { } ))
|
||||||
elseif routine.path then
|
elseif routine.path then
|
||||||
result, err = Util.run(routine.env, routine.path, table.unpack(routine.args or { } ))
|
result, err = xprun(routine.env, routine.path, table.unpack(routine.args or { } ))
|
||||||
else
|
else
|
||||||
err = 'kernel: invalid routine'
|
err = 'kernel: invalid routine'
|
||||||
end
|
end
|
||||||
|
|
||||||
if not result and err ~= 'Terminated' then
|
pcall(routine.onExit, routine, result, err)
|
||||||
error(err or 'Error occurred', 2)
|
routine:cleanup()
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
table.insert(kernel.routines, routine)
|
table.insert(kernel.routines, routine)
|
||||||
|
@ -203,8 +207,6 @@ function kernel.raise(uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
switch(routine, previous)
|
switch(routine, previous)
|
||||||
-- local previous = eventData[2]
|
|
||||||
-- local routine = kernel.find(previous)
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
|
@ -232,8 +234,8 @@ function kernel.find(uid)
|
||||||
return Util.find(kernel.routines, 'uid', uid)
|
return Util.find(kernel.routines, 'uid', uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.halt()
|
function kernel.halt(status, message)
|
||||||
os.queueEvent('kernel_halt')
|
os.queueEvent('kernel_halt', status, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.event(event, eventData)
|
function kernel.event(event, eventData)
|
||||||
|
@ -275,15 +277,20 @@ function kernel.event(event, eventData)
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.start()
|
function kernel.start()
|
||||||
local s, m = pcall(function()
|
local s, m
|
||||||
|
pcall(function()
|
||||||
repeat
|
repeat
|
||||||
local eventData = { os.pullEventRaw() }
|
local eventData = { os.pullEventRaw() }
|
||||||
local event = table.remove(eventData, 1)
|
local event = table.remove(eventData, 1)
|
||||||
kernel.event(event, eventData)
|
kernel.event(event, eventData)
|
||||||
|
if event == 'kernel_halt' then
|
||||||
|
s = eventData[1]
|
||||||
|
m = eventData[2]
|
||||||
|
end
|
||||||
until event == 'kernel_halt'
|
until event == 'kernel_halt'
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if not s then
|
if not s and m then
|
||||||
kernel.window.setVisible(true)
|
kernel.window.setVisible(true)
|
||||||
term.redirect(kernel.window)
|
term.redirect(kernel.window)
|
||||||
print('\nCrash detected\n')
|
print('\nCrash detected\n')
|
||||||
|
@ -320,15 +327,15 @@ local function init(...)
|
||||||
term.redirect(kernel.window)
|
term.redirect(kernel.window)
|
||||||
shell.run('sys/apps/autorun.lua')
|
shell.run('sys/apps/autorun.lua')
|
||||||
|
|
||||||
local shellWindow = window.create(kernel.terminal, 1, 1, w, h, false)
|
local win = window.create(kernel.terminal, 1, 1, w, h, true)
|
||||||
local s, m = kernel.run({
|
local s, m = kernel.run({
|
||||||
title = args[1],
|
title = args[1],
|
||||||
path = 'sys/apps/shell.lua',
|
path = 'sys/apps/shell.lua',
|
||||||
args = args,
|
args = args,
|
||||||
haltOnExit = true,
|
window = win,
|
||||||
haltOnError = true,
|
onExit = function(_, s, m)
|
||||||
terminal = shellWindow,
|
kernel.halt(s, m)
|
||||||
window = shellWindow,
|
end,
|
||||||
})
|
})
|
||||||
if s then
|
if s then
|
||||||
kernel.raise(s.uid)
|
kernel.raise(s.uid)
|
||||||
|
@ -342,8 +349,12 @@ end
|
||||||
kernel.run({
|
kernel.run({
|
||||||
fn = init,
|
fn = init,
|
||||||
title = 'init',
|
title = 'init',
|
||||||
haltOnError = true,
|
|
||||||
args = { ... },
|
args = { ... },
|
||||||
|
onExit = function(_, status, message)
|
||||||
|
if not status then
|
||||||
|
kernel.halt(status, message)
|
||||||
|
end
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
kernel.start()
|
kernel.start()
|
||||||
|
|
|
@ -79,7 +79,7 @@ return function(env)
|
||||||
|
|
||||||
-- place package and require function into env
|
-- place package and require function into env
|
||||||
env.package = {
|
env.package = {
|
||||||
path = env.LUA_PATH or _G.LUA_PATH or DEFAULT_PATH,
|
path = env.LUA_PATH or _G.LUA_PATH or DEFAULT_PATH,
|
||||||
config = '/\n:\n?\n!\n-',
|
config = '/\n:\n?\n!\n-',
|
||||||
preload = { },
|
preload = { },
|
||||||
loaded = {
|
loaded = {
|
||||||
|
|
|
@ -37,6 +37,22 @@ local function trim_traceback(target, marker)
|
||||||
for line in target:gmatch("([^\n]*)\n?") do ttarget[#ttarget + 1] = line end
|
for line in target:gmatch("([^\n]*)\n?") do ttarget[#ttarget + 1] = line end
|
||||||
for line in marker:gmatch("([^\n]*)\n?") do tmarker[#tmarker + 1] = line end
|
for line in marker:gmatch("([^\n]*)\n?") do tmarker[#tmarker + 1] = line end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
TODO : fix this trace
|
||||||
|
Anavrins - if you could take a look, it would be appreciated
|
||||||
|
-- basically i want the stack logged in a more readable
|
||||||
|
-- format and the normal code/error message to be returned
|
||||||
|
|
||||||
|
-- unsure why the traceback method concatenates the stack
|
||||||
|
-- when it can just be returned as a table - would make
|
||||||
|
-- filtering much simpler
|
||||||
|
|
||||||
|
-- the following seems to reduce the stacktrace way too
|
||||||
|
-- much - losing most of the relevant call stack
|
||||||
|
|
||||||
|
-- i have modified this a bit from the original - not sure
|
||||||
|
-- if my changes are causing the issues or not
|
||||||
|
|
||||||
-- Trim identical suffixes
|
-- Trim identical suffixes
|
||||||
local t_len, m_len = #ttarget, #tmarker
|
local t_len, m_len = #ttarget, #tmarker
|
||||||
while t_len >= 3 and ttarget[t_len] == tmarker[m_len] do
|
while t_len >= 3 and ttarget[t_len] == tmarker[m_len] do
|
||||||
|
@ -50,7 +66,7 @@ local function trim_traceback(target, marker)
|
||||||
table.remove(ttarget, t_len)
|
table.remove(ttarget, t_len)
|
||||||
t_len = t_len - 1
|
t_len = t_len - 1
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
ttarget[#ttarget] = nil -- remove 2 calls added by the added xpcall
|
ttarget[#ttarget] = nil -- remove 2 calls added by the added xpcall
|
||||||
ttarget[#ttarget] = nil
|
ttarget[#ttarget] = nil
|
||||||
|
|
||||||
|
@ -84,6 +100,7 @@ return function (fn, ...)
|
||||||
if trace[i] == "stack traceback:" then trace_starts = i; break end
|
if trace[i] == "stack traceback:" then trace_starts = i; break end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
_G._syslog('')
|
||||||
for _, line in pairs(trace) do
|
for _, line in pairs(trace) do
|
||||||
_G._syslog(line)
|
_G._syslog(line)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue