From efb3ab42fde4c43de11121819e62732515e3df5e Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Tue, 21 Jan 2025 21:59:55 +0100 Subject: [PATCH] feat(buffers): add tracking of last modified and last used times for buffers --- src/buffer/Buffer.zig | 15 +++++++++++++++ src/buffer/Manager.zig | 42 +++++++++++++++++++++++++----------------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/buffer/Buffer.zig b/src/buffer/Buffer.zig index b5779e4..215a179 100644 --- a/src/buffer/Buffer.zig +++ b/src/buffer/Buffer.zig @@ -44,6 +44,9 @@ undo_history: ?*UndoNode = null, redo_history: ?*UndoNode = null, curr_history: ?*UndoNode = null, +mtime: i64, +utime: i64, + pub const EolMode = enum { lf, crlf }; pub const EolModeTag = @typeInfo(EolMode).Enum.tag_type; @@ -1052,6 +1055,8 @@ pub fn create(allocator: Allocator) error{OutOfMemory}!*Self { .allocator = self.arena.allocator(), .external_allocator = allocator, .root = try Node.new(self.allocator, &empty_leaf, &empty_leaf), + .mtime = std.time.milliTimestamp(), + .utime = std.time.milliTimestamp(), }; return self; } @@ -1063,6 +1068,10 @@ pub fn deinit(self: *Self) void { self.external_allocator.destroy(self); } +pub fn update_last_used_time(self: *Self) void { + self.utime = std.time.milliTimestamp(); +} + fn new_file(self: *const Self, file_exists: *bool) error{OutOfMemory}!Root { file_exists.* = false; return Leaf.new(self.allocator, "", true, false); @@ -1142,6 +1151,7 @@ pub fn load_from_string_and_update(self: *Self, file_path: []const u8, s: []cons self.last_save = self.root; self.last_save_eol_mode = self.file_eol_mode; self.file_exists = false; + self.mtime = std.time.milliTimestamp(); } pub const LoadFromFileError = error{ @@ -1213,12 +1223,14 @@ pub fn load_from_file_and_update(self: *Self, file_path: []const u8) LoadFromFil self.file_eol_mode = eol_mode; self.file_utf8_sanitized = utf8_sanitized; self.last_save_eol_mode = eol_mode; + self.mtime = std.time.milliTimestamp(); } pub fn reset_to_last_saved(self: *Self) void { if (self.last_save) |last_save| { self.store_undo(&[_]u8{}) catch {}; self.root = last_save; + self.mtime = std.time.milliTimestamp(); } } @@ -1319,6 +1331,7 @@ pub fn version(self: *const Self) usize { pub fn update(self: *Self, root: Root) void { self.root = root; + self.mtime = std.time.milliTimestamp(); } pub fn store_undo(self: *Self, meta: []const u8) !void { @@ -1369,6 +1382,7 @@ pub fn undo(self: *Self, meta: []const u8) error{Stop}![]const u8 { self.curr_history = h; self.root = h.root; self.push_redo(r); + self.mtime = std.time.milliTimestamp(); return h.meta; } @@ -1380,5 +1394,6 @@ pub fn redo(self: *Self) error{Stop}![]const u8 { self.curr_history = h; self.root = h.root; self.push_undo(u); + self.mtime = std.time.milliTimestamp(); return h.meta; } diff --git a/src/buffer/Manager.zig b/src/buffer/Manager.zig index 910e389..26a1448 100644 --- a/src/buffer/Manager.zig +++ b/src/buffer/Manager.zig @@ -23,39 +23,47 @@ pub fn deinit(self: *Self) void { } pub fn open_file(self: *Self, file_path: []const u8) Buffer.LoadFromFileError!*Buffer { - if (self.buffers.get(file_path)) |buffer| { - return buffer; - } else { + const buffer = if (self.buffers.get(file_path)) |buffer| buffer else blk: { var buffer = try Buffer.create(self.allocator); errdefer buffer.deinit(); try buffer.load_from_file_and_update(file_path); try self.buffers.put(self.allocator, try self.allocator.dupe(u8, file_path), buffer); - return buffer; - } + break :blk buffer; + }; + buffer.update_last_used_time(); + return buffer; } pub fn open_scratch(self: *Self, file_path: []const u8, content: []const u8) Buffer.LoadFromStringError!*Buffer { - if (self.buffers.get(file_path)) |buffer| { - return buffer; - } else { + const buffer = if (self.buffers.get(file_path)) |buffer| buffer else blk: { var buffer = try Buffer.create(self.allocator); errdefer buffer.deinit(); try buffer.load_from_string_and_update(file_path, content); buffer.file_exists = true; try self.buffers.put(self.allocator, try self.allocator.dupe(u8, file_path), buffer); - return buffer; - } + break :blk buffer; + }; + buffer.update_last_used_time(); + return buffer; } -pub fn retire(self: *Self, buffer: *Buffer) void { - _ = self; - _ = buffer; +pub fn retire(_: *Self, buffer: *Buffer) void { + buffer.update_last_used_time(); } -pub fn list(self: *Self, allocator: std.mem.Allocator) []*const Buffer { - _ = self; - _ = allocator; - unreachable; +pub fn list(self: *Self, allocator: std.mem.Allocator) error{OutOfMemory}![]*const Buffer { + var buffers: std.ArrayListUnmanaged([]*const Buffer) = .{}; + var i = self.buffers.iterator(); + while (i.next()) |kv| + (try buffers.addOne()).* = kv.value_ptr.*; + + std.mem.sort(*Buffer, buffers.items, {}, struct { + fn less_fn(_: void, lhs: *Buffer, rhs: *Buffer) bool { + return lhs.mtime > rhs.mtime; + } + }.less_fn); + + return buffers.toOwnedSlice(allocator); } pub fn is_dirty(self: *const Self) bool {