transition to kernel

This commit is contained in:
kepler155c@gmail.com 2018-01-20 07:18:13 -05:00
parent d85e9b96b2
commit 1c1eb9b782
28 changed files with 398 additions and 228 deletions

70
startup
View File

@ -1,9 +1,18 @@
local colors = _G.colors
local os = _G.os
local settings = _G.settings
local term = _G.term
local bootOptions = { local bootOptions = {
{ prompt = 'Default Shell', file = '/sys/boot/default.boot' }, { prompt = os.version() },
{ prompt = 'Opus' , file = '/sys/boot/opus.boot' }, { prompt = 'Opus' , args = { '/sys/boot/opus.boot' } },
-- { prompt = 'TLCO' , file = '/sys/boot/tlco.boot' }, { prompt = 'Opus Shell' , args = { '/sys/boot/opus.boot', 'sys/apps/shell' } },
} }
local bootOption = 2 local bootOption = 2
if settings then
settings.load('.settings')
bootOption = tonumber(settings.get('opus.boot_option') or 2) or 2
end
local function startupMenu() local function startupMenu()
while true do while true do
@ -16,20 +25,51 @@ local function startupMenu()
end end
print('') print('')
term.write('> ') term.write('> ')
local ch = tonumber(read()) local ch = tonumber(_G.read())
if ch and bootOptions[ch] then if ch and bootOptions[ch] then
return ch return ch
end end
end end
end
local function splash()
local w, h = term.current().getSize()
term.setTextColor(colors.white)
if not term.isColor() then
local str = 'Opus OS'
term.setCursorPos((w - #str) / 2, h / 2)
term.write(str)
else
term.setBackgroundColor(colors.black)
term.clear() term.clear()
term.setCursorPos(1, 1) local opus = {
'fffff00',
'ffff07000',
'ff00770b00 4444',
'ff077777444444444',
'f07777744444444444',
'f0000777444444444',
'070000111744444',
'777770000',
'7777000000',
'70700000000',
'077000000000',
}
for k,line in ipairs(opus) do
term.setCursorPos((w - 18) / 2, k + (h - #opus) / 2)
term.blit(string.rep(' ', #line), string.rep('a', #line), line)
end
end
local str = 'Press any key for menu'
term.setCursorPos((w - #str) / 2, h)
term.write(str)
end end
term.clear() term.clear()
term.setCursorPos(1, 1) splash()
print('Starting OS')
print()
print('Press any key for menu')
local timerId = os.startTimer(1.5) local timerId = os.startTimer(1.5)
while true do while true do
local e, id = os.pullEvent() local e, id = os.pullEvent()
@ -38,8 +78,18 @@ while true do
end end
if e == 'char' then if e == 'char' then
bootOption = startupMenu() bootOption = startupMenu()
if settings then
settings.set('opus.boot_option', bootOption)
settings.save('.settings')
end
break break
end end
end end
os.run(getfenv(1), bootOptions[bootOption].file) term.clear()
term.setCursorPos(1, 1)
if bootOptions[bootOption].args then
os.run(_G.getfenv(1), table.unpack(bootOptions[bootOption].args))
else
print(bootOptions[bootOption].prompt)
end

View File

@ -154,8 +154,10 @@ function Event.pullEvents(...)
end end
repeat repeat
local e = Event.pullEvent() Event.pullEvent()
until e[1] == 'terminate' until Event.terminate
Event.terminate = false
end end
function Event.exitPullEvents() function Event.exitPullEvents()
@ -203,11 +205,12 @@ function Event.pullEvent(eventType)
while true do while true do
local e = { os.pullEventRaw() } local e = { os.pullEventRaw() }
Event.terminate = Event.terminate or e[1] == 'terminate'
processHandlers(e[1]) processHandlers(e[1])
processRoutines(table.unpack(e)) processRoutines(table.unpack(e))
if Event.terminate or e[1] == 'terminate' then if Event.terminate then
Event.terminate = false
return { 'terminate' } return { 'terminate' }
end end

View File

@ -55,12 +55,13 @@ local function loadUrl(url)
end end
end end
-- Add require and package to the environment
local function requireWrapper(env) local function requireWrapper(env)
local function standardSearcher(modname) local function standardSearcher(modname)
if package.loaded[modname] then if env.package.loaded[modname] then
return function() return function()
return package.loaded[modname] return env.package.loaded[modname]
end end
end end
end end
@ -79,7 +80,7 @@ local function requireWrapper(env)
local function pathSearcher(modname) local function pathSearcher(modname)
local fname = modname:gsub('%.', '/') .. '.lua' local fname = modname:gsub('%.', '/') .. '.lua'
for dir in string.gmatch(package.path, "[^:]+") do for dir in string.gmatch(env.package.path, "[^:]+") do
local path = fs.combine(dir, fname) local path = fs.combine(dir, fname)
if fs.exists(path) and not fs.isDir(path) then if fs.exists(path) and not fs.isDir(path) then
return loadfile(path, env) return loadfile(path, env)
@ -115,7 +116,7 @@ local function requireWrapper(env)
local fname = modname:gsub('%.', '/') .. '.lua' local fname = modname:gsub('%.', '/') .. '.lua'
if fname:sub(1, 1) ~= '/' then if fname:sub(1, 1) ~= '/' then
for entry in string.gmatch(package.upath, "[^;]+") do for entry in string.gmatch(env.package.upath, "[^;]+") do
local url = entry .. '/' .. fname local url = entry .. '/' .. fname
local c = loadUrl(url) local c = loadUrl(url)
if c then if c then
@ -127,8 +128,8 @@ local function requireWrapper(env)
-- place package and require function into env -- place package and require function into env
env.package = { env.package = {
path = LUA_PATH or 'sys/apis', path = env.LUA_PATH or 'sys/apis',
upath = LUA_UPATH or DEFAULT_UPATH, upath = env.LUA_UPATH or DEFAULT_UPATH,
config = '/\n:\n?\n!\n-', config = '/\n:\n?\n!\n-',
loaded = { loaded = {
math = math, math = math,
@ -148,15 +149,14 @@ local function requireWrapper(env)
} }
function env.require(modname) function env.require(modname)
for _,searcher in ipairs(env.package.loaders) do
for _,searcher in ipairs(package.loaders) do
local fn, msg = searcher(modname) local fn, msg = searcher(modname)
if fn then if fn then
local module, msg2 = fn(modname, env) local module, msg2 = fn(modname, env)
if not module then if not module then
error(msg2 or (modname .. ' module returned nil'), 2) error(msg2 or (modname .. ' module returned nil'), 2)
end end
package.loaded[modname] = module env.package.loaded[modname] = module
return module return module
end end
if msg then if msg then
@ -171,6 +171,6 @@ end
return function(env) return function(env)
env = env or getfenv(2) env = env or getfenv(2)
setfenv(requireWrapper, env) --setfenv(requireWrapper, env)
return requireWrapper(env) return requireWrapper(env)
end end

View File

@ -121,10 +121,10 @@ function Peripheral.get(args)
end end
local function getProxy(pi) local function getProxy(pi)
local socket = Socket.connect(pi.host, 189) local socket, msg = Socket.connect(pi.host, 189)
if not socket then if not socket then
error("Timed out attaching peripheral: " .. pi.uri) error("Timed out attaching peripheral: " .. pi.uri .. '\n' .. msg)
end end
-- write the uri of the periperal we are requesting... -- write the uri of the periperal we are requesting...

View File

@ -24,7 +24,7 @@ function socketClass:read(timeout)
while true do while true do
local e, id = os.pullEvent() local e, id = os.pullEvent()
if e == 'transport_' .. self.sport then if e == 'transport_' .. self.uid then
data, distance = _G.transport.read(self) data, distance = _G.transport.read(self)
if data then if data then
os.cancelTimer(timerId) os.cancelTimer(timerId)

View File

@ -1,40 +1,229 @@
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 _rep = string.rep
local _sub = string.sub
local Terminal = { } local Terminal = { }
function Terminal.scrollable(win, parent) -- add scrolling functions to a window
local w, h = win.getSize() function Terminal.scrollable(win, maxScroll)
local _, ph = parent.getSize() local lines = { }
local scrollPos = 0 local scrollPos = 0
local scp = win.setCursorPos local oblit, oreposition = win.blit, win.reposition
win.setCursorPos = function(x, y) local palette = { }
_G._p = y for n = 1, 16 do
if y > scrollPos + ph then palette[2 ^ (n - 1)] = _sub("0123456789abcdef", n, n)
win.scrollTo(y - ph)
end
scp(x, y)
end end
win.scrollUp = function() maxScroll = maxScroll or 100
win.scrollTo(scrollPos - 1)
-- should only do if window is visible...
local function redraw()
local _, h = win.getSize()
local x, y = win.getCursorPos()
for i = 1, h do
local line = lines[i + scrollPos]
if line and line.dirty then
win.setCursorPos(1, i)
oblit(line.text, line.fg, line.bg)
line.dirty = false
end
end
win.setCursorPos(x, y)
end end
win.scrollDown = function() local function scrollTo(p, forceRedraw)
win.scrollTo(scrollPos + 1) local _, h = win.getSize()
end local ms = #lines - h -- max scroll
p = math.min(math.max(p, 0), ms) -- normalize
win.scrollTo = function(p) if p ~= scrollPos or forceRedraw then
p = math.min(math.max(p, 0), h - ph)
if p ~= scrollPos then
scrollPos = p scrollPos = p
win.reposition(1, -scrollPos + 1, w, h) for _, line in pairs(lines) do
line.dirty = true
end end
end end
end end
function win.write(text)
local _, h = win.getSize()
scrollTo(#lines - h)
win.blit(tostring(text),
_rep(palette[win.getTextColor()], #text),
_rep(palette[win.getBackgroundColor()], #text))
local x, y = win.getCursorPos()
win.setCursorPos(x + #text, y)
end
function win.clearLine()
local w, h = win.getSize()
local _, y = win.getCursorPos()
scrollTo(#lines - h)
lines[y + scrollPos] = {
text = _rep(' ', w),
fg = _rep(palette[win.getTextColor()], w),
bg = _rep(palette[win.getBackgroundColor()], w),
dirty = true,
}
redraw()
end
function win.blit(text, fg, bg)
local x, y = win.getCursorPos()
local w, h = win.getSize()
if y > 0 and y <= h and x <= w then
local width = #text
-- fix ffs
if x < 1 then
text = _sub(text, 2 - x)
if bg then
bg = _sub(bg, 2 - x)
end
if bg then
fg = _sub(fg, 2 - x)
end
width = width + x - 1
x = 1
end
if x + width - 1 > w then
text = _sub(text, 1, w - x + 1)
if bg then
bg = _sub(bg, 1, w - x + 1)
end
if bg then
fg = _sub(fg, 1, w - x + 1)
end
width = #text
end
if width > 0 then
local function replace(sstr, pos, rstr)
if pos == 1 and width == w then
return rstr
elseif pos == 1 then
return rstr .. _sub(sstr, pos+width)
elseif pos + width > w then
return _sub(sstr, 1, pos-1) .. rstr
end
return _sub(sstr, 1, pos-1) .. rstr .. _sub(sstr, pos+width)
end
local line = lines[y + scrollPos]
line.dirty = true
line.text = replace(line.text, x, text, width)
if fg then
line.fg = replace(line.fg, x, fg, width)
end
if bg then
line.bg = replace(line.bg, x, bg, width)
end
end
end
redraw()
end
function win.clear()
local w, h = win.getSize()
local text = _rep(' ', w)
local fg = _rep(palette[win.getTextColor()], w)
local bg = _rep(palette[win.getBackgroundColor()], w)
lines = { }
for y = 1, h do
lines[y] = {
dirty = true,
text = text,
fg = fg,
bg = bg,
}
end
scrollPos = 0
redraw()
end
-- doesn't support negative scrolling...
function win.scroll(n)
local w = win.getSize()
for _ = 1, n do
lines[#lines + 1] = {
text = _rep(' ', w),
fg = _rep(palette[win.getTextColor()], w),
bg = _rep(palette[win.getBackgroundColor()], w),
}
end
while #lines > maxScroll do
table.remove(lines, 1)
end
scrollTo(maxScroll, true)
redraw()
end
function win.scrollUp()
scrollTo(scrollPos - 1)
redraw()
end
function win.scrollDown()
scrollTo(scrollPos + 1)
redraw()
end
function win.reposition(x, y, nw, nh)
local w, h = win.getSize()
local D = (nh or h) - h
if D > 0 then
for _ = 1, D do
lines[#lines + 1] = {
text = _rep(' ', w),
fg = _rep(palette[win.getTextColor()], w),
bg = _rep(palette[win.getBackgroundColor()], w),
}
end
elseif D < 0 then
for _ = D, -1 do
lines[#lines] = nil
end
end
return oreposition(x, y, nw, nh)
end
win.clear()
end
-- get windows contents
function Terminal.getContents(win, parent)
local oblit, oscp = parent.blit, parent.setCursorPos
local lines = { }
parent.blit = function(text, fg, bg)
lines[#lines + 1] = {
text = text,
fg = fg,
bg = bg,
}
end
parent.setCursorPos = function() end
win.setVisible(true)
win.redraw()
parent.blit = oblit
parent.setCursorPos = oscp
return lines
end
function Terminal.toGrayscale(ct) function Terminal.toGrayscale(ct)
local scolors = { local scolors = {
[ colors.white ] = colors.white, [ colors.white ] = colors.white,

View File

@ -154,6 +154,7 @@ function Util.merge(obj, args)
obj[k] = v obj[k] = v
end end
end end
return obj
end end
function Util.deepMerge(obj, args) function Util.deepMerge(obj, args)

View File

@ -11,7 +11,6 @@ local multishell = _ENV.multishell
local os = _G.os local os = _G.os
local shell = _ENV.shell local shell = _ENV.shell
multishell.setTitle(multishell.getCurrent(), 'Files')
UI:configure('Files', ...) UI:configure('Files', ...)
local config = { local config = {
@ -255,9 +254,15 @@ function Browser:setDir(dirName, noStatus)
self.grid:setIndex(self.dir.index) self.grid:setIndex(self.dir.index)
end end
function Browser:run(path, ...) function Browser:run(...)
local tabId = shell.openTab(path, ...) if multishell then
local tabId = shell.openTab(...)
multishell.setFocus(tabId) multishell.setFocus(tabId)
else
shell.run(...)
Event.terminate = false
self:draw()
end
end end
function Browser:hasMarked() function Browser:hasMarked()

View File

@ -5,9 +5,7 @@ local Util = require('util')
local colors = _G.colors local colors = _G.colors
local help = _G.help local help = _G.help
local multishell = _ENV.multishell
multishell.setTitle(multishell.getCurrent(), 'Help')
UI:configure('Help', ...) UI:configure('Help', ...)
local topics = { } local topics = { }

View File

@ -7,7 +7,6 @@ local UI = require('ui')
local Util = require('util') local Util = require('util')
local colors = _G.colors local colors = _G.colors
local multishell = _ENV.multishell
local os = _G.os local os = _G.os
local textutils = _G.textutils local textutils = _G.textutils
@ -16,9 +15,6 @@ sandboxEnv.exit = function() Event.exitPullEvents() end
sandboxEnv._echo = function( ... ) return { ... } end sandboxEnv._echo = function( ... ) return { ... } end
injector(sandboxEnv) injector(sandboxEnv)
if multishell and multishell.setTitle then
multishell.setTitle(multishell.getCurrent(), 'Lua')
end
UI:configure('Lua', ...) UI:configure('Lua', ...)
local command = '' local command = ''

View File

@ -12,7 +12,6 @@ local network = _G.network
local os = _G.os local os = _G.os
local shell = _ENV.shell local shell = _ENV.shell
multishell.setTitle(multishell.getCurrent(), 'Network')
UI:configure('Network', ...) UI:configure('Network', ...)
local gridColumns = { local gridColumns = {

View File

@ -11,14 +11,13 @@ local UI = require('ui')
local Util = require('util') local Util = require('util')
local fs = _G.fs local fs = _G.fs
local multishell = _ENV.multishell local multishell = _ENV.multishell or error('This program requires multishell')
local pocket = _G.pocket local pocket = _G.pocket
local term = _G.term local term = _G.term
local turtle = _G.turtle local turtle = _G.turtle
local REGISTRY_DIR = 'usr/.registry' local REGISTRY_DIR = 'usr/.registry'
multishell.setTitle(multishell.getCurrent(), 'Overview')
UI:configure('Overview', ...) UI:configure('Overview', ...)
local config = { local config = {

View File

@ -7,13 +7,11 @@ local UI = require('ui')
local Util = require('util') local Util = require('util')
local fs = _G.fs local fs = _G.fs
local multishell = _ENV.multishell
local os = _G.os local os = _G.os
local settings = _G.settings local settings = _G.settings
local shell = _ENV.shell local shell = _ENV.shell
local turtle = _G.turtle local turtle = _G.turtle
multishell.setTitle(multishell.getCurrent(), 'System')
UI:configure('System', ...) UI:configure('System', ...)
local env = { local env = {

View File

@ -4,9 +4,9 @@ local Event = require('event')
local UI = require('ui') local UI = require('ui')
local Util = require('util') local Util = require('util')
local kernel = _G.kernel
local multishell = _ENV.multishell local multishell = _ENV.multishell
multishell.setTitle(multishell.getCurrent(), 'Tasks')
UI:configure('Tasks', ...) UI:configure('Tasks', ...)
local page = UI.Page { local page = UI.Page {
@ -24,7 +24,7 @@ local page = UI.Page {
{ heading = 'Status', key = 'status' }, { heading = 'Status', key = 'status' },
{ heading = 'Time', key = 'timestamp' }, { heading = 'Time', key = 'timestamp' },
}, },
values = multishell.getTabs(), values = kernel.routines,
sortColumn = 'uid', sortColumn = 'uid',
autospace = true, autospace = true,
}, },

View File

@ -1,18 +1,15 @@
local parentShell = _ENV.shell local parentShell = _ENV.shell
_ENV.shell = { } _ENV.shell = { }
--_ENV.multishell = _ENV.multishell or { }
local fs = _G.fs local fs = _G.fs
local shell = _ENV.shell local shell = _ENV.shell
--local multishell = _ENV.multishell
local sandboxEnv = setmetatable({ }, { __index = _G }) local sandboxEnv = setmetatable({ }, { __index = _G })
for k,v in pairs(_ENV) do for k,v in pairs(_ENV) do
sandboxEnv[k] = v sandboxEnv[k] = v
end end
sandboxEnv.shell = shell sandboxEnv.shell = shell
--sandboxEnv.multishell = multishell
_G.requireInjector() _G.requireInjector()
@ -64,7 +61,7 @@ local function run(env, ...)
end end
if _ENV.multishell then if _ENV.multishell then
_ENV.multishell.setTitle(_ENV.multishell.getCurrent(), fs.getName(path)) _ENV.multishell.setTitle(_ENV.multishell.getCurrent(), fs.getName(path):match('([^%.]+)'))
end end
if isUrl then if isUrl then
@ -309,7 +306,7 @@ function shell.newTab(tabInfo, ...)
tabInfo.path = path tabInfo.path = path
tabInfo.env = sandboxEnv tabInfo.env = sandboxEnv
tabInfo.args = args tabInfo.args = args
tabInfo.title = fs.getName(path) tabInfo.title = fs.getName(path):match('([^%.]+)')
if path ~= 'sys/apps/shell' then if path ~= 'sys/apps/shell' then
table.insert(tabInfo.args, 1, tabInfo.path) table.insert(tabInfo.args, 1, tabInfo.path)
@ -345,6 +342,7 @@ end
local Config = require('config') local Config = require('config')
local History = require('history') local History = require('history')
local Terminal = require('terminal')
local colors = _G.colors local colors = _G.colors
local keys = _G.keys local keys = _G.keys
@ -352,6 +350,10 @@ local os = _G.os
local term = _G.term local term = _G.term
local textutils = _G.textutils local textutils = _G.textutils
local terminal = term.current()
Terminal.scrollable(terminal, 100)
terminal.noAutoScroll = true
local config = { local config = {
standard = { standard = {
textColor = colors.white, textColor = colors.white,
@ -567,6 +569,12 @@ local function shellRead(history)
sLine = '' sLine = ''
nPos = 0 nPos = 0
redraw() redraw()
elseif sEvent == 'mouse_scroll' then
if param == -1 then
terminal.scrollUp()
else
terminal.scrollDown()
end
elseif sEvent == 'terminate' then elseif sEvent == 'terminate' then
bExit = true bExit = true
break break

View File

@ -22,7 +22,7 @@ if not remoteId then
error('Syntax: telnet [-title TITLE] ID [PROGRAM]') error('Syntax: telnet [-title TITLE] ID [PROGRAM]')
end end
if options.title then if options.title and multishell then
multishell.setTitle(multishell.getCurrent(), options.title) multishell.setTitle(multishell.getCurrent(), options.title)
end end

View File

@ -22,7 +22,9 @@ if not remoteId then
error('Syntax: vnc <host ID>') error('Syntax: vnc <host ID>')
end end
if multishell then
multishell.setTitle(multishell.getCurrent(), 'VNC-' .. remoteId) multishell.setTitle(multishell.getCurrent(), 'VNC-' .. remoteId)
end
print('connecting...') print('connecting...')
local socket, msg = Socket.connect(remoteId, 5900) local socket, msg = Socket.connect(remoteId, 5900)

View File

@ -25,10 +25,7 @@ end
local function run(file, ...) local function run(file, ...)
local s, m = loadfile(file, makeEnv()) local s, m = loadfile(file, makeEnv())
if s then if s then
s, m = pcall(s, ...) return s(...)
if s then
return m
end
end end
error('Error loading ' .. file .. '\n' .. m) error('Error loading ' .. file .. '\n' .. m)
end end
@ -47,9 +44,6 @@ local function runUrl(file, ...)
error('Failed to download ' .. url) error('Failed to download ' .. url)
end end
local args = { ... }
local s, m = pcall(function()
-- Install require shim -- Install require shim
if fs.exists('sys/apis/injector.lua') then if fs.exists('sys/apis/injector.lua') then
_G.requireInjector = run('sys/apis/injector.lua') _G.requireInjector = run('sys/apis/injector.lua')
@ -62,8 +56,7 @@ local s, m = pcall(function()
fs.mount('', 'gitfs', GIT_REPO) fs.mount('', 'gitfs', GIT_REPO)
end end
run('sys/apps/shell', 'sys/kernel.lua', table.unpack(args)) local s, m = pcall(run, 'sys/apps/shell', 'sys/kernel.lua', ...)
end)
if not s then if not s then
print('\nError loading Opus OS\n') print('\nError loading Opus OS\n')

View File

@ -2,14 +2,14 @@ local pullEvent = os.pullEventRaw
local shutdown = os.shutdown local shutdown = os.shutdown
os.pullEventRaw = function() os.pullEventRaw = function()
error('die') error('')
end end
os.shutdown = function() os.shutdown = function()
os.pullEventRaw = pullEvent os.pullEventRaw = pullEvent
os.shutdown = shutdown os.shutdown = shutdown
os.run(getfenv(1), 'sys/boot/multishell.boot') os.run(getfenv(1), 'sys/boot/opus.boot')
end end
os.queueEvent('modem_message') os.queueEvent('modem_message')

View File

@ -95,7 +95,7 @@
\030 \031f | |\ \030 \031f | |\
\030 \031fo| o|\ \030 \031fo| o|\
", ",
run = "usr/apps/music.lua", run = "usr/apps/Music.lua",
requires = 'turtle', requires = 'turtle',
}, },
c47ae15370cfe1ed2781eedc1dc2547d12d9e972 = { c47ae15370cfe1ed2781eedc1dc2547d12d9e972 = {
@ -128,7 +128,7 @@
icon = "\0304 \030 \ icon = "\0304 \030 \
\030f \0304 \0307 \030 \031 \031f_\ \030f \0304 \0307 \030 \031 \031f_\
\030f \0304 \0307 \030 \031f/", \030f \0304 \0307 \030 \031f/",
run = "Peripherals.lua", run = "Devices.lua",
}, },
f39d173d91c22348565c20283b89d4d1cabd3b7e = { f39d173d91c22348565c20283b89d4d1cabd3b7e = {
title = "Falling", title = "Falling",
@ -170,7 +170,7 @@
icon = "\030f\031f \0315/\ icon = "\030f\031f \0315/\
\030f\031f \0315/\\/ \ \030f\031f \0315/\\/ \
\030f\0315/\031f ", \030f\0315/\031f ",
run = "Tabs.lua", run = "Tasks.lua",
}, },
[ "114edfc04a1ab03541bdc80ce064f66a7cfcedbb" ] = { [ "114edfc04a1ab03541bdc80ce064f66a7cfcedbb" ] = {
title = "Recorder", title = "Recorder",

View File

@ -1,44 +0,0 @@
if false then
local colors = _G.colors
local term = _G.term
local window = _G.window
local terminal = term.current()
local w, h = term.getSize()
local splashWindow = window.create(terminal.parent, 1, 1, w, h, false)
splashWindow.setTextColor(colors.white)
if splashWindow.isColor() then
splashWindow.setBackgroundColor(colors.black)
splashWindow.clear()
local opus = {
'fffff00',
'ffff07000',
'ff00770b00 4444',
'ff077777444444444',
'f07777744444444444',
'f0000777444444444',
'070000111744444',
'777770000',
'7777000000',
'70700000000',
'077000000000',
}
for k,line in ipairs(opus) do
splashWindow.setCursorPos((w - 18) / 2, k + (h - #opus) / 2)
splashWindow.blit(string.rep(' ', #line), string.rep('a', #line), line)
end
end
local str = 'Loading Opus OS...'
print(str)
splashWindow.setCursorPos((w - #str) / 2, h)
splashWindow.write(str)
terminal.setVisible(false)
splashWindow.setVisible(true)
kernel.hook('kernel_ready', function()
kernel.window.setVisible(true)
end)
end

View File

@ -1,7 +1,7 @@
local os = _G.os
-- Default label -- Default label
if not os.getComputerLabel() then if not os.getComputerLabel() then
showStatus('Setting computer label')
local id = os.getComputerID() local id = os.getComputerID()
if _G.turtle then if _G.turtle then
os.setComputerLabel('turtle_' .. id) os.setComputerLabel('turtle_' .. id)

View File

@ -11,8 +11,8 @@ end
if not fs.exists('usr/autorun') then if not fs.exists('usr/autorun') then
fs.makeDir('usr/autorun') fs.makeDir('usr/autorun')
end end
if not fs.exists('usr/etc/fstab') then if not fs.exists('usr/config/fstab') then
Util.writeFile('usr/etc/fstab', 'usr gitfs kepler155c/opus-apps/' .. _ENV.BRANCH) Util.writeFile('usr/config/fstab', 'usr gitfs kepler155c/opus-apps/' .. _ENV.BRANCH)
end end
if not fs.exists('usr/config/shell') then if not fs.exists('usr/config/shell') then
@ -35,4 +35,4 @@ end
shell.setPath(config.path) shell.setPath(config.path)
shell.setEnv('LUA_PATH', config.lua_path) shell.setEnv('LUA_PATH', config.lua_path)
fs.loadTab('usr/etc/fstab') fs.loadTab('usr/config/fstab')

View File

@ -21,3 +21,4 @@ if _G.device.wireless_modem then
startNetwork() startNetwork()
os.sleep(0) -- give the network a cycle to start os.sleep(0) -- give the network a cycle to start
end end

View File

@ -54,7 +54,7 @@ local function redrawMenu()
end end
function multishell.getFocus() function multishell.getFocus()
local currentTab = kernel.routines[1] local currentTab = kernel.getFocused()
return currentTab.uid return currentTab.uid
end end
@ -70,9 +70,7 @@ end
function multishell.setTitle(tabId, title) function multishell.setTitle(tabId, title)
local tab = kernel.find(tabId) local tab = kernel.find(tabId)
if tab then if tab then
if not tab.isOverview then tab.title = title
tab.title = title or ''
end
redrawMenu() redrawMenu()
end end
end end
@ -105,15 +103,15 @@ 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) tab.title = fs.getName(tab.path):match('([^%.]+)')
end end
tab.title = tab.title or 'untitled' tab.title = tab.title or 'untitled'
tab.window = 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.window tab.terminal = tab.terminal or tab.window
local routine = kernel.newRoutine(tab) local routine = kernel.newRoutine(tab)
tab.co = coroutine.create(function() routine.co = coroutine.create(function()
local result, err local result, err
if tab.fn then if tab.fn then
@ -128,9 +126,9 @@ function multishell.openTab(tab)
if err then if err then
printError(tostring(err)) printError(tostring(err))
end end
printError('Press enter to close') print('\nPress enter to close')
tab.isDead = true routine.isDead = true
tab.hidden = false routine.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
@ -147,8 +145,7 @@ function multishell.openTab(tab)
else else
redrawMenu() redrawMenu()
end end
return routine.uid
return tab.uid
end end
function multishell.hideTab(tabId) function multishell.hideTab(tabId)
@ -217,10 +214,9 @@ kernel.hook('multishell_redraw', function()
parentTerm.setCursorPos(1, 1) parentTerm.setCursorPos(1, 1)
parentTerm.clearLine() parentTerm.clearLine()
local currentTab = kernel.routines[1] local currentTab = kernel.getFocused()
for _,tab in pairs(kernel.routines) do for _,tab in pairs(kernel.routines) do
tab.title = tab.env._APP_TITLE or tab.title
if tab.hidden and tab ~= currentTab then if tab.hidden and tab ~= currentTab then
tab.width = 0 tab.width = 0
else else
@ -241,7 +237,8 @@ tab.title = tab.env._APP_TITLE or tab.title
end end
local function compareTab(a, b) local function compareTab(a, b)
return b.hidden and -1 or a.uid < b.uid if a.hidden then return false end
return b.hidden or a.uid < b.uid
end end
local tabX = 0 local tabX = 0
@ -295,12 +292,12 @@ end)
kernel.hook('mouse_click', function(_, eventData) kernel.hook('mouse_click', function(_, eventData)
local x, y = eventData[2], eventData[3] local x, y = eventData[2], eventData[3]
local currentTab = kernel.routines[1]
if y == 1 then if y == 1 then
if x == 1 then if x == 1 then
multishell.setFocus(overviewId) multishell.setFocus(overviewId)
elseif x == w then elseif x == w then
local currentTab = kernel.getFocused()
if currentTab then if currentTab then
multishell.terminate(currentTab.uid) multishell.terminate(currentTab.uid)
end end
@ -344,6 +341,7 @@ local function startup()
for _,file in ipairs(files) do for _,file in ipairs(files) do
os.sleep(0) os.sleep(0)
local result, err = open(directory .. '/' .. file) local result, err = open(directory .. '/' .. file)
if result then if result then
if term.isColor() then if term.isColor() then
term.setTextColor(colors.green) term.setTextColor(colors.green)
@ -362,6 +360,7 @@ local function startup()
if err then if err then
_G.printError('\n' .. err) _G.printError('\n' .. err)
end end
print()
success = false success = false
end end
end end
@ -383,8 +382,8 @@ kernel.hook('kernel_ready', function()
path = 'sys/apps/Overview.lua', path = 'sys/apps/Overview.lua',
isOverview = true, isOverview = true,
focused = true, focused = true,
title = '+',
}) })
kernel.find(overviewId).title = '+'
multishell.openTab({ multishell.openTab({
fn = startup, fn = startup,

View File

@ -1,5 +1,6 @@
_G.requireInjector() _G.requireInjector()
local Terminal = require('terminal')
local Util = require('util') local Util = require('util')
_G.kernel = { _G.kernel = {
@ -19,6 +20,8 @@ local w, h = term.getSize()
kernel.terminal = term.current() kernel.terminal = term.current()
kernel.window = window.create(kernel.terminal, 1, 1, w, h, false) kernel.window = window.create(kernel.terminal, 1, 1, w, h, false)
Terminal.scrollable(kernel.window)
local focusedRoutineEvents = Util.transpose { local focusedRoutineEvents = Util.transpose {
'char', 'key', 'key_up', 'char', 'key', 'key_up',
'mouse_click', 'mouse_drag', 'mouse_scroll', 'mouse_up', 'mouse_click', 'mouse_drag', 'mouse_scroll', 'mouse_up',
@ -73,16 +76,17 @@ function Routine:resume(event, ...)
local ok, result = coroutine.resume(self.co, event, ...) local ok, result = coroutine.resume(self.co, event, ...)
kernel.running = previous kernel.running = previous
self.terminal = term.current()
term.redirect(previousTerm)
if ok then if ok then
self.filter = result self.filter = result
else else
_G.printError(result) _G.printError(result)
if self.haltOnError then
error(result)
end end
self.terminal = term.current()
term.redirect(previousTerm)
if not ok and self.haltOnError then
error(result)
end end
if coroutine.status(self.co) == 'dead' then if coroutine.status(self.co) == 'dead' then
Util.removeByValue(kernel.routines, self) Util.removeByValue(kernel.routines, self)
@ -108,14 +112,15 @@ end
function kernel.newRoutine(args) function kernel.newRoutine(args)
kernel.UID = kernel.UID + 1 kernel.UID = kernel.UID + 1
args = args or { } local routine = setmetatable({
uid = kernel.UID,
timestamp = os.clock(),
terminal = kernel.window,
window = kernel.window,
}, { __index = Routine })
local routine = setmetatable(args, { __index = Routine }) Util.merge(routine, args)
routine.uid = kernel.UID
routine.timestamp = os.clock()
routine.env = args.env or Util.shallowCopy(shell.getEnv()) routine.env = args.env or Util.shallowCopy(shell.getEnv())
routine.terminal = args.terminal or kernel.window
routine.window = args.window or kernel.window
return routine return routine
end end
@ -242,6 +247,7 @@ local function init(...)
local runLevel = #args > 0 and 6 or 7 local runLevel = #args > 0 and 6 or 7
print('Starting Opus OS')
local dir = 'sys/extensions' local dir = 'sys/extensions'
local files = fs.list(dir) local files = fs.list(dir)
table.sort(files) table.sort(files)
@ -252,6 +258,7 @@ local function init(...)
if not s then if not s then
error(m) error(m)
end end
os.sleep(0)
end end
end end
@ -264,6 +271,7 @@ local function init(...)
path = 'sys/apps/shell', path = 'sys/apps/shell',
args = args, args = args,
haltOnExit = true, haltOnExit = true,
haltOnError = true,
terminal = kernel.terminal, terminal = kernel.terminal,
}) })
if s then if s then

View File

@ -13,12 +13,16 @@ local computerId = os.getComputerID()
local transport = { local transport = {
timers = { }, timers = { },
sockets = { }, sockets = { },
UID = 0,
} }
_G.transport = transport _G.transport = transport
function transport.open(socket) function transport.open(socket)
transport.UID = transport.UID + 1
transport.sockets[socket.sport] = socket transport.sockets[socket.sport] = socket
socket.activityTimer = os.clock() socket.activityTimer = os.clock()
socket.uid = transport.UID
end end
function transport.read(socket) function transport.read(socket)
@ -78,9 +82,11 @@ Event.on('modem_message', function(_, _, dport, dhost, msg, distance)
if msg.type == 'DISC' then if msg.type == 'DISC' then
-- received disconnect from other end -- received disconnect from other end
if socket.connected then
os.queueEvent('transport_' .. socket.uid)
end
socket.connected = false socket.connected = false
socket:close() socket:close()
os.queueEvent('transport_' .. socket.sport)
elseif msg.type == 'ACK' then elseif msg.type == 'ACK' then
local ackTimerId = socket.timers[msg.seq] local ackTimerId = socket.timers[msg.seq]
@ -109,7 +115,7 @@ Event.on('modem_message', function(_, _, dport, dhost, msg, distance)
-- use resume instead ?? -- use resume instead ??
if not socket.messages[2] then -- table size is 1 if not socket.messages[2] then -- table size is 1
os.queueEvent('transport_' .. socket.sport) os.queueEvent('transport_' .. socket.uid)
end end
--debug('>> ' .. Util.tostring({ type = 'ACK', seq = msg.seq })) --debug('>> ' .. Util.tostring({ type = 'ACK', seq = msg.seq }))

View File

@ -1,67 +1,26 @@
_G.requireInjector() _G.requireInjector(_ENV)
--[[ --[[
Adds the control-d hotkey to view the kernel log. Adds a task and the control-d hotkey to view the kernel log.
]] --]]
local Terminal = require('terminal')
local kernel = _G.kernel local kernel = _G.kernel
local keyboard = _G.device.keyboard 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 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
local w, h = kernel.window.getSize() 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) 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()
for _,r in pairs(kernel.routines) do routine.terminal = kernel.window
if r.terminal == kernel.window then routine.window = kernel.window
r.terminal = win term.redirect(kernel.window)
r.window = win
end
end
--kernel.terminal = win
kernel.window = win
routine.terminal = win
routine.window = win
term.redirect(routine.window)
local previousId local previousId
@ -69,8 +28,8 @@ kernel.hook('mouse_scroll', function(_, eventData)
local dir, y = eventData[1], eventData[3] local dir, y = eventData[1], eventData[3]
if y > 1 then if y > 1 then
local currentTab = kernel.routines[1] local currentTab = kernel.getFocused()
if currentTab.terminal.scrollUp then if currentTab.terminal.scrollUp and not currentTab.terminal.noAutoScroll then
if dir == -1 then if dir == -1 then
currentTab.terminal.scrollUp() currentTab.terminal.scrollUp()
else else