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
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

View File

@ -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

View File

@ -6,7 +6,7 @@
#include <errno.h>
#include <sys/stat.h>
#include "api.h"
#include "dmon.h"
#include "dirmonitor.h"
#include "rencache.h"
#ifdef _WIN32
#include <direct.h>
@ -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;
}
@ -642,30 +650,17 @@ static void watch_callback(dmon_watch_id watch_id, dmon_action action, const cha
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)(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;
}

View File

@ -18,12 +18,10 @@
#include <mach-o/dyld.h>
#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;
}

View File

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