mirror of
https://github.com/kepler155c/opus
synced 2024-12-28 17:40:26 +00:00
better fuzzy matching + vfs type flag in Files
This commit is contained in:
parent
b93d69c261
commit
985830fcfd
@ -77,8 +77,8 @@ local Browser = UI.Page {
|
||||
grid = UI.ScrollingGrid {
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'name' },
|
||||
{ key = 'flags', width = 2 },
|
||||
{ heading = 'Size', key = 'fsize', width = 5 },
|
||||
{ key = 'flags', width = 3, textColor = 'lightGray' },
|
||||
{ heading = 'Size', key = 'fsize', width = 5, textColor = 'yellow' },
|
||||
},
|
||||
sortColumn = 'name',
|
||||
y = 2, ey = -2,
|
||||
@ -211,7 +211,7 @@ function Browser:enable()
|
||||
self:setFocus(self.grid)
|
||||
end
|
||||
|
||||
function Browser.menuBar:getActive(menuItem)
|
||||
function Browser.menuBar.getActive(_, menuItem)
|
||||
local file = Browser.grid:getSelected()
|
||||
if menuItem.flags == FILE then
|
||||
return file and not file.isDir
|
||||
@ -223,7 +223,7 @@ function Browser:setStatus(status, ...)
|
||||
self.notification:info(string.format(status, ...))
|
||||
end
|
||||
|
||||
function Browser:unmarkAll()
|
||||
function Browser.unmarkAll()
|
||||
for _,m in pairs(marked) do
|
||||
m.marked = false
|
||||
end
|
||||
@ -263,10 +263,11 @@ function Browser:updateDirectory(dir)
|
||||
dir.size = #files
|
||||
for _, file in pairs(files) do
|
||||
file.fullName = fs.combine(dir.name, file.name)
|
||||
file.flags = ''
|
||||
file.flags = file.fstype or ' '
|
||||
if not file.isDir then
|
||||
dir.totalSize = dir.totalSize + file.size
|
||||
file.fsize = formatSize(file.size)
|
||||
file.flags = file.flags .. ' '
|
||||
else
|
||||
if config.showDirSizes then
|
||||
file.size = fs.getSize(file.fullName, true)
|
||||
@ -274,11 +275,9 @@ function Browser:updateDirectory(dir)
|
||||
dir.totalSize = dir.totalSize + file.size
|
||||
file.fsize = formatSize(file.size)
|
||||
end
|
||||
file.flags = 'D'
|
||||
end
|
||||
if file.isReadOnly then
|
||||
file.flags = file.flags .. 'R'
|
||||
file.flags = file.flags .. 'D'
|
||||
end
|
||||
file.flags = file.flags .. (file.isReadOnly and 'R' or ' ')
|
||||
if config.showHidden or file.name:sub(1, 1) ~= '.' then
|
||||
dir.files[file.fullName] = file
|
||||
end
|
||||
@ -467,7 +466,7 @@ function Browser:eventHandler(event)
|
||||
|
||||
elseif event.type == 'paste' then
|
||||
for _,m in pairs(copied) do
|
||||
local s, m = pcall(function()
|
||||
pcall(function()
|
||||
if cutMode then
|
||||
fs.move(m.fullName, fs.combine(self.dir.name, m.name))
|
||||
else
|
||||
|
@ -1,3 +1,4 @@
|
||||
local fuzzy = require('opus.fuzzy')
|
||||
local UI = require('opus.ui')
|
||||
local Util = require('opus.util')
|
||||
|
||||
@ -42,13 +43,13 @@ UI:addPage('main', UI.Page {
|
||||
|
||||
elseif event.type == 'text_change' then
|
||||
if not event.text then
|
||||
self.grid.values = topics
|
||||
self.grid.sortColumn = 'lname'
|
||||
else
|
||||
self.grid.values = { }
|
||||
for _,f in pairs(topics) do
|
||||
if string.find(f.lname, event.text:lower()) then
|
||||
table.insert(self.grid.values, f)
|
||||
end
|
||||
self.grid.sortColumn = 'score'
|
||||
self.grid.inverseSort = false
|
||||
local pattern = event.text:lower()
|
||||
for _,v in pairs(self.grid.values) do
|
||||
v.score = -fuzzy(v.lname, pattern)
|
||||
end
|
||||
end
|
||||
self.grid:update()
|
||||
|
@ -41,7 +41,7 @@ local page = UI.Page {
|
||||
},
|
||||
description = UI.TextArea {
|
||||
x = 16, y = 3, ey = -5,
|
||||
marginRight = 0, marginLeft = 0,
|
||||
marginRight = 2, marginLeft = 0,
|
||||
},
|
||||
action = UI.SlideOut {
|
||||
titleBar = UI.TitleBar {
|
||||
@ -140,9 +140,9 @@ function page:eventHandler(event)
|
||||
elseif event.type == 'grid_focus_row' then
|
||||
local manifest = event.selected.manifest
|
||||
|
||||
self.description.value = string.format('%s%s\n\n%s%s',
|
||||
self.description:setValue(string.format('%s%s\n\n%s%s',
|
||||
Ansi.yellow, manifest.title,
|
||||
Ansi.white, manifest.description)
|
||||
Ansi.white, manifest.description))
|
||||
self.description:draw()
|
||||
self:updateSelection(event.selected)
|
||||
|
||||
|
@ -52,8 +52,8 @@ local function run(...)
|
||||
loadFn = loadfile
|
||||
end
|
||||
|
||||
local funkshun, err = loadFn(path, env)
|
||||
if not funkshun then
|
||||
local O_v_O, err = loadFn(path, env)
|
||||
if not O_v_O then
|
||||
error(err, -1)
|
||||
end
|
||||
|
||||
@ -68,7 +68,7 @@ local function run(...)
|
||||
}
|
||||
|
||||
env[ "arg" ] = { [0] = path, table.unpack(args) }
|
||||
local r = { funkshun(table.unpack(args)) }
|
||||
local r = { O_v_O(table.unpack(args)) }
|
||||
|
||||
tProgramStack[#tProgramStack] = nil
|
||||
|
||||
|
@ -166,6 +166,13 @@ function fs.complete(partial, dir, includeFiles, includeSlash)
|
||||
return fs.native.complete(partial, dir, includeFiles, includeSlash)
|
||||
end
|
||||
|
||||
local displayFlags = {
|
||||
urlfs = 'U',
|
||||
linkfs = 'L',
|
||||
ramfs = 'T',
|
||||
netfs = 'N',
|
||||
}
|
||||
|
||||
function fs.listEx(dir)
|
||||
dir = fs.combine(dir, '')
|
||||
local node = getNode(dir)
|
||||
@ -176,20 +183,22 @@ function fs.listEx(dir)
|
||||
local t = { }
|
||||
local files = node.fs.list(node, dir)
|
||||
|
||||
pcall(function()
|
||||
for _,f in ipairs(files) do
|
||||
for _,f in ipairs(files) do
|
||||
pcall(function()
|
||||
local fullName = fs.combine(dir, f)
|
||||
local n = fs.getNode(fullName)
|
||||
local file = {
|
||||
name = f,
|
||||
isDir = fs.isDir(fullName),
|
||||
isReadOnly = fs.isReadOnly(fullName),
|
||||
fstype = n.mountPoint == fullName and displayFlags[n.fstype],
|
||||
}
|
||||
if not file.isDir then
|
||||
file.size = fs.getSize(fullName)
|
||||
end
|
||||
table.insert(t, file)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
|
@ -6,37 +6,41 @@ fs.loadTab('sys/etc/fstab')
|
||||
-- add some Lua compatibility functions
|
||||
function os.remove(a)
|
||||
if fs.exists(a) then
|
||||
local s = pcall(fs.delete, a)
|
||||
return s and true or nil, a .. ': Unable to remove file'
|
||||
local s = pcall(fs.delete, a)
|
||||
return s and true or nil, a .. ': Unable to remove file'
|
||||
end
|
||||
return nil, a .. ': No such file or directory'
|
||||
end
|
||||
|
||||
os.execute = function(cmd)
|
||||
if not cmd then
|
||||
return 1
|
||||
end
|
||||
local env = _G.getfenv(2)
|
||||
if not cmd then
|
||||
return env.shell and 1 or 0
|
||||
end
|
||||
|
||||
local env = _G.getfenv(2)
|
||||
local s, m = env.shell.run('sys/apps/shell.lua ' .. cmd)
|
||||
if not env.shell then
|
||||
return 0
|
||||
end
|
||||
|
||||
if not s then
|
||||
return 1, m
|
||||
end
|
||||
local s, m = env.shell.run('sys/apps/shell.lua ' .. cmd)
|
||||
|
||||
return 0
|
||||
if not s then
|
||||
return 1, m
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
os.tmpname = function()
|
||||
local fname
|
||||
repeat
|
||||
fname = 'tmp/a' .. math.random(1, 32768)
|
||||
until not fs.exists(fname)
|
||||
local fname
|
||||
repeat
|
||||
fname = 'tmp/a' .. math.random(1, 32768)
|
||||
until not fs.exists(fname)
|
||||
|
||||
return fname
|
||||
return fname
|
||||
end
|
||||
|
||||
-- non-standard - will raise error instead
|
||||
os.exit = function(code)
|
||||
error('Terminated with ' .. code)
|
||||
error('Terminated with ' .. code)
|
||||
end
|
||||
|
@ -13,7 +13,13 @@ table.insert(helpPaths, '/sys/help')
|
||||
for name in pairs(Packages:installed()) do
|
||||
local packageDir = fs.combine('packages', name)
|
||||
|
||||
local fstabPath = fs.combine(packageDir, 'etc/fstab')
|
||||
if fs.exists(fstabPath) then
|
||||
fs.loadTab(fstabPath)
|
||||
end
|
||||
|
||||
table.insert(appPaths, 1, '/' .. packageDir)
|
||||
|
||||
local apiPath = fs.combine(packageDir, 'apis') -- TODO: rename dir to 'modules' (someday)
|
||||
if fs.exists(apiPath) then
|
||||
fs.mount(fs.combine('rom/modules/main', name), 'linkfs', apiPath)
|
||||
@ -23,11 +29,6 @@ for name in pairs(Packages:installed()) do
|
||||
if fs.exists(helpPath) then
|
||||
table.insert(helpPaths, helpPath)
|
||||
end
|
||||
|
||||
local fstabPath = fs.combine(packageDir, 'etc/fstab')
|
||||
if fs.exists(fstabPath) then
|
||||
fs.loadTab(fstabPath)
|
||||
end
|
||||
end
|
||||
|
||||
help.setPath(table.concat(helpPaths, ':'))
|
||||
|
@ -1,21 +1,56 @@
|
||||
-- Based on Squid's fuzzy search
|
||||
-- https://github.com/SquidDev-CC/artist/blob/vnext/artist/lib/match.lua
|
||||
--
|
||||
-- not very fuzzy anymore
|
||||
local find = string.find
|
||||
local floor = math.floor
|
||||
local min = math.min
|
||||
local max = math.max
|
||||
local sub = string.sub
|
||||
|
||||
local SCORE_WEIGHT = 1000
|
||||
local LEADING_LETTER_PENALTY = -30
|
||||
local LEADING_LETTER_PENALTY_MAX = -90
|
||||
|
||||
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)
|
||||
- (#str - #pattern)
|
||||
-- https://rosettacode.org/wiki/Jaro_distance (ported to lua)
|
||||
return function(s1, s2)
|
||||
local l1, l2 = #s1, #s2;
|
||||
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
|
||||
|
||||
for i = 1, l1 do
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
if matches == 0 then
|
||||
return 0.0
|
||||
end
|
||||
|
||||
local t = 0.0
|
||||
local k = 1
|
||||
for i = 1, l1 do
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
-- provide a major boost for exact matches
|
||||
local b = 0.0
|
||||
if find(s1, s2, 1, true) then
|
||||
b = b + .5
|
||||
end
|
||||
|
||||
local m = matches
|
||||
return (m / l1 + m / l2 + (m - t) / m) / 3.0 + b
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user