mirror of https://github.com/kepler155c/opus
debugger support
This commit is contained in:
parent
97bfae10fb
commit
26bbb50981
|
@ -7,47 +7,47 @@ local shell = _ENV.shell
|
||||||
local URL = 'https://raw.githubusercontent.com/kepler155c/opus/%s/.opus_version'
|
local URL = 'https://raw.githubusercontent.com/kepler155c/opus/%s/.opus_version'
|
||||||
|
|
||||||
if fs.exists('.opus_version') then
|
if fs.exists('.opus_version') then
|
||||||
local f = fs.open('.opus_version', 'r')
|
local f = fs.open('.opus_version', 'r')
|
||||||
local date = f.readLine()
|
local date = f.readLine()
|
||||||
f.close()
|
f.close()
|
||||||
date = type(date) == 'string' and Util.split(date)[1]
|
date = type(date) == 'string' and Util.split(date)[1]
|
||||||
|
|
||||||
local today = os.date('%j')
|
local today = os.date('%j')
|
||||||
local config = Config.load('version', {
|
local config = Config.load('version', {
|
||||||
packages = date,
|
packages = date,
|
||||||
checked = today,
|
checked = today,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- check if packages need an update
|
-- check if packages need an update
|
||||||
if date ~= config.packages then
|
if date ~= config.packages then
|
||||||
config.packages = date
|
config.packages = date
|
||||||
Config.update('version', config)
|
Config.update('version', config)
|
||||||
print('Updating packages')
|
print('Updating packages')
|
||||||
shell.run('package updateall')
|
shell.run('package updateall')
|
||||||
os.reboot()
|
os.reboot()
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(date) == 'string' and #date > 0 then
|
if type(date) == 'string' and #date > 0 then
|
||||||
if config.checked ~= today then
|
if config.checked ~= today then
|
||||||
config.checked = today
|
config.checked = today
|
||||||
Config.update('version', config)
|
Config.update('version', config)
|
||||||
print('Checking for new version')
|
print('Checking for new version')
|
||||||
pcall(function()
|
pcall(function()
|
||||||
local c = Util.httpGet(string.format(URL, _G.OPUS_BRANCH))
|
local c = Util.httpGet(string.format(URL, _G.OPUS_BRANCH))
|
||||||
if c then
|
if c then
|
||||||
local lines = Util.split(c)
|
local lines = Util.split(c)
|
||||||
local revdate = table.remove(lines, 1)
|
local revdate = table.remove(lines, 1)
|
||||||
if date ~= revdate and config.skip ~= revdate then
|
if date ~= revdate and config.skip ~= revdate then
|
||||||
config.current = revdate
|
config.current = revdate
|
||||||
config.details = table.concat(lines, '\n')
|
config.details = table.concat(lines, '\n')
|
||||||
Config.update('version', config)
|
Config.update('version', config)
|
||||||
print('New version available')
|
print('New version available')
|
||||||
if _ENV.multishell then
|
if _ENV.multishell then
|
||||||
shell.openForegroundTab('sys/apps/Version.lua')
|
shell.openForegroundTab('sys/apps/Version.lua')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,20 @@
|
||||||
local fs = _G.fs
|
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 })
|
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
|
||||||
|
|
|
@ -42,5 +42,5 @@ end
|
||||||
|
|
||||||
-- non-standard - will raise error instead
|
-- non-standard - will raise error instead
|
||||||
os.exit = function(code)
|
os.exit = function(code)
|
||||||
error('Terminated with ' .. code)
|
error(code)
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,41 +7,41 @@ local sub = string.sub
|
||||||
-- https://rosettacode.org/wiki/Jaro_distance (ported to lua)
|
-- https://rosettacode.org/wiki/Jaro_distance (ported to lua)
|
||||||
return function(s1, s2)
|
return function(s1, s2)
|
||||||
local l1, l2 = #s1, #s2;
|
local l1, l2 = #s1, #s2;
|
||||||
if l1 == 0 then
|
if l1 == 0 then
|
||||||
return l2 == 0 and 1.0 or 0.0
|
return l2 == 0 and 1.0 or 0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
local match_distance = max(floor(max(l1, l2) / 2) - 1, 0)
|
local match_distance = max(floor(max(l1, l2) / 2) - 1, 0)
|
||||||
local s1_matches = { }
|
local s1_matches = { }
|
||||||
local s2_matches = { }
|
local s2_matches = { }
|
||||||
local matches = 0
|
local matches = 0
|
||||||
|
|
||||||
for i = 1, l1 do
|
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
|
for k = max(1, i - match_distance), _end do
|
||||||
if not s2_matches[k] and sub(s1, i, i) == sub(s2, k, k) then
|
if not s2_matches[k] and sub(s1, i, i) == sub(s2, k, k) then
|
||||||
s1_matches[i] = true
|
s1_matches[i] = true
|
||||||
s2_matches[k] = true
|
s2_matches[k] = true
|
||||||
matches = matches + 1
|
matches = matches + 1
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if matches == 0 then
|
if matches == 0 then
|
||||||
return 0.0
|
return 0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
local t = 0.0
|
local t = 0.0
|
||||||
local k = 1
|
local k = 1
|
||||||
for i = 1, l1 do
|
for i = 1, l1 do
|
||||||
if s1_matches[i] then
|
if s1_matches[i] then
|
||||||
while not s2_matches[k] do
|
while not s2_matches[k] do
|
||||||
k = k + 1
|
k = k + 1
|
||||||
end
|
end
|
||||||
if sub(s1, i, i) ~= sub(s2, k, k) then
|
if sub(s1, i, i) ~= sub(s2, k, k) then
|
||||||
t = t + 0.5
|
t = t + 0.5
|
||||||
end
|
end
|
||||||
k = k + 1
|
k = k + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -51,6 +51,6 @@ return function(s1, s2)
|
||||||
b = b + .5
|
b = b + .5
|
||||||
end
|
end
|
||||||
|
|
||||||
local m = matches
|
local m = matches
|
||||||
return (m / l1 + m / l2 + (m - t) / m) / 3.0 + b
|
return (m / l1 + m / l2 + (m - t) / m) / 3.0 + b
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,10 @@ local function traceback(x)
|
||||||
return x
|
return x
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if x and x:match(':%d+: 0$') then
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
|
||||||
if debug_traceback then
|
if debug_traceback then
|
||||||
-- The parens are important, as they prevent a tail call occuring, meaning
|
-- The parens are important, as they prevent a tail call occuring, meaning
|
||||||
-- the stack level is preserved. This ensures the code behaves identically
|
-- the stack level is preserved. This ensures the code behaves identically
|
||||||
|
@ -65,7 +69,7 @@ local function trim_traceback(stack)
|
||||||
local t = { }
|
local t = { }
|
||||||
for _, line in pairs(trace) do
|
for _, line in pairs(trace) do
|
||||||
if not matchesFilter(line) then
|
if not matchesFilter(line) then
|
||||||
line = line:gsub("in function", "in")
|
line = line:gsub("in function", "in"):gsub('%w+/', '')
|
||||||
table.insert(t, line)
|
table.insert(t, line)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -84,9 +88,15 @@ return function (fn, ...)
|
||||||
if not res[1] and res[2] ~= nil then
|
if not res[1] and res[2] ~= nil then
|
||||||
local err, trace = trim_traceback(res[2])
|
local err, trace = trim_traceback(res[2])
|
||||||
|
|
||||||
_G._syslog('\n' .. err .. '\n' .. 'stack traceback:')
|
if #trace > 0 then
|
||||||
for _, v in ipairs(trace) do
|
_G._syslog('\n' .. err .. '\n' .. 'stack traceback:')
|
||||||
_G._syslog(v)
|
for _, v in ipairs(trace) do
|
||||||
|
_G._syslog(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if err:match(':%d+: 0$') then
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return res[1], err, trace
|
return res[1], err, trace
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue