Fix bug with expanding directory when file limited

Introduce a new field in items generated by TreeView:each_item()
to point "dir" to the toplevel directory entry.

In this was we can simplify the code and know if the toplevel
directory is files limited.
This commit is contained in:
Francesco Abbate 2021-07-15 12:17:18 +02:00
parent 3994c3ac42
commit d3c7a43a60
4 changed files with 31 additions and 36 deletions

View File

@ -66,6 +66,7 @@ command.add(nil, {
end, end,
["core:find-file"] = function() ["core:find-file"] = function()
-- FIXME: core.project_files_limit was removed!
if core.project_files_limit then if core.project_files_limit then
return command.perform "core:open-file" return command.perform "core:open-file"
end end

View File

@ -154,8 +154,8 @@ local function get_directory_files(root, path, t, recursive, begin_hook)
end end
-- FIXME: change the name with core.scan_project_folder -- Populate a project folder top directory by scanning the filesystem.
function core.project_scan_topdir(index) function core.scan_project_folder(index)
local dir = core.project_directories[index] local dir = core.project_directories[index]
local t, entries_count = get_directory_files(dir.name, "", {}, true) local t, entries_count = get_directory_files(dir.name, "", {}, true)
if entries_count > config.max_project_files then if entries_count > config.max_project_files then
@ -189,22 +189,12 @@ function core.add_project_directory(path)
is_dirty = true, is_dirty = true,
watch_id = watch_id, watch_id = watch_id,
}) })
core.project_scan_topdir(#core.project_directories) core.scan_project_folder(#core.project_directories)
core.redraw = true core.redraw = true
end end
function core.is_project_folder(dirname) function core.scan_project_subdir(dirname, filename)
for _, dir in ipairs(core.project_directories) do
if dir.name == dirname then
return true
end
end
return false
end
function core.scan_project_folder(dirname, filename)
for _, dir in ipairs(core.project_directories) do for _, dir in ipairs(core.project_directories) do
if dir.name == dirname then if dir.name == dirname then
for i, file in ipairs(dir.files) do for i, file in ipairs(dir.files) do
@ -216,15 +206,17 @@ function core.scan_project_folder(dirname, filename)
table.insert(dir.files, i + j, new_file) table.insert(dir.files, i + j, new_file)
end end
file.scanned = true file.scanned = true
return return true
end end
end end
end end
end end
end end
-- FIXME: rename this function -- Find files and directories recursively reading from the filesystem.
local function find_project_files_co(root, path) -- Filter files and yields file's directory and info table. This latter
-- is filled to be like required by project directories "files" list.
local function find_files_rec(root, path)
local size_limit = config.file_size_limit * 10e5 local size_limit = config.file_size_limit * 10e5
local all = system.list_dir(root .. path) or {} local all = system.list_dir(root .. path) or {}
for _, file in ipairs(all) do for _, file in ipairs(all) do
@ -236,7 +228,7 @@ local function find_project_files_co(root, path)
if info.type == "file" then if info.type == "file" then
coroutine.yield(root, info) coroutine.yield(root, info)
else else
find_project_files_co(root, PATHSEP .. info.filename) find_files_rec(root, PATHSEP .. info.filename)
end end
end end
end end
@ -244,19 +236,25 @@ local function find_project_files_co(root, path)
end end
-- Iterator function to list all project files
local function project_files_iter(state) local function project_files_iter(state)
local dir = core.project_directories[state.dir_index] local dir = core.project_directories[state.dir_index]
if state.co then if state.co then
-- We have a coroutine to fetch for files, use the coroutine.
-- Used for directories that exceeds the files nuumber limit.
local ok, name, file = coroutine.resume(state.co, dir.name, "") local ok, name, file = coroutine.resume(state.co, dir.name, "")
if ok and name then if ok and name then
return name, file return name, file
else else
-- The coroutine terminated, increment file/dir counter to scan
-- next project directory.
state.co = false state.co = false
state.file_index = 1 state.file_index = 1
state.dir_index = state.dir_index + 1 state.dir_index = state.dir_index + 1
dir = core.project_directories[state.dir_index] dir = core.project_directories[state.dir_index]
end end
else else
-- Increase file/dir counter
state.file_index = state.file_index + 1 state.file_index = state.file_index + 1
while dir and state.file_index > #dir.files do while dir and state.file_index > #dir.files do
state.dir_index = state.dir_index + 1 state.dir_index = state.dir_index + 1
@ -266,7 +264,9 @@ local function project_files_iter(state)
end end
if not dir then return end if not dir then return end
if dir.files_limit then if dir.files_limit then
state.co = coroutine.create(find_project_files_co) -- The current project directory is files limited: create a couroutine
-- to read files from the filesystem.
state.co = coroutine.create(find_files_rec)
return project_files_iter(state) return project_files_iter(state)
end end
return dir.name, dir.files[state.file_index] return dir.name, dir.files[state.file_index]

View File

@ -50,7 +50,7 @@ function TreeView:set_target_size(axis, value)
end end
function TreeView:get_cached(item, dirname) function TreeView:get_cached(dir, item, dirname)
local dir_cache = self.cache[dirname] local dir_cache = self.cache[dirname]
if not dir_cache then if not dir_cache then
dir_cache = {} dir_cache = {}
@ -76,6 +76,7 @@ function TreeView:get_cached(item, dirname)
end end
t.name = basename t.name = basename
t.type = item.type t.type = item.type
t.dir = dir -- points to top level "dir" item
dir_cache[cache_name] = t dir_cache[cache_name] = t
end end
return t return t
@ -122,14 +123,14 @@ function TreeView:each_item()
for k = 1, #core.project_directories do for k = 1, #core.project_directories do
local dir = core.project_directories[k] local dir = core.project_directories[k]
local dir_cached = self:get_cached(dir.item, dir.name) local dir_cached = self:get_cached(dir, dir.item, dir.name)
coroutine.yield(dir_cached, ox, y, w, h) coroutine.yield(dir_cached, ox, y, w, h)
count_lines = count_lines + 1 count_lines = count_lines + 1
y = y + h y = y + h
local i = 1 local i = 1
while i <= #dir.files and dir_cached.expanded do while i <= #dir.files and dir_cached.expanded do
local item = dir.files[i] local item = dir.files[i]
local cached = self:get_cached(item, dir.name) local cached = self:get_cached(dir, item, dir.name)
coroutine.yield(cached, ox, y, w, h) coroutine.yield(cached, ox, y, w, h)
count_lines = count_lines + 1 count_lines = count_lines + 1
@ -213,19 +214,9 @@ function TreeView:on_mouse_pressed(button, x, y, clicks)
if keymap.modkeys["ctrl"] and button == "left" then if keymap.modkeys["ctrl"] and button == "left" then
create_directory_in(hovered_item) create_directory_in(hovered_item)
else else
if core.project_files_limit and not hovered_item.expanded then if hovered_item.dir.files_limit and not hovered_item.expanded then
local filename, abs_filename = hovered_item.filename, hovered_item.abs_filename local dirname = hovered_item.dir.name
local index = 0 if core.scan_project_subdir(dirname, hovered_item.filename) then
-- The loop below is used to find the first match starting from the end
-- in case there are multiple matches.
while index and index + #filename < #abs_filename do
index = string.find(abs_filename, filename, index + 1, true)
end
-- we assume here index is not nil because the abs_filename must contain the
-- relative filename
local dirname = string.sub(abs_filename, 1, index - 2)
if core.is_project_folder(dirname) then
core.scan_project_folder(dirname, filename)
self:invalidate_cache(dirname) self:invalidate_cache(dirname)
end end
end end

View File

@ -1,6 +1,9 @@
`core.scan_project_folder`: `core.scan_project_folder`: (renamed to `core.scan_project_subdir`)
scan a single folder, without recursion. Used when too many files. scan a single folder, without recursion. Used when too many files.
New `core.scan_project_folder`:
Populate the project folder top directory. Done only once when the directory
is added to the project.
`core.add_project_directory`: `core.add_project_directory`:
Add a new top-level folder to the project. Add a new top-level folder to the project.