WIP: add correct binary search for removed file
Use a C function to compare nested files in project tree to enable binary search of a file across the project files tree.
This commit is contained in:
parent
b2affddf32
commit
79b65014a5
|
@ -106,6 +106,18 @@ local function compare_file(a, b)
|
|||
return a.filename < b.filename
|
||||
end
|
||||
|
||||
|
||||
-- compute a file's info entry completed with "filename" to be used
|
||||
-- in project scan or falsy if it shouldn't appear in the list.
|
||||
local function get_project_file_info(root, file, size_limit)
|
||||
local info = system.get_file_info(root .. file)
|
||||
if info then
|
||||
info.filename = strip_leading_path(file)
|
||||
end
|
||||
return info and info.size < size_limit and info
|
||||
end
|
||||
|
||||
|
||||
-- "root" will by an absolute path without trailing '/'
|
||||
-- "path" will be a path starting with '/' and without trailing '/'
|
||||
-- or the empty string.
|
||||
|
@ -124,10 +136,8 @@ local function get_directory_files(root, path, t, recursive, begin_hook)
|
|||
local max_entries = config.max_project_files
|
||||
for _, file in ipairs(all) do
|
||||
if not common.match_pattern(file, config.ignore_files) then
|
||||
local file = path .. PATHSEP .. file
|
||||
local info = system.get_file_info(root .. file)
|
||||
if info and info.size < size_limit then
|
||||
info.filename = strip_leading_path(file)
|
||||
local info = get_project_file_info(root, path .. PATHSEP .. file, size_limit)
|
||||
if info then
|
||||
table.insert(info.type == "dir" and dirs or files, info)
|
||||
entries_count = entries_count + 1
|
||||
if recursive and entries_count > max_entries then return nil, entries_count end
|
||||
|
@ -283,20 +293,18 @@ function core.project_files_number()
|
|||
end
|
||||
|
||||
|
||||
local function file_search(files, filepath)
|
||||
local function file_search(files, fileinfo)
|
||||
local inf, sup = 1, #files
|
||||
if false then -- FIXME: skipping binary search / it is broken
|
||||
while sup - inf > 8 do
|
||||
local curr = math.floor((inf + sup) / 2)
|
||||
if filepath < files[curr].filename then
|
||||
if system.path_compare(fileinfo.filename, fileinfo.type, files[curr].filename, files[curr].type) then
|
||||
sup = curr - 1
|
||||
else
|
||||
inf = curr
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = inf, sup do
|
||||
if files[i].filename == filepath then
|
||||
if files[i].filename == fileinfo.filename then
|
||||
return i
|
||||
end
|
||||
end
|
||||
|
@ -310,12 +318,18 @@ local function project_scan_remove_file(watch_id, filepath)
|
|||
project_dir_entry = core.project_directories[i]
|
||||
end
|
||||
end
|
||||
if not project_dir_entry then return end
|
||||
print("LOOKING for", filepath, " in", project_dir_entry and project_dir_entry.name)
|
||||
local index = project_dir_entry and file_search(project_dir_entry.files, filepath)
|
||||
if index then
|
||||
print("FOUND", filepath, " at index", index)
|
||||
table.remove(files, index)
|
||||
project_dir_entry.is_dirty = true
|
||||
local fileinfo = { filename = filepath }
|
||||
for _, filetype in ipairs {"dir", "file"} do
|
||||
fileinfo.type = filetype
|
||||
local index = file_search(project_dir_entry.files, fileinfo)
|
||||
if index then
|
||||
print("FOUND", filepath, " at index", index)
|
||||
table.remove(project_dir_entry.files, index)
|
||||
project_dir_entry.is_dirty = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -663,6 +663,39 @@ static int f_watch_dir(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PATHSEP '\\'
|
||||
#else
|
||||
#define PATHSEP '/'
|
||||
#endif
|
||||
|
||||
|
||||
static int f_path_compare(lua_State *L) {
|
||||
const char *path1 = luaL_checkstring(L, 1);
|
||||
const char *type1_s = luaL_checkstring(L, 2);
|
||||
const char *path2 = luaL_checkstring(L, 3);
|
||||
const char *type2_s = luaL_checkstring(L, 4);
|
||||
const int len1 = strlen(path1), len2 = strlen(path2);
|
||||
int type1 = strcmp(type1_s, "dir") != 0;
|
||||
int type2 = strcmp(type2_s, "dir") != 0;
|
||||
int i;
|
||||
for (i = 0; i < len1 && i < len2; i++) {
|
||||
if (path1[i] != path2[i]) break;
|
||||
}
|
||||
if (strchr(path1 + i, PATHSEP)) {
|
||||
type1 = 0;
|
||||
}
|
||||
if (strchr(path2 + i, PATHSEP)) {
|
||||
type2 = 0;
|
||||
}
|
||||
if (type1 != type2) {
|
||||
lua_pushboolean(L, type1 < type2);
|
||||
return 1;
|
||||
}
|
||||
lua_pushboolean(L, strcmp(path1 + i, path2 + i) < 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg lib[] = {
|
||||
{ "poll_event", f_poll_event },
|
||||
|
@ -691,6 +724,7 @@ static const luaL_Reg lib[] = {
|
|||
{ "fuzzy_match", f_fuzzy_match },
|
||||
{ "set_window_opacity", f_set_window_opacity },
|
||||
{ "watch_dir", f_watch_dir },
|
||||
{ "path_compare", f_path_compare },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue