diff --git a/data/core/init.lua b/data/core/init.lua index bb249dbd..109b1b83 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -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 diff --git a/src/api/system.c b/src/api/system.c index ffead96f..9c8f8faa 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -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 } };