WIP: advance implementation bot not yet complete

Now we request a watch on the directory and we manage sending
and receiving directory change events.

The mechanism to update on the fly the directory scan is not complete.
The code to remove a file is there but we need to implement the code
to add a new file.
This commit is contained in:
Francesco Abbate 2021-07-13 17:40:26 +02:00
parent 31199ecbfc
commit b2affddf32
5 changed files with 75 additions and 35 deletions

View File

@ -283,6 +283,43 @@ function core.project_files_number()
end 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 -- create a directory using mkdir but may need to create the parent
-- directories as well. -- directories as well.
local function create_user_directory() 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. -- will be simply the name of the directory, without its path.
-- The field item.topdir will identify it as a top level directory. -- The field item.topdir will identify it as a top level directory.
path = normalize_path(path) path = normalize_path(path)
local watch_id = system.watch_dir(path);
table.insert(core.project_directories, { table.insert(core.project_directories, {
name = path, name = path,
item = {filename = common.basename(path), type = "dir", topdir = true}, item = {filename = common.basename(path), type = "dir", topdir = true},
files = {} files = {},
is_dirty = true,
watch_id = watch_id,
}) })
end end
@ -890,6 +930,13 @@ function core.try(fn, ...)
end 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, ...) function core.on_event(type, ...)
local did_keymap = false local did_keymap = false
if type == "textinput" then if type == "textinput" then
@ -925,6 +972,9 @@ function core.on_event(type, ...)
end end
elseif type == "focuslost" then elseif type == "focuslost" then
core.root_view:on_focus_lost(...) 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 elseif type == "quit" then
core.quit() core.quit()
end end

View File

@ -108,11 +108,12 @@ function TreeView:check_cache()
if not last_files then if not last_files then
self.last[dir.name] = dir.files self.last[dir.name] = dir.files
else else
if dir.files ~= last_files then if dir.is_dirty or dir.files ~= last_files then
self:invalidate_cache(dir.name) self:invalidate_cache(dir.name)
self.last[dir.name] = dir.files self.last[dir.name] = dir.files
end end
end end
dir.is_dirty = false
end end
end end

View File

@ -6,7 +6,7 @@
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "api.h" #include "api.h"
#include "dmon.h" #include "dirmonitor.h"
#include "rencache.h" #include "rencache.h"
#ifdef _WIN32 #ifdef _WIN32
#include <direct.h> #include <direct.h>
@ -223,6 +223,14 @@ top:
lua_pushnumber(L, e.wheel.y); lua_pushnumber(L, e.wheel.y);
return 2; 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: default:
goto top; 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, 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)(user);
(void)(watch_id); (void)(rootdir);
dirmonitor_push_event(watch_id, action, filepath, oldfilepath);
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);
} }
static int f_watch_dir(lua_State *L) { static int f_watch_dir(lua_State *L) {
const char *path = luaL_checkstring(L, 1); const char *path = luaL_checkstring(L, 1);
dmon_watch(path, watch_callback, DMON_WATCHFLAGS_RECURSIVE, NULL); fprintf(stderr, "DEBUG: watching dir: %s\n", path); fflush(stderr);
// FIXME: we ignore the watch id and if there is an error. dmon_watch_id watch_id = dmon_watch(path, watch_callback, DMON_WATCHFLAGS_RECURSIVE, NULL);
return 0; lua_pushnumber(L, watch_id.id);
// FIXME: we ignore if there is an error.
return 1;
} }

View File

@ -18,12 +18,10 @@
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
#endif #endif
#define DMON_IMPL #include "dirmonitor.h"
#include "dmon.h"
SDL_Window *window; SDL_Window *window;
Uint32 dmon_event_no;
static double get_scale(void) { static double get_scale(void) {
#ifdef _WIN32 #ifdef _WIN32
@ -136,12 +134,7 @@ int main(int argc, char **argv) {
SDL_DisplayMode dm; SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm); SDL_GetCurrentDisplayMode(0, &dm);
dmon_init(); dirmonitor_init();
dmon_event_no = SDL_RegisterEvents(1);
if (dmon_event_no == (Uint32)-1) {
fprintf(stderr, "internal error registering SDL dmon event.\n");
exit(1);
}
window = SDL_CreateWindow( window = SDL_CreateWindow(
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8, "", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
@ -222,7 +215,7 @@ init_lua:
lua_close(L); lua_close(L);
ren_free_window_resources(); ren_free_window_resources();
dmon_deinit(); dirmonitor_deinit();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -6,6 +6,7 @@ lite_sources = [
'api/regex.c', 'api/regex.c',
'api/system.c', 'api/system.c',
'api/process.c', 'api/process.c',
'dirmonitor.c',
'renderer.c', 'renderer.c',
'renwindow.c', 'renwindow.c',
'fontdesc.c', 'fontdesc.c',