diff --git a/data/core/init.lua b/data/core/init.lua index a23026b2..bb249dbd 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -283,6 +283,43 @@ function core.project_files_number() end +local function file_search(files, filepath) + 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 + sup = curr - 1 + else + inf = curr + end + end + end + for i = inf, sup do + if files[i].filename == filepath then + return i + end + end +end + + +local function project_scan_remove_file(watch_id, filepath) + local project_dir_entry + for i = 1, #core.project_directories do + if core.project_directories[i].watch_id == watch_id then + project_dir_entry = core.project_directories[i] + end + 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 + end +end + + -- create a directory using mkdir but may need to create the parent -- directories as well. local function create_user_directory() @@ -380,10 +417,13 @@ function core.add_project_directory(path) -- will be simply the name of the directory, without its path. -- The field item.topdir will identify it as a top level directory. path = normalize_path(path) + local watch_id = system.watch_dir(path); table.insert(core.project_directories, { name = path, item = {filename = common.basename(path), type = "dir", topdir = true}, - files = {} + files = {}, + is_dirty = true, + watch_id = watch_id, }) end @@ -890,6 +930,13 @@ function core.try(fn, ...) end +function core.on_dir_change(watch_id, action, filepath) + if action == "delete" then + project_scan_remove_file(watch_id, filepath) + end +end + + function core.on_event(type, ...) local did_keymap = false if type == "textinput" then @@ -925,6 +972,9 @@ function core.on_event(type, ...) end elseif type == "focuslost" then core.root_view:on_focus_lost(...) + elseif type == "dirchange" then + print("DEBUG: dirchange", select(1, ...), select(2, ...), select(3, ...)) + core.on_dir_change(...) elseif type == "quit" then core.quit() end diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index 8214bda4..8224c1cd 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -108,11 +108,12 @@ function TreeView:check_cache() if not last_files then self.last[dir.name] = dir.files else - if dir.files ~= last_files then + if dir.is_dirty or dir.files ~= last_files then self:invalidate_cache(dir.name) self.last[dir.name] = dir.files end end + dir.is_dirty = false end end diff --git a/src/api/system.c b/src/api/system.c index 1c371772..ffead96f 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -6,7 +6,7 @@ #include #include #include "api.h" -#include "dmon.h" +#include "dirmonitor.h" #include "rencache.h" #ifdef _WIN32 #include @@ -223,6 +223,14 @@ top: lua_pushnumber(L, e.wheel.y); return 2; + case SDL_USEREVENT: + lua_pushstring(L, "dirchange"); + lua_pushnumber(L, e.user.code >> 16); + lua_pushstring(L, (e.user.code & 0xffff) == DMON_ACTION_DELETE ? "delete" : "create"); + lua_pushstring(L, e.user.data1); + free(e.user.data1); + return 4; + default: goto top; } @@ -639,33 +647,20 @@ static int f_set_window_opacity(lua_State *L) { } static void watch_callback(dmon_watch_id watch_id, dmon_action action, const char* rootdir, - const char* filepath, const char* oldfilepath, void* user) + const char* filepath, const char* oldfilepath, void* user) { - (void)(user); - (void)(watch_id); - - switch (action) { - case DMON_ACTION_CREATE: - printf("CREATE: [%s]%s\n", rootdir, filepath); - break; - case DMON_ACTION_DELETE: - printf("DELETE: [%s]%s\n", rootdir, filepath); - break; - case DMON_ACTION_MODIFY: - printf("MODIFY: [%s]%s\n", rootdir, filepath); - break; - case DMON_ACTION_MOVE: - printf("MOVE: [%s]%s -> [%s]%s\n", rootdir, oldfilepath, rootdir, filepath); - break; - } - fflush(stdout); + (void)(user); + (void)(rootdir); + dirmonitor_push_event(watch_id, action, filepath, oldfilepath); } static int f_watch_dir(lua_State *L) { const char *path = luaL_checkstring(L, 1); - dmon_watch(path, watch_callback, DMON_WATCHFLAGS_RECURSIVE, NULL); - // FIXME: we ignore the watch id and if there is an error. - return 0; + fprintf(stderr, "DEBUG: watching dir: %s\n", path); fflush(stderr); + dmon_watch_id watch_id = dmon_watch(path, watch_callback, DMON_WATCHFLAGS_RECURSIVE, NULL); + lua_pushnumber(L, watch_id.id); + // FIXME: we ignore if there is an error. + return 1; } diff --git a/src/main.c b/src/main.c index 007263c5..ccc33054 100644 --- a/src/main.c +++ b/src/main.c @@ -18,12 +18,10 @@ #include #endif -#define DMON_IMPL -#include "dmon.h" +#include "dirmonitor.h" SDL_Window *window; -Uint32 dmon_event_no; static double get_scale(void) { #ifdef _WIN32 @@ -136,12 +134,7 @@ int main(int argc, char **argv) { SDL_DisplayMode dm; SDL_GetCurrentDisplayMode(0, &dm); - dmon_init(); - dmon_event_no = SDL_RegisterEvents(1); - if (dmon_event_no == (Uint32)-1) { - fprintf(stderr, "internal error registering SDL dmon event.\n"); - exit(1); - } + dirmonitor_init(); window = SDL_CreateWindow( "", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8, @@ -222,7 +215,7 @@ init_lua: lua_close(L); ren_free_window_resources(); - dmon_deinit(); + dirmonitor_deinit(); return EXIT_SUCCESS; } diff --git a/src/meson.build b/src/meson.build index 03cc826f..c5e618f3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,6 +6,7 @@ lite_sources = [ 'api/regex.c', 'api/system.c', 'api/process.c', + 'dirmonitor.c', 'renderer.c', 'renwindow.c', 'fontdesc.c',