Fix files limited project with dir monintoring

Changed approach to files limited project. Now we keep into the
top-level dir a list of subdirectories to be shown. When in file
limited mode we will not scan subdirectories unless they are in
the list of shown subdirectories.

With the new mechanism the function get_subdirectory_files always
recurse into subdirectories by default but is able to figure out
to stop recursing into subdirectories for files limited project.

The new mechanism is more robust of the previous one. Now the
rescan of subdirectories is compatible with files limited project.
This commit is contained in:
Francesco Abbate 2021-07-25 20:49:35 +02:00
parent db24dbc3a0
commit b7ef9a5609
2 changed files with 29 additions and 16 deletions

View File

@ -114,29 +114,27 @@ end
-- 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 eash item the "filename" will be the -- Returns a list of file "items". In eash item the "filename" will be the
-- complete file path relative to "root" *without* the trailing '/'. -- complete file path relative to "root" *without* the trailing '/'.
local function get_directory_files(root, path, t, recursive, begin_hook) local function get_directory_files(dir, root, path, t, begin_hook, max_files)
if begin_hook then begin_hook() end if begin_hook then begin_hook() end
local all = system.list_dir(root .. path) or {} local all = system.list_dir(root .. path) or {}
local dirs, files = {}, {} local dirs, files = {}, {}
local entries_count = 0 local entries_count = 0
local max_entries = config.max_project_files
for _, file in ipairs(all) do for _, file in ipairs(all) do
local info = get_project_file_info(root, path .. PATHSEP .. file) local info = get_project_file_info(root, path .. PATHSEP .. file)
if info then if info then
table.insert(info.type == "dir" and dirs or files, info) table.insert(info.type == "dir" and dirs or files, info)
entries_count = entries_count + 1 entries_count = entries_count + 1
if recursive and entries_count > max_entries then return nil, entries_count end
end end
end end
table.sort(dirs, compare_file) table.sort(dirs, compare_file)
for _, f in ipairs(dirs) do for _, f in ipairs(dirs) do
table.insert(t, f) table.insert(t, f)
if recursive and entries_count <= max_entries then if (not max_files or entries_count <= max_files) and core.project_subdir_is_shown(dir, f.filename) then
local subdir_t, subdir_count = get_directory_files(root, PATHSEP .. f.filename, t, recursive, begin_hook) local sub_limit = max_files and max_files - entries_count
entries_count = entries_count + subdir_count local _, n = get_directory_files(dir, root, PATHSEP .. f.filename, t, begin_hook, sub_limit)
f.scanned = true entries_count = entries_count + n
end end
end end
@ -149,6 +147,16 @@ local function get_directory_files(root, path, t, recursive, begin_hook)
end end
function core.project_subdir_set_show(dir, filename, show)
dir.shown_subdir[filename] = show
end
function core.project_subdir_is_shown(dir, filename)
return not dir.files_limit or dir.shown_subdir[filename]
end
local function show_max_files_warning() local function show_max_files_warning()
core.status_view:show_message("!", style.accent, core.status_view:show_message("!", style.accent,
"Too many files in project directory: stopped reading at ".. "Too many files in project directory: stopped reading at "..
@ -160,7 +168,7 @@ end
-- Populate a project folder top directory by scanning the filesystem. -- Populate a project folder top directory by scanning the filesystem.
local function scan_project_folder(index) local function 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, dir.name, "", {}, nil, config.max_project_files)
if entries_count > config.max_project_files then if entries_count > config.max_project_files then
dir.files_limit = true dir.files_limit = true
if core.status_view then -- May be not yet initialized. if core.status_view then -- May be not yet initialized.
@ -184,6 +192,7 @@ function core.add_project_directory(path)
files_limit = false, files_limit = false,
is_dirty = true, is_dirty = true,
watch_id = watch_id, watch_id = watch_id,
shown_subdir = {},
} }
table.insert(core.project_directories, dir) table.insert(core.project_directories, dir)
scan_project_folder(#core.project_directories) scan_project_folder(#core.project_directories)
@ -277,8 +286,7 @@ local function project_subdir_bounds(dir, filename)
end end
local function rescan_project_subdir(dir, filename_rooted) local function rescan_project_subdir(dir, filename_rooted)
local recursive = not dir.files_limit local new_files = get_directory_files(dir, dir.name, filename_rooted, {}, coroutine.yield)
local new_files = get_directory_files(dir.name, filename_rooted, {}, recursive, coroutine.yield)
local index, n = 0, #dir.files local index, n = 0, #dir.files
if filename_rooted ~= "" then if filename_rooted ~= "" then
local filename = strip_leading_path(filename_rooted) local filename = strip_leading_path(filename_rooted)
@ -296,9 +304,9 @@ end
function core.scan_project_subdir(dir, filename) function core.scan_project_subdir(dir, filename)
local index, n, file = project_subdir_bounds(dir, filename) local index, n, file = project_subdir_bounds(dir, filename)
if index then if index then
local new_files = get_directory_files(dir.name, PATHSEP .. filename, {}) local new_files = get_directory_files(dir, dir.name, PATHSEP .. filename, {})
files_list_replace(dir.files, index, n, new_files) files_list_replace(dir.files, index, n, new_files)
file.scanned = true dir.is_dirty = true
return true return true
end end
end end
@ -1051,6 +1059,7 @@ function core.has_pending_rescan()
end end
end end
function core.dir_rescan_add_job(dir, filepath) function core.dir_rescan_add_job(dir, filepath)
local dirpath = filepath:match("^(.+)[/\\].+$") local dirpath = filepath:match("^(.+)[/\\].+$")
local dirpath_rooted = dirpath and PATHSEP .. dirpath or "" local dirpath_rooted = dirpath and PATHSEP .. dirpath or ""
@ -1058,7 +1067,8 @@ function core.dir_rescan_add_job(dir, filepath)
if dirpath then if dirpath then
-- check if the directory is in the project files list, if not exit -- check if the directory is in the project files list, if not exit
local dir_index, dir_match = file_search(dir.files, {filename = dirpath, type = "dir"}) local dir_index, dir_match = file_search(dir.files, {filename = dirpath, type = "dir"})
if not dir_match or (dir.files_limit and not dir.files[dir_index].scanned) then return end local dir_filename = dir.files[dir_index].filename
if not dir_match or not core.project_subdir_is_shown(dir, dir_filename) then return end
end end
local new_time = system.get_time() + 1 local new_time = system.get_time() + 1

View File

@ -217,10 +217,13 @@ 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 hovered_item.dir.files_limit and not hovered_item.expanded then hovered_item.expanded = not hovered_item.expanded
if hovered_item.dir.files_limit then
if hovered_item.expanded then
core.scan_project_subdir(hovered_item.dir, hovered_item.filename) core.scan_project_subdir(hovered_item.dir, hovered_item.filename)
end end
hovered_item.expanded = not hovered_item.expanded core.project_subdir_set_show(hovered_item.dir, hovered_item.filename, hovered_item.expanded)
end
end end
else else
core.try(function() core.try(function()