refactor: update project file index on watcher events

This commit is contained in:
CJ van den Berg 2026-02-20 11:40:12 +01:00
parent bf0ef280ce
commit 50fac630ce
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
2 changed files with 58 additions and 1 deletions

View file

@ -777,6 +777,40 @@ fn loaded(self: *Self, parent: tp.pid_ref) OutOfMemoryError!void {
parent.send(.{ "PRJ", "open_done", self.name, self.longest_file_path, self.files.items.len }) catch {};
}
pub fn file_added(self: *Self, file_path: []const u8) OutOfMemoryError!void {
for (self.files.items) |file|
if (std.mem.eql(u8, file.path, file_path)) return;
const file_type, const file_icon, const file_color = guess_file_type(file_path);
(try self.files.addOne(self.allocator)).* = .{
.path = try self.allocator.dupe(u8, file_path),
.type = file_type,
.icon = file_icon,
.color = file_color,
.mtime = std.time.nanoTimestamp(),
};
self.longest_file_path = @max(self.longest_file_path, file_path.len);
self.sort_files_by_mtime();
}
pub fn file_modified(self: *Self, file_path: []const u8) void {
for (self.files.items) |*file| {
if (!std.mem.eql(u8, file.path, file_path)) continue;
file.mtime = std.time.nanoTimestamp();
self.sort_files_by_mtime();
return;
}
}
pub fn file_deleted(self: *Self, file_path: []const u8) void {
for (self.files.items, 0..) |file, i| {
if (!std.mem.eql(u8, file.path, file_path)) continue;
self.allocator.free(file.path);
_ = self.files.swapRemove(i);
self.sort_files_by_mtime();
return;
}
}
pub fn update_mru(self: *Self, file_path: []const u8, row: usize, col: usize) OutOfMemoryError!void {
defer self.sort_files_by_mtime();
try self.update_mru_internal(file_path, std.time.nanoTimestamp(), row, col);

View file

@ -421,8 +421,11 @@ const Process = struct {
var vcs_id: []const u8 = undefined;
var eol_mode: Buffer.EolModeTag = @intFromEnum(Buffer.EolMode.lf);
var event_type: file_watcher.EventType = undefined;
if (try cbor.match(m.buf, .{ "walk_tree_entry", tp.extract(&project_directory), tp.more })) {
if (try cbor.match(m.buf, .{ "FW", "change", tp.extract(&path), tp.extract(&event_type) })) {
self.handle_file_watch_event(path, event_type);
} else if (try cbor.match(m.buf, .{ "walk_tree_entry", tp.extract(&project_directory), tp.more })) {
if (self.projects.get(project_directory)) |project|
project.walk_tree_entry(m) catch |e| self.logger.err("walk_tree_entry", e);
} else if (try cbor.match(m.buf, .{ "walk_tree_done", tp.extract(&project_directory) })) {
@ -539,6 +542,26 @@ const Process = struct {
}
}
fn handle_file_watch_event(self: *Process, abs_path: []const u8, event_type: file_watcher.EventType) void {
std.log.debug("file_watch_event: {s} {s}", .{ @tagName(event_type), abs_path });
var it = self.projects.iterator();
while (it.next()) |entry| {
const dir = entry.key_ptr.*;
if (!std.mem.startsWith(u8, abs_path, dir)) continue;
if (abs_path.len <= dir.len or abs_path[dir.len] != std.fs.path.sep) continue;
const rel_path = abs_path[dir.len + 1 ..];
const project = entry.value_ptr.*;
switch (event_type) {
.created => project.file_added(rel_path) catch |e| self.logger.err("file_watcher.file_added", e),
.modified => project.file_modified(rel_path),
.deleted => project.file_deleted(rel_path),
.renamed => project.file_deleted(rel_path),
}
return;
}
self.parent.send(.{ "FW", "change", abs_path, event_type }) catch {};
}
fn open(self: *Process, project_directory: []const u8) (SpawnError || std.fs.Dir.OpenError)!void {
if (self.projects.get(project_directory)) |project| {
project.last_used = std.time.nanoTimestamp();