diff --git a/common/edit.lua b/common/edit.lua index bfc157a..54f5ba6 100644 --- a/common/edit.lua +++ b/common/edit.lua @@ -335,92 +335,23 @@ local page = UI.Page { return UI.SlideOut.eventHandler(self, event) end, }, - quick_open = UI.SlideOut { - filter_entry = UI.TextEntry { - x = 2, y = 2, ex = -2, - shadowText = 'File name', - accelerators = { - [ 'enter' ] = 'accept', - [ 'up' ] = 'grid_up', - [ 'down' ] = 'grid_down', - }, - }, - grid = UI.ScrollingGrid { - x = 2, y = 3, ex = -2, ey = -4, - disableHeader = true, - columns = { - { key = 'name' }, - { key = 'dir', textColor = 'lightGray' }, - }, - accelerators = { - grid_select = 'accept', - }, - }, - cancel = UI.Button { - x = -9, y = -2, - text = 'Cancel', - event = 'slide_hide', - }, - apply_filter = function(self, 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, + quick_open = UI.QuickSelect { + modal = true, + enable = function() end, show = function(self) - 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:apply_filter() - self.filter_entry:reset() - UI.SlideOut.show(self) + UI.QuickSelect.enable(self) + self:focusFirst() + self:draw() self:addTransition('expandUp', { easing = 'outBounce', ticks = 12 }) end, eventHandler = function(self, event) - if event.type == 'grid_up' then - self.grid:emit({ type = 'scroll_up' }) - - elseif event.type == 'grid_down' then - self.grid:emit({ type = 'scroll_down' }) - - elseif event.type == 'accept' then - local sel = self.grid:getSelected() - if sel then - actions.process('open', sel.fullName) - self:hide() - end - - elseif event.type == 'text_change' then - self:apply_filter(event.text) - self.grid:draw() - - else - return UI.SlideOut.eventHandler(self, event) + if event.type == 'select_cancel' then + self:disable() + elseif event.type == 'select_file' then + self:disable() + actions.process('open', event.file) end - return true + return UI.QuickSelect.eventHandler(self, event) end, }, completions = UI.SlideOut { diff --git a/debugger/.package b/debugger/.package new file mode 100644 index 0000000..b16807f --- /dev/null +++ b/debugger/.package @@ -0,0 +1,6 @@ +{ + title = 'Lua Debugger', + repository = 'kepler155c/opus-apps/{{OPUS_BRANCH}}/debugger', + description = [[Lua interactive debugger]], + license = 'MIT', +} \ No newline at end of file diff --git a/debugger/apis/init.lua b/debugger/apis/init.lua new file mode 100644 index 0000000..61ed024 --- /dev/null +++ b/debugger/apis/init.lua @@ -0,0 +1,201 @@ +--[[ +some portions from https://github.com/slembcke/debugger.lua +]] + +local fs = _G.fs + +local dbg = { } + +local function hookBreakpoint(info) + if dbg.breakpoints then + for _,v in pairs(dbg.breakpoints) do + if v.line == info.currentline and v.file == info.short_src then + return true + end + end + end +end + +local function hookFunction(fn) + return function(info) + return info.func == fn + end +end + +local function hookStep() + local co = coroutine.running() + return function() + return co == coroutine.running() + end +end + +local function hookStepStacksize(n) + local co = coroutine.running() + local i = 2 + while true do + local info = debug.getinfo(i) + if not info then + break + end + i = i + 1 + end + return function() + if co == coroutine.running() then + if not debug.getinfo(i - n) then + return true + end + end + end +end + +local function hookStepOut() + return hookStepStacksize(1) +end + +local function hookStepOver() + return hookStepStacksize(0) +end + +local hookEval = function() end + +-- Create a table of all the locally accessible variables. +-- Globals are not included when running the locals command +local function local_bindings(offset, stack_inspect_offset) + offset = offset + 1 + stack_inspect_offset -- add this function to the offset + local func = debug.getinfo(offset).func + local bindings = {} + + -- Retrieve the upvalues + do local i = 1; while true do + local name, value = debug.getupvalue(func, i) + if not name then break end + bindings[name] = value + i = i + 1 + end end + + -- Retrieve the locals (overwriting any upvalues) + do local i = 1; while true do + local name, value = debug.getlocal(offset, i) + if not name then break end + bindings[name] = value + i = i + 1 + end end + + -- Retrieve the varargs (works in Lua 5.2 and LuaJIT) + local varargs = {} + do local i = 1; while true do + local name, value = debug.getlocal(offset, -i) + if not name then break end + varargs[i] = value + i = i + 1 + end end + if #varargs > 0 then bindings["..."] = varargs end + + return bindings +end + +local function get_trace(offset, stack_inspect_offset) + local function format_loc(file, line) return file..":"..line end + local function format_stack_frame_info(info) + local filename = info.source:match("@(.*)") + local source = filename and fs.getName(filename) or info.short_src + local namewhat = (info.namewhat == "" and "chunk at" or info.namewhat) + local name = (info.name and "'"..info.name.."'" or format_loc(source, info.linedefined)) + return format_loc(source, info.currentline).." in "..namewhat.." "..name + end + + offset = offset + 1 -- add this function to the offset + local t = { } + local i = 0 + while true do + local info = debug.getinfo(offset + i) + if not info then break end + t[i] = { + index = i, + current = (i == stack_inspect_offset), + desc = format_stack_frame_info(info), + info = info, + } + i = i + 1 + end + + return t +end + +local inHook = false + +local function hook() + local info = debug.getinfo(2) + if info.currentline < 0 then + return + end + if not inHook and hookEval(info) then + inHook = true + + local offset = 2 -- the offset from this function to the code being debugged + local inspectOffset = 0 + + repeat + local done = true + local snapshot = { + info = debug.getinfo(offset + inspectOffset), + locals = local_bindings(offset, inspectOffset), + stack = get_trace(offset, inspectOffset), + } + + inspectOffset = 0 -- reset + + local cmd, param = dbg.read(snapshot) + if cmd == 's' then + hookEval = hookStep() + elseif cmd == 'n' then + hookEval = hookStepOver() + elseif cmd == 'f' then + hookEval = hookStepOut() + elseif cmd == 'c' then + hookEval = hookBreakpoint + elseif cmd == 'd' then -- detach + debug.sethook() + elseif cmd == 'q' then + os.exit(0) + elseif cmd == 'b' then + dbg.breakpoints = param + done = false + elseif cmd == 'i' then + -- inspect stack at this offset + inspectOffset = param + done = false + end + until done + + inHook = false + end +end + +debug.sethook(hook, 'l') + +-- Expose the debugger's functions +dbg.hook = hook +dbg.exit = function(err) os.exit(err) end +dbg.stopIn = function(fn) + hookEval = hookFunction(fn) +end +dbg.debugger = nil + +dbg.read = function(info) + _G._pinfo = info + + os.sleep(0) -- this is important ... + dbg.debugger:resume('debugger', 'info', info) + + while true do + local _, cmd, args = os.pullEvent('debugger') + if cmd == 'b' then + dbg.breakpoints = args + else + return cmd, args + end + end +end + +return dbg diff --git a/debugger/debug.lua b/debugger/debug.lua new file mode 100644 index 0000000..1e2cdcd --- /dev/null +++ b/debugger/debug.lua @@ -0,0 +1,407 @@ +local Config = require('opus.config') +local Event = require('opus.event') +local UI = require('opus.ui') +local Util = require('opus.util') + +local fs = _G.fs +local getfenv = _G.getfenv +local kernel = _G.kernel +local multishell = _ENV.multishell +local shell = _ENV.shell + +local args = { ... } +local filename = shell.resolveProgram(table.remove(args, 1)) + +if not filename then + error('file not found') +end + +local config = Config.load('debugger') +if not config.filename then + config.filename = { } +end + +local breakpoints = config.filename +local currentFile +local debugFile, debugLine + +local debugger = kernel.getCurrent() +local client + +local function startClient() + local env = kernel.makeEnv(_ENV) + + local clientId = multishell.openTab(nil, { + env = env, + title = fs.getName(filename):match('([^%.]+)'), + args = args, + fn = function(...) + local dbg = require('debugger') + local fn = loadfile(filename, env) + + local cocreate = coroutine.create + env.coroutine = require('opus.util').shallowCopy(coroutine) + env.coroutine.create = function(f, ...) + local co = cocreate(f, ...) + debug.sethook(co, dbg.hook, "l") + return co + end + + dbg.debugger = debugger + dbg.breakpoints = breakpoints + dbg.stopIn(fn) + fn(...) + end, + }) + client = kernel.find(clientId) +end + +local function loadSource(file) + currentFile = file:match('@?(.*)') + local src = { } + local lines = Util.readLines(file:match('@?(.*)')) + + if lines then + for i = 1, #lines do + table.insert(src, { line = i, source = lines[i] }) + end + end + + return src +end + +local function message(...) + client:resume('debugger', ...) +end + +local page = UI.Page { + menuBar = UI.MenuBar { + buttons = { + { text = 'Continue', event = 'cmd', cmd = 'c' }, + { text = 'Step', event = 'cmd', cmd = 's' }, + { text = 'Step Over', event = 'cmd', cmd = 'n' }, + { text = 'Step Out', event = 'cmd', cmd = 'f' }, + { text = 'Restart', event = 'restart', width = 9, ex = -1 }, + }, + }, + + container = UI.Window { + y = 2, ey = '50%', + locals = UI.ScrollingGrid { + ey = -2, + disableHeader = true, + columns = { + { heading = 'Key', key = 'name' }, + { heading = 'Value', key = 'value', textColor = 'yellow' }, + }, + --sortColumn = 'name', + autospace = true, + accelerators = { + grid_select = 'show_variable', + }, + }, + statusBar = UI.StatusBar { + ex = -7, y = -1, + backgroundColor = 'primary', + textColor = 'white', + }, + UI.Button { + y = -1, x = -6, + event = 'open', + text = 'Open', + } + }, + + tabs = UI.Tabs { + y = '50%', + source = UI.Tab { + title = 'Source', + index = 1, + grid = UI.ScrollingGrid { + disableHeader = true, + columns = { + { key = 'marker', width = 1 }, + { key = 'line', textColor = 'cyan', width = 4 }, + { heading = 'heading', key = 'source' }, + }, + getDisplayValues = function(_, row) + for _,v in pairs(breakpoints) do + if v.file == currentFile and v.line == row.line then + return { + marker = '!', + line = row.line, + source = row.source, + } + end + end + return row + end, + getRowTextColor = function(self, row, selected) + return row.line == debugLine and currentFile == debugFile and 'yellow' + or UI.Grid.getRowTextColor(self, row, selected) + end, + eventHandler = function(self, event) + if event.type == 'grid_select' then + self:emit({ + type = 'toggle_breakpoint', + file = currentFile, + line = event.selected.line, + }) + end + return UI.Grid.eventHandler(self, event) + end, + }, + }, + + stack = UI.Tab { + title = 'Stack', + index = 3, + grid = UI.ScrollingGrid { + columns = { + { key = 'index', width = 2 }, + { heading = 'heading', key = 'desc' }, + }, + getRowTextColor = function(self, row, selected) + return row.current and 'yellow' + or UI.Grid.getRowTextColor(self, row, selected) + end, + sortColumn = 'index', + }, + eventHandler = function(self, event) + if event.type == 'grid_select' then + message('r', event.selected.index) + else + return UI.Grid.eventHandler(self, event) + end + end, + }, + + env = UI.Tab { + title = 'Env', + index = 4, + grid = UI.ScrollingGrid { + columns = { + { heading = 'Key', key = 'name' }, + { heading = 'Value', key = 'value', textColor = 'yellow' }, + }, + autospace = true, + accelerators = { + grid_select = 'show_variable', + }, + sortCompare = function() end, + }, + }, + + breaks = UI.Tab { + title = 'Breakpoints', + index = 2, + menuBar = UI.MenuBar { + buttons = { + { text = 'Toggle', event = 'toggle' }, + { text = 'Remove', event = 'remove' }, + { text = 'Clear', event = 'clear' }, + }, + }, + grid = UI.ScrollingGrid { + y = 2, + columns = { + { heading = 'Line', key = 'line', width = 5 }, + { heading = 'Name', key = 'short' }, + { heading = 'Path', key = 'path', textColor = 'lightGray' }, + }, + values = breakpoints, + autospace = true, + getRowTextColor = function(self, row, selected) + return row.disabled and 'lightGray' + or UI.Grid.getRowTextColor(self, row, selected) + end, + }, + eventHandler = function(self, event) + if event.type == 'clear' then + Util.clear(self.grid.values) + self:emit({ type = 'update_breakpoints' }) + + elseif event.type == 'toggle' then + local bp = self.grid:getSelected() + if bp then + bp.disabled = not bp.disabled + self:emit({ type = 'update_breakpoints' }) + end + + elseif event.type == 'grid_select' then + self:emit({ + type = 'open_file', + file = event.selected.file, + line = event.selected.line, + }) + + elseif event.type == 'remove' then + local bp = self.grid:getSelected() + if bp then + Util.removeByValue(self.grid.values, bp) + self:emit({ type = 'update_breakpoints' }) + end + + end + return UI.Tab.eventHandler(self, event) + end, + }, + }, + + quick_open = UI.QuickSelect { + modal = true, + enable = function() end, + show = function(self) + UI.QuickSelect.enable(self) + self:focusFirst() + self:draw() + self:addTransition('expandUp', { easing = 'outBounce', ticks = 12 }) + end, + eventHandler = function(self, event) + if event.type == 'select_cancel' then + self:disable() + elseif event.type == 'select_file' then + self.parent:openFile(event.file) + self:disable() + end + return UI.QuickSelect.eventHandler(self, event) + end, + }, + + openFile = function(self, file, line) + if file ~= currentFile then + local src = loadSource(file) + self.tabs.source.grid:setValues(src) + end + if line then + self.tabs.source.grid:setIndex(#self.tabs.source.grid.values) + self.tabs.source.grid:setIndex(math.max(1, line - 4)) + end + self.tabs.source.grid:setIndex(line or 1) + self.tabs:selectTab(self.tabs.source) + + if currentFile == debugFile then + self.container.statusBar:setStatus( + string.format('%s : %d', fs.getName(file), debugLine)) + else + self.container.statusBar:setStatus(fs.getName(file)) + end + self:draw() + end, + eventHandler = function(self, event) + if event.type == 'cmd' then + self.container.statusBar:setStatus('Running...') + message(event.element.cmd) + + elseif event.type == 'restart' then + if kernel.find(client.uid) then + client:resume('terminate') + end + startClient() + + elseif event.type == 'open' then + self.quick_open:show() + + elseif event.type == 'open_file' then + self:openFile(event.file, event.line) + + elseif event.type == 'update_breakpoints' then + self.tabs.breaks.grid:update() + self.tabs.breaks.grid:draw() + self.tabs.source.grid:draw() + message('b', breakpoints) + Config.update('debugger', config) + + elseif event.type == 'toggle_breakpoint' then + for k,v in pairs(breakpoints) do + if v.file == event.file and v.line == event.line then + table.remove(breakpoints, k) + self:emit({ type = 'update_breakpoints' }) + return + end + end + + table.insert(breakpoints, { + file = event.file, + line = event.line, + short = fs.getName(event.file), + path = fs.getDir(event.file), + }) + + self:emit({ type = 'update_breakpoints' }) + + elseif event.type == 'show_variable' then + if type(event.selected.raw) == 'table' then + if event.selected.children then + event.selected.children = nil + else + event.selected.children = { } + local t = event.selected.raw + for k,v in pairs(t) do + local depth = event.selected.depth or 0 + table.insert(event.selected.children, + { name = (' '):rep(depth + 2) .. k, value = tostring(v), raw = v, depth = depth + 2 }) + end + table.sort(event.selected.children, function(a, b) return a.name < b.name end) + end + local t = { } + local function insert(values) + for _,v in pairs(values) do + table.insert(t, v) + if v.children then + insert(v.children) + end + end + end + insert(event.element.orig) + event.element:setValues(t) + event.element:draw() + end + end + return UI.Page.eventHandler(self, event) + end, + enable = function(self) + UI.Page.enable(self) + startClient() + end, +} + +Event.on('debugger', function(_, cmd, data) + if cmd == 'info' then + kernel.raise(debugger.uid) + + -- local tab + local t = { } + for k,v in pairs(data.locals or { }) do + table.insert(t, { name = k, value = tostring(v), raw = v }) + end + table.sort(t, function(a, b) return a.name < b.name end) + page.container.locals:setValues(t) + page.container.locals.orig = Util.shallowCopy(t) + + -- env tab + t = { } + for k,v in pairs(getfenv(data.info.func)) do + table.insert(t, { name = k, value = tostring(v), raw = v }) + end + page.tabs.env.grid:setValues(t) + page.tabs.env.grid.orig = Util.shallowCopy(t) + + debugLine = data.info.currentline + debugFile = data.info.source:match('@?(.*)') + + -- source tab + page:openFile(debugFile, debugLine) + + -- stack + page.tabs.stack.grid:setValues(data.stack) + + page:draw() + page:sync() + end +end) + +UI:setPage(page) +UI:start() + +message('d') diff --git a/debugger/example.lua b/debugger/example.lua new file mode 100644 index 0000000..7743808 --- /dev/null +++ b/debugger/example.lua @@ -0,0 +1,28 @@ +local function m2(a) + return a +end + +local function method(times) + local a = 2 + -- use step out to return out of method + for _ = 1, times do + a = a * a + end + return m2(a) +end + +print('before') +-- breakpoint +--dbg() +print('after') + +local i = 2 +print(i) +local res = method(i) + +dofile("rom/modules/main/cc/expect.lua") + +print(res) +print('result: ' .. res) + +error('f') diff --git a/lzwfs/lzwfs.lua b/lzwfs/lzwfs.lua index 382bd7a..bad922a 100644 --- a/lzwfs/lzwfs.lua +++ b/lzwfs/lzwfs.lua @@ -19,9 +19,9 @@ local SIGC = 'LZWC' local basedictcompress = {} local basedictdecompress = {} for i = 0, 255 do - local ic, iic = char(i), char(i, 0) - basedictcompress[ic] = iic - basedictdecompress[iic] = ic + local ic, iic = char(i), char(i, 0) + basedictcompress[ic] = iic + basedictdecompress[iic] = ic end local native = { open = fs.open } @@ -29,123 +29,123 @@ local enabled = false local filters = { } local function dictAddA(str, dict, a, b) - if a >= 256 then - a, b = 0, b+1 - if b >= 256 then - dict = {} - b = 1 - end - end - dict[str] = char(a,b) - a = a+1 - return dict, a, b + if a >= 256 then + a, b = 0, b+1 + if b >= 256 then + dict = {} + b = 1 + end + end + dict[str] = char(a,b) + a = a+1 + return dict, a, b end local function compress(input) - if type(input) ~= "string" then - error ("string expected, got "..type(input)) - end - local len = #input - if len <= 1 then - return input - end + if type(input) ~= "string" then + error ("string expected, got "..type(input)) + end + local len = #input + if len <= 1 then + return input + end - local dict = {} - local a, b = 0, 1 + local dict = {} + local a, b = 0, 1 - local result = { SIGC } - local resultlen = 1 - local n = 2 - local word = "" - for i = 1, len do - local c = sub(input, i, i) - local wc = word..c - if not (basedictcompress[wc] or dict[wc]) then - local write = basedictcompress[word] or dict[word] - if not write then - error "algorithm error, could not fetch word" - end - result[n] = write - resultlen = resultlen + #write - n = n+1 - if len <= resultlen then - return input - end - dict, a, b = dictAddA(wc, dict, a, b) - word = c - else - word = wc - end - end - result[n] = basedictcompress[word] or dict[word] - resultlen = resultlen+#result[n] - if len <= resultlen then - return input - end - return tconcat(result) + local result = { SIGC } + local resultlen = 1 + local n = 2 + local word = "" + for i = 1, len do + local c = sub(input, i, i) + local wc = word..c + if not (basedictcompress[wc] or dict[wc]) then + local write = basedictcompress[word] or dict[word] + if not write then + error "algorithm error, could not fetch word" + end + result[n] = write + resultlen = resultlen + #write + n = n+1 + if len <= resultlen then + return input + end + dict, a, b = dictAddA(wc, dict, a, b) + word = c + else + word = wc + end + end + result[n] = basedictcompress[word] or dict[word] + resultlen = resultlen+#result[n] + if len <= resultlen then + return input + end + return tconcat(result) end local function dictAddB(str, dict, a, b) - if a >= 256 then - a, b = 0, b+1 - if b >= 256 then - dict = {} - b = 1 - end - end - dict[char(a,b)] = str - a = a+1 - return dict, a, b + if a >= 256 then + a, b = 0, b+1 + if b >= 256 then + dict = {} + b = 1 + end + end + dict[char(a,b)] = str + a = a+1 + return dict, a, b end local function decompress(input) - if type(input) ~= "string" then - error( "string expected, got "..type(input)) - end + if type(input) ~= "string" then + error( "string expected, got "..type(input)) + end - if #input <= 1 then - return input - end + if #input <= 1 then + return input + end - local control = sub(input, 1, 4) - if control ~= SIGC then - return input - end - input = sub(input, 5) - local len = #input + local control = sub(input, 1, 4) + if control ~= SIGC then + return input + end + input = sub(input, 5) + local len = #input - if len < 2 then - error("invalid input - not a compressed string") - end + if len < 2 then + error("invalid input - not a compressed string") + end - local dict = {} - local a, b = 0, 1 + local dict = {} + local a, b = 0, 1 - local result = {} - local n = 1 - local last = sub(input, 1, 2) - result[n] = basedictdecompress[last] or dict[last] - n = n+1 - for i = 3, len, 2 do - local code = sub(input, i, i+1) - local lastStr = basedictdecompress[last] or dict[last] - if not lastStr then - error( "could not find last from dict. Invalid input?") - end - local toAdd = basedictdecompress[code] or dict[code] - if toAdd then - result[n] = toAdd - n = n+1 - dict, a, b = dictAddB(lastStr..sub(toAdd, 1, 1), dict, a, b) - else - local tmp = lastStr..sub(lastStr, 1, 1) - result[n] = tmp - n = n+1 - dict, a, b = dictAddB(tmp, dict, a, b) - end - last = code - end - return tconcat(result) + local result = {} + local n = 1 + local last = sub(input, 1, 2) + result[n] = basedictdecompress[last] or dict[last] + n = n+1 + for i = 3, len, 2 do + local code = sub(input, i, i+1) + local lastStr = basedictdecompress[last] or dict[last] + if not lastStr then + error( "could not find last from dict. Invalid input?") + end + local toAdd = basedictdecompress[code] or dict[code] + if toAdd then + result[n] = toAdd + n = n+1 + dict, a, b = dictAddB(lastStr..sub(toAdd, 1, 1), dict, a, b) + else + local tmp = lastStr..sub(lastStr, 1, 1) + result[n] = tmp + n = n+1 + dict, a, b = dictAddB(tmp, dict, a, b) + end + last = code + end + return tconcat(result) end local function split(str, pattern) @@ -157,39 +157,39 @@ local function split(str, pattern) end local function matchesFilter(fname) - if not fname:find('lzwfs') then -- don't compress anything with lzwfs in name (sigh) - for _, filter in pairs(filters) do - if fname:match(filter) then - return true - end - end - end + if not fname:find('lzwfs') then -- don't compress anything with lzwfs in name (sigh) + for _, filter in pairs(filters) do + if fname:match(filter) then + return true + end + end + end end function fs.open(fname, flags) - if not enabled then - return native.open(fname, flags) - end + if not enabled then + return native.open(fname, flags) + end - if flags == 'r' then - local f, err = native.open(fname, 'rb') - if not f then - return f, err - end + if flags == 'r' then + local f, err = native.open(fname, 'rb') + if not f then + return f, err + end local ctr = 0 local lines return { - read = function() - if not lines then - lines = decompress(f.readAll()) - end - ctr = ctr + 1 - return lines:sub(ctr, ctr) - end, - readLine = function() + read = function() if not lines then - lines = split(decompress(f.readAll())) + lines = decompress(f.readAll()) + end + ctr = ctr + 1 + return lines:sub(ctr, ctr) + end, + readLine = function() + if not lines then + lines = split(decompress(f.readAll())) end ctr = ctr + 1 return lines[ctr] @@ -197,61 +197,61 @@ function fs.open(fname, flags) readAll = function() return decompress(f.readAll()) end, - close = function() - f.close() - end, - } - elseif flags == 'w' or flags == 'a' then - if not matchesFilter(fs.combine(fname, '')) then - return native.open(fname, flags) - end - - local c = { } - - if flags == 'a' then - local f = fs.open(fname, 'r') - if f then - tinsert(c, f.readAll()) - f.close() - end - end - - local f, err = native.open(fname, 'wb') - if not f then - return f, err - end - - return { - write = function(str) - tinsert(c, str) - end, - writeLine = function(str) - tinsert(c, str) - tinsert(c, '\n') - end, - flush = function() - -- this isn't gonna work... - -- f.write(compress(tconcat(c))) - f.flush(); - end, - close = function() - f.write(compress(tconcat(c))) - f.close() + close = function() + f.close() end, } - end + elseif flags == 'w' or flags == 'a' then + if not matchesFilter(fs.combine(fname, '')) then + return native.open(fname, flags) + end - return native.open(fname, flags) + local c = { } + + if flags == 'a' then + local f = fs.open(fname, 'r') + if f then + tinsert(c, f.readAll()) + f.close() + end + end + + local f, err = native.open(fname, 'wb') + if not f then + return f, err + end + + return { + write = function(str) + tinsert(c, str) + end, + writeLine = function(str) + tinsert(c, str) + tinsert(c, '\n') + end, + flush = function() + -- this isn't gonna work... + -- f.write(compress(tconcat(c))) + f.flush(); + end, + close = function() + f.write(compress(tconcat(c))) + f.close() + end, + } + end + + return native.open(fname, flags) end function fs.option(category, action, option) - if category == 'compression' then - if action == 'enabled' then - enabled = option - elseif action == 'filters' then - filters = option - end - end + if category == 'compression' then + if action == 'enabled' then + enabled = option + elseif action == 'filters' then + filters = option + end + end end print('lzwfs started') diff --git a/lzwfs/startup.lua b/lzwfs/startup.lua index 03a21c6..e8fa675 100644 --- a/lzwfs/startup.lua +++ b/lzwfs/startup.lua @@ -6,11 +6,11 @@ local CONFIG = 'usr/config/lzwfs' local config = { } if fs.exists(CONFIG) then - local f = fs.open(CONFIG, 'r') + local f = fs.open(CONFIG, 'r') if f then config = textutils.unserialize(f.readAll()) f.close() - end + end end os.run(_ENV, '/packages/lzwfs/lzwfs.lua') diff --git a/mbs/autorun/startup.lua b/mbs/autorun/startup.lua index 8ff9e9a..098c671 100644 --- a/mbs/autorun/startup.lua +++ b/mbs/autorun/startup.lua @@ -3,7 +3,7 @@ local shell = _ENV.shell if not fs.exists('.mbs') then print('Installing MBS') - shell.run('mbs download') + --shell.run('mbs download') end print('Initializing MBS') -shell.run('mbs startup') +--shell.run('mbs startup') diff --git a/minify/minifyDir.lua b/minify/minifyDir.lua index 8aa6932..4b307e9 100644 --- a/minify/minifyDir.lua +++ b/minify/minifyDir.lua @@ -2,24 +2,24 @@ local fs = _G.fs local shell = _ENV.shell local function recurse(path) - if fs.isDir(path) then - for _, v in pairs(fs.listEx(path)) do - if not v.isReadOnly then - recurse(fs.combine(path, v.name)) - end - end - elseif path:match('%.lua$') and not fs.isReadOnly(path) then - local sz = fs.getSize(path) - shell.run('minify.lua minify ' .. path) - print(string.format('%s : %.2f%%', path, (sz - fs.getSize(path)) / sz * 100)) - end + if fs.isDir(path) then + for _, v in pairs(fs.listEx(path)) do + if not v.isReadOnly then + recurse(fs.combine(path, v.name)) + end + end + elseif path:match('%.lua$') and not fs.isReadOnly(path) then + local sz = fs.getSize(path) + shell.run('minify.lua minify ' .. path) + print(string.format('%s : %.2f%%', path, (sz - fs.getSize(path)) / sz * 100)) + end end local path = ({ ... })[1] or error('Syntax: minifyDir PATH') path = fs.combine(path, '') if not fs.isDir(path) then - error('Invalid path') + error('Invalid path') end recurse(path) diff --git a/neural/Equipment.lua b/neural/Equipment.lua index 32b849e..df782bd 100644 --- a/neural/Equipment.lua +++ b/neural/Equipment.lua @@ -16,12 +16,12 @@ UI:configure('Equipment', ...) local equipment = device.neuralInterface.getEquipment() local slots = { - 'primary', - 'offhand', - 'boots', - 'leggings', - 'chest', - 'helmet', + 'primary', + 'offhand', + 'boots', + 'leggings', + 'chest', + 'helmet', } local page = UI.Page { @@ -34,29 +34,29 @@ local page = UI.Page { grid = UI.Grid { y = 2, columns = { - { heading = 'Slot', key = 'index', width = 7 }, + { heading = 'Slot', key = 'index', width = 7 }, { heading = 'Name', key = 'displayName' }, { heading = 'Count', key = 'count', width = 5, align = 'right' }, }, - sortColumn = 'index', - accelerators = { - grid_select = 'show_detail', - }, - getDisplayValues = function(_, row) - row = Util.shallowCopy(row) - if row.name then - local item = itemDB:get( - table.concat({ row.name, row.damage, row.nbtHash }, ':'), - function() - return equipment.getItemMeta(row.index) - end) - row.displayName = item.displayName - else - row.displayName = 'empty' - end - row.index = slots[row.index] - return row - end, + sortColumn = 'index', + accelerators = { + grid_select = 'show_detail', + }, + getDisplayValues = function(_, row) + row = Util.shallowCopy(row) + if row.name then + local item = itemDB:get( + table.concat({ row.name, row.damage, row.nbtHash }, ':'), + function() + return equipment.getItemMeta(row.index) + end) + row.displayName = item.displayName + else + row.displayName = 'empty' + end + row.index = slots[row.index] + return row + end, }, accelerators = { [ 'control-q' ] = 'quit', @@ -77,58 +77,58 @@ local page = UI.Page { accelerators = { grid_select = 'inspect', }, - }, - show = function(self, slot) - local detail = equipment.getItemMeta(slot.index) - local t = { } - for k,v in pairs(detail) do - table.insert(t, { - name = k, - value = v, - }) - end - self.grid:setValues(t) - self.grid:setIndex(1) - UI.SlideOut.show(self) - end, - }, - enable = function(self) - self:refresh() - UI.Page.enable(self) - end, - refresh = function(self) - local t = { } - local list = equipment.list() - for i = 1, equipment.size() do - local v = list[i] or { } - v.index = i - table.insert(t, v) - end - self.grid:setValues(t) - self.grid:draw() - end, - eventHandler = function(self, event) - if event.type == 'quit' then - UI:quit() + }, + show = function(self, slot) + local detail = equipment.getItemMeta(slot.index) + local t = { } + for k,v in pairs(detail) do + table.insert(t, { + name = k, + value = v, + }) + end + self.grid:setValues(t) + self.grid:setIndex(1) + UI.SlideOut.show(self) + end, + }, + enable = function(self) + self:refresh() + UI.Page.enable(self) + end, + refresh = function(self) + local t = { } + local list = equipment.list() + for i = 1, equipment.size() do + local v = list[i] or { } + v.index = i + table.insert(t, v) + end + self.grid:setValues(t) + self.grid:draw() + end, + eventHandler = function(self, event) + if event.type == 'quit' then + UI:quit() - elseif event.type == 'show_detail' then - if event.selected.name then - self.detail:show(event.selected) - end + elseif event.type == 'show_detail' then + if event.selected.name then + self.detail:show(event.selected) + end - elseif event.type == 'drop' then - local selected = self.grid:getSelected() - equipment.drop(selected.index) - self:refresh() + elseif event.type == 'drop' then + local selected = self.grid:getSelected() + equipment.drop(selected.index) + self:refresh() - elseif event.type == 'suck' then - local selected = self.grid:getSelected() - equipment.suck(selected.index) - self:refresh() - end + elseif event.type == 'suck' then + local selected = self.grid:getSelected() + equipment.suck(selected.index) + self:refresh() + end - UI.Page.eventHandler(self, event) - end, + UI.Page.eventHandler(self, event) + end, } Event.onInterval(1, function() diff --git a/packages.list b/packages.list index b674e1a..41bbf6a 100644 --- a/packages.list +++ b/packages.list @@ -4,6 +4,7 @@ [ 'ccemux' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/ccemux/.package', [ 'common' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/common/.package', [ 'core' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/core/.package', + [ 'debugger' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/debugger/.package', [ 'farms' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/farms/.package', -- [ 'forestry' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/forestry/.package', [ 'games' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/games/.package', @@ -11,7 +12,7 @@ [ 'gps' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/gps/.package', [ 'lfs' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/lfs/.package', [ 'lzwfs' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/lzwfs/.package', - [ 'mbs' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/mbs/.package', +-- [ 'mbs' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/mbs/.package', [ 'milo' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/milo/.package', [ 'miloApps' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/miloApps/.package', [ 'miners' ] = 'https://raw.githubusercontent.com/kepler155c/opus-apps/develop-1.8/miners/.package',