Fix `dirmonitor` sorting issues (#1599)
* Use `PATHSEP` in path-related functions * Don't stop on digits when getting the common part in `system.path_compare` * Avoid sorting multiple times in `dirwatch.get_directory_files` This also fixes the timeout detection in `recurse_pred`.
This commit is contained in:
parent
6cd1f96234
commit
5c5c77219b
|
@ -226,7 +226,7 @@ function common.path_suggest(text, root)
|
|||
if root and root:sub(-1) ~= PATHSEP then
|
||||
root = root .. PATHSEP
|
||||
end
|
||||
local path, name = text:match("^(.-)([^/\\]*)$")
|
||||
local path, name = text:match("^(.-)([^"..PATHSEP.."]*)$")
|
||||
local clean_dotslash = false
|
||||
-- ignore root if path is absolute
|
||||
local is_absolute = common.is_absolute_path(text)
|
||||
|
@ -279,7 +279,7 @@ end
|
|||
---@param text string The input path.
|
||||
---@return string[]
|
||||
function common.dir_path_suggest(text)
|
||||
local path, name = text:match("^(.-)([^/\\]*)$")
|
||||
local path, name = text:match("^(.-)([^"..PATHSEP.."]*)$")
|
||||
local files = system.list_dir(path == "" and "." or path) or {}
|
||||
local res = {}
|
||||
for _, file in ipairs(files) do
|
||||
|
@ -298,7 +298,7 @@ end
|
|||
---@param dir_list string[] A list of paths to filter.
|
||||
---@return string[]
|
||||
function common.dir_list_suggest(text, dir_list)
|
||||
local path, name = text:match("^(.-)([^/\\]*)$")
|
||||
local path, name = text:match("^(.-)([^"..PATHSEP.."]*)$")
|
||||
local res = {}
|
||||
for _, dir_path in ipairs(dir_list) do
|
||||
if dir_path:lower():find(text:lower(), nil, true) == 1 then
|
||||
|
@ -461,7 +461,7 @@ end
|
|||
function common.basename(path)
|
||||
-- a path should never end by / or \ except if it is '/' (unix root) or
|
||||
-- 'X:\' (windows drive)
|
||||
return path:match("[^\\/]+$") or path
|
||||
return path:match("[^"..PATHSEP.."]+$") or path
|
||||
end
|
||||
|
||||
|
||||
|
@ -470,7 +470,7 @@ end
|
|||
---@param path string
|
||||
---@return string|nil
|
||||
function common.dirname(path)
|
||||
return path:match("(.+)[\\/][^\\/]+$")
|
||||
return path:match("(.+)["..PATHSEP.."][^"..PATHSEP.."]+$")
|
||||
end
|
||||
|
||||
|
||||
|
@ -513,10 +513,10 @@ end
|
|||
|
||||
local function split_on_slash(s, sep_pattern)
|
||||
local t = {}
|
||||
if s:match("^[/\\]") then
|
||||
if s:match("^["..PATHSEP.."]") then
|
||||
t[#t + 1] = ""
|
||||
end
|
||||
for fragment in string.gmatch(s, "([^/\\]+)") do
|
||||
for fragment in string.gmatch(s, "([^"..PATHSEP.."]+)") do
|
||||
t[#t + 1] = fragment
|
||||
end
|
||||
return t
|
||||
|
@ -649,7 +649,7 @@ function common.mkdirp(path)
|
|||
while path and path ~= "" do
|
||||
local success_mkdir = system.mkdir(path)
|
||||
if success_mkdir then break end
|
||||
local updir, basedir = path:match("(.*)[/\\](.+)$")
|
||||
local updir, basedir = path:match("(.*)["..PATHSEP.."](.+)$")
|
||||
table.insert(subdirs, 1, basedir or path)
|
||||
path = updir
|
||||
end
|
||||
|
|
|
@ -190,49 +190,47 @@ end
|
|||
-- "root" will by an absolute path without trailing '/'
|
||||
-- "path" will be a path starting without '/' and without trailing '/'
|
||||
-- or the empty string.
|
||||
-- It will identifies a sub-path within "root.
|
||||
-- It identifies a sub-path within "root".
|
||||
-- The current path location will therefore always be: root .. path.
|
||||
-- When recursing "root" will always be the same, only "path" will change.
|
||||
-- When recursing, "root" will always be the same, only "path" will change.
|
||||
-- Returns a list of file "items". In each item the "filename" will be the
|
||||
-- complete file path relative to "root" *without* the trailing '/', and without the starting '/'.
|
||||
function dirwatch.get_directory_files(dir, root, path, t, entries_count, recurse_pred)
|
||||
function dirwatch.get_directory_files(dir, root, path, entries_count, recurse_pred)
|
||||
local t = {}
|
||||
local t0 = system.get_time()
|
||||
local t_elapsed = system.get_time() - t0
|
||||
local dirs, files = {}, {}
|
||||
local ignore_compiled = compile_ignore_files()
|
||||
|
||||
|
||||
local all = system.list_dir(root .. PATHSEP .. path)
|
||||
if not all then return nil end
|
||||
|
||||
for _, file in ipairs(all or {}) do
|
||||
local entries = { }
|
||||
for _, file in ipairs(all) do
|
||||
local info = get_project_file_info(root, (path ~= "" and (path .. PATHSEP) or "") .. file, ignore_compiled)
|
||||
if info then
|
||||
table.insert(info.type == "dir" and dirs or files, info)
|
||||
entries_count = entries_count + 1
|
||||
table.insert(entries, info)
|
||||
end
|
||||
end
|
||||
table.sort(entries, compare_file)
|
||||
|
||||
local recurse_complete = true
|
||||
table.sort(dirs, compare_file)
|
||||
for _, f in ipairs(dirs) do
|
||||
table.insert(t, f)
|
||||
if recurse_pred(dir, f.filename, entries_count, t_elapsed) then
|
||||
local _, complete, n = dirwatch.get_directory_files(dir, root, f.filename, t, entries_count, recurse_pred)
|
||||
recurse_complete = recurse_complete and complete
|
||||
if n ~= nil then
|
||||
entries_count = n
|
||||
for _, info in ipairs(entries) do
|
||||
table.insert(t, info)
|
||||
entries_count = entries_count + 1
|
||||
if info.type == "dir" then
|
||||
if recurse_pred(dir, info.filename, entries_count, system.get_time() - t0) then
|
||||
local t_rec, complete, n = dirwatch.get_directory_files(dir, root, info.filename, entries_count, recurse_pred)
|
||||
recurse_complete = recurse_complete and complete
|
||||
if n ~= nil then
|
||||
entries_count = n
|
||||
for _, info_rec in ipairs(t_rec) do
|
||||
table.insert(t, info_rec)
|
||||
end
|
||||
end
|
||||
else
|
||||
recurse_complete = false
|
||||
end
|
||||
else
|
||||
recurse_complete = false
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(files, compare_file)
|
||||
for _, f in ipairs(files) do
|
||||
table.insert(t, f)
|
||||
end
|
||||
|
||||
return t, recurse_complete, entries_count
|
||||
end
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ local function strip_leading_path(filename)
|
|||
end
|
||||
|
||||
local function strip_trailing_slash(filename)
|
||||
if filename:match("[^:][/\\]$") then
|
||||
if filename:match("[^:]["..PATHSEP.."]$") then
|
||||
return filename:sub(1, -2)
|
||||
end
|
||||
return filename
|
||||
|
@ -120,9 +120,7 @@ local function show_max_files_warning(dir)
|
|||
"Too many files in project directory: stopped reading at "..
|
||||
config.max_project_files.." files. For more information see "..
|
||||
"usage.md at https://github.com/lite-xl/lite-xl."
|
||||
if core.status_view then
|
||||
core.status_view:show_message("!", style.accent, message)
|
||||
end
|
||||
core.warn(message)
|
||||
end
|
||||
|
||||
|
||||
|
@ -184,7 +182,7 @@ local function refresh_directory(topdir, target)
|
|||
directory_start_idx = directory_start_idx + 1
|
||||
end
|
||||
|
||||
local files = dirwatch.get_directory_files(topdir, topdir.name, (target or ""), {}, 0, function() return false end)
|
||||
local files = dirwatch.get_directory_files(topdir, topdir.name, (target or ""), 0, function() return false end)
|
||||
local change = false
|
||||
|
||||
-- If this file doesn't exist, we should be calling this on our parent directory, assume we'll do that.
|
||||
|
@ -265,7 +263,7 @@ function core.add_project_directory(path)
|
|||
|
||||
local fstype = PLATFORM == "Linux" and system.get_fs_type(topdir.name) or "unknown"
|
||||
topdir.force_scans = (fstype == "nfs" or fstype == "fuse")
|
||||
local t, complete, entries_count = dirwatch.get_directory_files(topdir, topdir.name, "", {}, 0, timed_max_files_pred)
|
||||
local t, complete, entries_count = dirwatch.get_directory_files(topdir, topdir.name, "", 0, timed_max_files_pred)
|
||||
topdir.files = t
|
||||
if not complete then
|
||||
topdir.slow_filesystem = not complete and (entries_count <= config.max_project_files)
|
||||
|
|
|
@ -24,7 +24,7 @@ local tooltip_alpha_rate = 1
|
|||
|
||||
local function get_depth(filename)
|
||||
local n = 1
|
||||
for sep in filename:gmatch("[\\/]") do
|
||||
for _ in filename:gmatch(PATHSEP) do
|
||||
n = n + 1
|
||||
end
|
||||
return n
|
||||
|
|
|
@ -1043,7 +1043,7 @@ static int f_load_native_plugin(lua_State *L) {
|
|||
#endif
|
||||
|
||||
/* Special purpose filepath compare function. Corresponds to the
|
||||
order used in the TreeView view of the project's files. Returns true iff
|
||||
order used in the TreeView view of the project's files. Returns true if
|
||||
path1 < path2 in the TreeView order. */
|
||||
static int f_path_compare(lua_State *L) {
|
||||
size_t len1, len2;
|
||||
|
@ -1057,7 +1057,6 @@ static int f_path_compare(lua_State *L) {
|
|||
size_t offset = 0, i, j;
|
||||
for (i = 0; i < len1 && i < len2; i++) {
|
||||
if (path1[i] != path2[i]) break;
|
||||
if (isdigit(path1[i])) break;
|
||||
if (path1[i] == PATHSEP) {
|
||||
offset = i + 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue