From 26bbb509815c46f5cabec45e0c3e8bcab5b43322 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Sat, 23 May 2020 21:45:05 -0600 Subject: [PATCH] debugger support --- sys/autorun/version.lua | 80 ++++++------- sys/boot/opus.boot | 15 +++ sys/init/3.sys.lua | 2 +- sys/modules/opus/fuzzy.lua | 34 +++--- sys/modules/opus/trace.lua | 18 ++- .../opus/ui/components/QuickSelect.lua | 107 ++++++++++++++++++ 6 files changed, 194 insertions(+), 62 deletions(-) create mode 100644 sys/modules/opus/ui/components/QuickSelect.lua diff --git a/sys/autorun/version.lua b/sys/autorun/version.lua index 7c5e5b2..798e8ec 100644 --- a/sys/autorun/version.lua +++ b/sys/autorun/version.lua @@ -7,47 +7,47 @@ local shell = _ENV.shell local URL = 'https://raw.githubusercontent.com/kepler155c/opus/%s/.opus_version' if fs.exists('.opus_version') then - local f = fs.open('.opus_version', 'r') - local date = f.readLine() - f.close() - date = type(date) == 'string' and Util.split(date)[1] + local f = fs.open('.opus_version', 'r') + local date = f.readLine() + f.close() + date = type(date) == 'string' and Util.split(date)[1] - local today = os.date('%j') - local config = Config.load('version', { - packages = date, - checked = today, - }) + local today = os.date('%j') + local config = Config.load('version', { + packages = date, + checked = today, + }) - -- check if packages need an update - if date ~= config.packages then - config.packages = date - Config.update('version', config) - print('Updating packages') - shell.run('package updateall') - os.reboot() - end + -- check if packages need an update + if date ~= config.packages then + config.packages = date + Config.update('version', config) + print('Updating packages') + shell.run('package updateall') + os.reboot() + end - if type(date) == 'string' and #date > 0 then - if config.checked ~= today then - config.checked = today - Config.update('version', config) - print('Checking for new version') - pcall(function() - local c = Util.httpGet(string.format(URL, _G.OPUS_BRANCH)) - if c then - local lines = Util.split(c) - local revdate = table.remove(lines, 1) - if date ~= revdate and config.skip ~= revdate then - config.current = revdate - config.details = table.concat(lines, '\n') - Config.update('version', config) - print('New version available') - if _ENV.multishell then - shell.openForegroundTab('sys/apps/Version.lua') - end - end - end - end) - end - end + if type(date) == 'string' and #date > 0 then + if config.checked ~= today then + config.checked = today + Config.update('version', config) + print('Checking for new version') + pcall(function() + local c = Util.httpGet(string.format(URL, _G.OPUS_BRANCH)) + if c then + local lines = Util.split(c) + local revdate = table.remove(lines, 1) + if date ~= revdate and config.skip ~= revdate then + config.current = revdate + config.details = table.concat(lines, '\n') + Config.update('version', config) + print('New version available') + if _ENV.multishell then + shell.openForegroundTab('sys/apps/Version.lua') + end + end + end + end) + end + end end diff --git a/sys/boot/opus.boot b/sys/boot/opus.boot index 2a02d14..da4a3c4 100644 --- a/sys/boot/opus.boot +++ b/sys/boot/opus.boot @@ -1,5 +1,20 @@ local fs = _G.fs +-- override bios function to include the actual filename +function _G.loadfile(filename, env) + -- Support the previous `loadfile(filename, env)` form instead. + if type(mode) == "table" and env == nil then + mode, env = nil, mode + end + + local file = fs.open(filename, "r") + if not file then return nil, "File not found" end + + local func, err = load(file.readAll(), '@' .. filename, mode, env) + file.close() + return func, err +end + local sandboxEnv = setmetatable({ }, { __index = _G }) for k,v in pairs(_ENV) do sandboxEnv[k] = v diff --git a/sys/init/3.sys.lua b/sys/init/3.sys.lua index d43bf53..e8103d4 100644 --- a/sys/init/3.sys.lua +++ b/sys/init/3.sys.lua @@ -42,5 +42,5 @@ end -- non-standard - will raise error instead os.exit = function(code) - error('Terminated with ' .. code) + error(code) end diff --git a/sys/modules/opus/fuzzy.lua b/sys/modules/opus/fuzzy.lua index 353c142..232af5a 100644 --- a/sys/modules/opus/fuzzy.lua +++ b/sys/modules/opus/fuzzy.lua @@ -7,41 +7,41 @@ local sub = string.sub -- https://rosettacode.org/wiki/Jaro_distance (ported to lua) return function(s1, s2) local l1, l2 = #s1, #s2; - if l1 == 0 then + if l1 == 0 then return l2 == 0 and 1.0 or 0.0 end local match_distance = max(floor(max(l1, l2) / 2) - 1, 0) - local s1_matches = { } - local s2_matches = { } - local matches = 0 + local s1_matches = { } + local s2_matches = { } + local matches = 0 for i = 1, l1 do - local _end = min(i + match_distance + 1, l2) + local _end = min(i + match_distance + 1, l2) for k = max(1, i - match_distance), _end do - if not s2_matches[k] and sub(s1, i, i) == sub(s2, k, k) then - s1_matches[i] = true - s2_matches[k] = true - matches = matches + 1 - break + if not s2_matches[k] and sub(s1, i, i) == sub(s2, k, k) then + s1_matches[i] = true + s2_matches[k] = true + matches = matches + 1 + break end end end - if matches == 0 then + if matches == 0 then return 0.0 end - local t = 0.0 - local k = 1 + local t = 0.0 + local k = 1 for i = 1, l1 do - if s1_matches[i] then + if s1_matches[i] then while not s2_matches[k] do k = k + 1 end if sub(s1, i, i) ~= sub(s2, k, k) then t = t + 0.5 end - k = k + 1 + k = k + 1 end end @@ -51,6 +51,6 @@ return function(s1, s2) b = b + .5 end - local m = matches - return (m / l1 + m / l2 + (m - t) / m) / 3.0 + b + local m = matches + return (m / l1 + m / l2 + (m - t) / m) / 3.0 + b end diff --git a/sys/modules/opus/trace.lua b/sys/modules/opus/trace.lua index d003f48..ed2738a 100644 --- a/sys/modules/opus/trace.lua +++ b/sys/modules/opus/trace.lua @@ -12,6 +12,10 @@ local function traceback(x) return x end + if x and x:match(':%d+: 0$') then + return x + end + if debug_traceback then -- The parens are important, as they prevent a tail call occuring, meaning -- the stack level is preserved. This ensures the code behaves identically @@ -65,7 +69,7 @@ local function trim_traceback(stack) local t = { } for _, line in pairs(trace) do if not matchesFilter(line) then - line = line:gsub("in function", "in") + line = line:gsub("in function", "in"):gsub('%w+/', '') table.insert(t, line) end end @@ -84,9 +88,15 @@ return function (fn, ...) if not res[1] and res[2] ~= nil then local err, trace = trim_traceback(res[2]) - _G._syslog('\n' .. err .. '\n' .. 'stack traceback:') - for _, v in ipairs(trace) do - _G._syslog(v) + if #trace > 0 then + _G._syslog('\n' .. err .. '\n' .. 'stack traceback:') + for _, v in ipairs(trace) do + _G._syslog(v) + end + end + + if err:match(':%d+: 0$') then + return true end return res[1], err, trace diff --git a/sys/modules/opus/ui/components/QuickSelect.lua b/sys/modules/opus/ui/components/QuickSelect.lua new file mode 100644 index 0000000..dc96979 --- /dev/null +++ b/sys/modules/opus/ui/components/QuickSelect.lua @@ -0,0 +1,107 @@ +local class = require('opus.class') +local fuzzy = require('opus.fuzzy') +local UI = require('opus.ui') + +local fs = _G.fs +local _insert = table.insert + +UI.QuickSelect = class(UI.Window) +UI.QuickSelect.defaults = { + UIElement = 'QuickSelect', +} +function UI.QuickSelect:postInit() + self.filterEntry = UI.TextEntry { + x = 2, y = 2, ex = -2, + shadowText = 'File name', + accelerators = { + [ 'enter' ] = 'accept', + [ 'up' ] = 'grid_up', + [ 'down' ] = 'grid_down', + }, + } + self.grid = UI.ScrollingGrid { + x = 2, y = 3, ex = -2, ey = -4, + disableHeader = true, + columns = { + { key = 'name' }, + { key = 'dir', textColor = 'lightGray' }, + }, + accelerators = { + grid_select = 'accept', + }, + } + self.cancel = UI.Button { + x = -9, y = -2, + text = 'Cancel', + event = 'select_cancel', + } +end + +function UI.QuickSelect:draw() + self:fillArea(1, 1, self.width, self.height, string.rep('\127', self.width), 'black', 'gray') + self:drawChildren() +end + +function UI.QuickSelect:applyFilter(filter) + if filter then + filter = filter:lower() + self.grid.sortColumn = 'score' + + for _,v in pairs(self.grid.values) do + v.score = -fuzzy(v.lname, filter) + end + else + self.grid.sortColumn = 'lname' + end + + self.grid:update() + self.grid:setIndex(1) +end + +function UI.QuickSelect:enable() + self.grid.values = { } + local function recurse(dir) + local files = fs.list(dir) + for _,f in ipairs(files) do + local fullName = fs.combine(dir, f) + if fs.native.isDir(fullName) then -- skip virtual dirs + if f ~= '.git' then recurse(fullName) end + else + _insert(self.grid.values, { + name = f, + dir = dir, + lname = f:lower(), + fullName = fullName, + }) + end + end + end + recurse('') + self:applyFilter() + self.filterEntry:reset() + UI.Window.enable(self) +end + +function UI.QuickSelect:eventHandler(event) + if event.type == 'grid_up' then + self.grid:emit({ type = 'scroll_up' }) + return true + + elseif event.type == 'grid_down' then + self.grid:emit({ type = 'scroll_down' }) + return true + + elseif event.type == 'accept' then + local sel = self.grid:getSelected() + if sel then + self:emit({ type = 'select_file', file = sel.fullName, element = self }) + end + return true + + elseif event.type == 'text_change' then + self:applyFilter(event.text) + self.grid:draw() + return true + + end +end