diff --git a/ccemux/etc/apps.db b/ccemux/etc/apps.db index 081f9f7..d94fb3d 100644 --- a/ccemux/etc/apps.db +++ b/ccemux/etc/apps.db @@ -1,10 +1,10 @@ { - [ "emu_config" ] = { + [ "87e89abb4c1c551fe08d355d097f18b8de78edca5f556997085681662fce8eed" ] = { title = "Config", category = "CCEmuX", run = "emu config", }, - [ "emu_data" ] = { + [ "cec3a9b89b2e391393d0f68e4bc12a9fa6cf358b3cdf79496dc442d52b8dd528" ] = { title = "Data", category = "CCEmuX", run = "emu data", diff --git a/common/edit.lua b/common/edit.lua index e689700..3c6f667 100644 --- a/common/edit.lua +++ b/common/edit.lua @@ -1,4 +1,5 @@ -local UI = require('opus.ui') +local fuzzy = require('opus.fuzzy') +local UI = require('opus.ui') local colors = _G.colors local fs = _G.fs @@ -29,8 +30,6 @@ local color = { keywordColor = '4', commentColor = 'd', stringColor = 'e', - statusColor = colors.gray, - panelColor = colors.cyan, } if not term.isColor() then @@ -39,8 +38,6 @@ if not term.isColor() then keywordColor = '8', commentColor = '8', stringColor = '8', - statusColor = colors.white, - panelColor = colors.white, } end @@ -53,7 +50,6 @@ local keyMapping = { pageUp = 'pageUp', [ 'control-b' ] = 'pageUp', pageDown = 'pageDown', --- [ 'control-f' ] = 'pageDown', home = 'home', [ 'end' ] = 'toend', [ 'control-home' ] = 'top', @@ -95,13 +91,13 @@ local keyMapping = { -- copy/paste [ 'control-x' ] = 'cut', [ 'control-c' ] = 'copy', --- [ 'control-shift-paste' ] = 'paste_internal', -- file [ 'control-s' ] = 'save', [ 'control-S' ] = 'save_as', [ 'control-q' ] = 'exit', [ 'control-enter' ] = 'run', + [ 'control-p' ] = 'quick_open', -- search [ 'control-f' ] = 'find_prompt', @@ -114,19 +110,17 @@ local keyMapping = { } local page = UI.Page { - backgroundColor = color.panelColor, menuBar = UI.MenuBar { transitionHint = 'slideLeft', buttons = { { text = 'File', dropdown = { { text = 'New ', event = 'menu_action', action = 'file_new' }, { text = 'Open ', event = 'menu_action', action = 'file_open' }, + { text = 'Quick Open... ^p', event = 'menu_action', action = 'quick_open' }, { spacer = true }, { text = 'Save ^s', event = 'menu_action', action = 'save' }, { text = 'Save As... ^S', event = 'menu_action', action = 'save_as' }, { spacer = true }, - { text = 'Run', event = 'menu_action', action = 'run' }, - { spacer = true }, { text = 'Quit ^q', event = 'menu_action', action = 'exit' }, } }, { text = 'Edit', dropdown = { @@ -142,10 +136,11 @@ local page = UI.Page { } }, { text = 'Code', dropdown = { { text = 'Complete ^space', event = 'menu_action', action = 'autocomplete' }, + { text = 'Run ^enter', event = 'menu_action', action = 'run' }, } }, }, status = UI.Text { - textColor = color.statusColor, + textColor = colors.gray, x = -9, width = 9, align = 'right', }, @@ -247,7 +242,7 @@ local page = UI.Page { cancel = UI.Button { x = 16, text = 'Cancel', - backgroundColor = color.panelColor, + backgroundColor = UI.colors.primary, event = 'question_cancel', }, show = function(self, action) @@ -288,6 +283,107 @@ local page = UI.Page { return UI.FileSelect.eventHandler(self, event) end, }, + quick_open = UI.SlideOut { + filter_entry = UI.TextEntry { + x = 2, y = 2, ex = -2, + limit = 256, + shadowText = 'File name', + accelerators = { + [ 'enter' ] = 'accept', + [ 'up' ] = 'grid_up', + [ 'down' ] = 'grid_down', + }, + }, + grid = UI.ScrollingGrid { + x = 2, y = 4, ex = -2, ey = -4, + sortColumn = 'name', + columns = { + { heading = 'Name', key = 'name' }, + { heading = 'Dir', key = 'dir' }, + }, + accelerators = { + grid_select = 'accept', + }, + }, + cancel = UI.Button { + x = -9, y = -2, + text = 'Cancel', + event = 'quick_cancel', + }, + apply_filter = function(self, filter) + local t = { } + if filter then + filter = filter:lower() + self.grid.sortColumn = 'score' + self.grid.inverseSort = true + + for _,v in pairs(self.listing) do + v.score = fuzzy(v.lname, filter) + if v.score then + table.insert(t, v) + end + end + else + self.grid.sortColumn = 'name' + self.grid.inverseSort = false + t = self.listing + end + + self.grid:setValues(t) + self.grid:update() + self.grid:setIndex(1) + end, + show = function(self) + local listing = { } + local function recurse(dir) + local files = fs.native.list(dir) + for _,f in ipairs(files) do + local fullName = fs.combine(dir, f) + if fs.native.isDir(fullName) then + recurse(fullName) + else + table.insert(listing, { + name = f, + dir = dir, + lname = f:lower(), + fullName = '/' .. fullName, + }) + end + end + end + recurse('') + self.listing = listing + self:apply_filter() + self.filter_entry:reset() + UI.SlideOut.show(self) + 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 == 'quick_cancel' then + self:hide() + + elseif event.type == 'text_change' then + self:apply_filter(event.text) + self.grid:draw() + + else + return UI.SlideOut.eventHandler(self, event) + end + return true + end, + }, completions = UI.SlideOut { x = -12, y = 2, transitionHint = 'slideLeft', @@ -690,11 +786,19 @@ actions = { page.search:show() end, + quick_open = function(force) + if not force and undo.chain[#undo.chain] ~= lastSave then + page.unsaved:show('quick_open') + else + page.quick_open:show() + end + end, + file_open = function(force) if not force and undo.chain[#undo.chain] ~= lastSave then page.unsaved:show('file_open') else - page.file_open:show('file_open') + page.file_open:show() end end, @@ -1299,4 +1403,9 @@ if not actions.load(args[1] and args[1] or 'untitled.txt') then end UI:setPage(page) -UI:start() +local s, m = pcall(function() UI:start() end) +if not s then + actions.save('/crash.txt') + print('Editor has crashed. File saved as /crash.txt') + error(m) +end diff --git a/common/etc/apps.db b/common/etc/apps.db index da88fad..d8608bb 100644 --- a/common/etc/apps.db +++ b/common/etc/apps.db @@ -72,5 +72,10 @@ iconExt = "7\ ¨¨¨¨f€0¨\ ¨¨f€0¨¨f€", - } + }, + [ "3f00927a719345edd4a8316599d3b328857987547f8884306861161ffa09647e" ] = { + title = "Write", + category = "Apps", + run = "write", + }, } diff --git a/examples/.package b/examples/.package deleted file mode 100644 index da8c112..0000000 --- a/examples/.package +++ /dev/null @@ -1,6 +0,0 @@ -{ - title = 'Example programs for coding in Opus', - repository = 'kepler155c/opus-apps/{{OPUS_BRANCH}}/examples', - description = [[Starter/example programs for creating Opus programs.]], - license = 'MIT', -} diff --git a/examples/grid.lua b/examples/grid.lua deleted file mode 100644 index b979a87..0000000 --- a/examples/grid.lua +++ /dev/null @@ -1,44 +0,0 @@ -local UI = require('opus.ui') - -local page = UI.Page { - menuBar = UI.MenuBar { - buttons = { - { text = 'Shuffle', event = 'shuffle' }, - { text = 'Clear', event = 'clear', }, - } - }, - grid = UI.ScrollingGrid { - y = 2, ey = -2, - values = { - { col = 'column1', value = 'value1' }, - { col = 'column2', value = 'value2' }, - { col = 'column3', value = 'value3' }, - }, - columns = { - { heading = 'HDR1', key = 'col' }, - { heading = 'HDR2', key = 'value' }, - } - }, - statusBar = UI.StatusBar { }, -} - -function page:eventHandler(event) - if event.type == 'grid_select' then - self.statusBar:setStatus('Selected: ' .. event.selected.value) - - elseif event.type == 'shuffle' then - for _,v in pairs(self.grid.values) do - v.col = 'column' .. math.random(1,3) - end - self.grid:update() - self.grid:draw() - - elseif event.type == 'clear' then - self.grid:setValues({ }) - self.grid:draw() - end - return UI.Page.eventHandler(self, event) -end - -UI:setPage(page) -UI:pullEvents() diff --git a/milo/MiloRemote.lua b/milo/MiloRemote.lua index 6644a5b..c2dc4f1 100644 --- a/milo/MiloRemote.lua +++ b/milo/MiloRemote.lua @@ -1,6 +1,6 @@ local Config = require('opus.config') local Event = require('opus.event') -local fuzzy = require('milo.fuzzyMatch') +local fuzzy = require('opus.fuzzy') local Sound = require('opus.sound') local Socket = require('opus.socket') local sync = require('opus.sync').sync diff --git a/milo/apis/fuzzyMatch.lua b/milo/apis/fuzzyMatch.lua deleted file mode 100644 index 7a6082d..0000000 --- a/milo/apis/fuzzyMatch.lua +++ /dev/null @@ -1,19 +0,0 @@ --- Based on Squid's fuzzy search --- https://github.com/SquidDev-CC/artist/blob/vnext/artist/lib/match.lua --- --- not very fuzzy anymore - -local SCORE_WEIGHT = 1000 -local LEADING_LETTER_PENALTY = -3 -local LEADING_LETTER_PENALTY_MAX = -9 - -local _find = string.find -local _max = math.max - -return function(str, pattern) - local start = _find(str, pattern, 1, true) - if start then - -- All letters before the current one are considered leading, so add them to our penalty - return SCORE_WEIGHT + _max(LEADING_LETTER_PENALTY * (start - 1), LEADING_LETTER_PENALTY_MAX) - end -end diff --git a/milo/core/listing.lua b/milo/core/listing.lua index b19b4d2..994ceba 100644 --- a/milo/core/listing.lua +++ b/milo/core/listing.lua @@ -1,6 +1,6 @@ local Craft = require('milo.craft2') local Event = require('opus.event') -local fuzzy = require('milo.fuzzyMatch') +local fuzzy = require('opus.fuzzy') local Milo = require('milo') local Sound = require('opus.sound') local UI = require('opus.ui')