Andrea Feletto: 1 draw both source and target for symlinks 4 files changed, 39 insertions(+), 20 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~leon_plickat/nfm/patches/36336/mbox | git am -3Learn more about email & git
--- src/Dir.zig | 2 +- src/DirMap.zig | 9 +++++---- src/File.zig | 37 ++++++++++++++++++++++++------------- src/UserInterface.zig | 11 +++++++++-- 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/Dir.zig b/src/Dir.zig index 376cb66..efd8b38 100644 --- a/src/Dir.zig +++ b/src/Dir.zig @@ -53,7 +53,7 @@ pub fn init(self: *Self, map: *DirMap, alloc: mem.Allocator, dir: fs.Dir, name: file.mark = false; file.text = null; file.id = map.genId(); - file.updateStats(); + try file.updateStats(); } if (builtin.os.tag == .linux) { diff --git a/src/DirMap.zig b/src/DirMap.zig index 64336b1..65a05c8 100644 --- a/src/DirMap.zig +++ b/src/DirMap.zig @@ -470,7 +470,7 @@ fn addNewFileToDir(self: *Self, dir: *Dir, name: []const u8) !void { for (dir.files.items) |file, i| { if (mem.eql(u8, file.name, name)) { const f = &dir.files.items[i]; - f.updateStats(); + try f.updateStats(); if (file.dir.visible) { context.ui.list_dirty = true; @@ -488,9 +488,10 @@ fn addNewFileToDir(self: *Self, dir: *Dir, name: []const u8) !void { .text = null, .id = self.genId(), .stat = undefined, - .kind = undefined, + .kind = .Unknown, + .link_target = undefined, }; - f.updateStats(); + try f.updateStats(); try dir.files.append(alloc, f); // If the dir is visible, we need to update the DirView. @@ -742,7 +743,7 @@ fn handleInotifyStatChange(self: *Self, ev: *const os.linux.inotify_event, ptr: for (dir.files.items) |*file| { if (mem.eql(u8, basename, file.name)) { std.log.scoped(.inotify).debug(" -> found the file, updating stats", .{}); - file.updateStats(); + try file.updateStats(); if (dir.visible) context.ui.list_dirty = true; } } diff --git a/src/File.zig b/src/File.zig index 385ec23..0160efa 100644 --- a/src/File.zig +++ b/src/File.zig @@ -37,20 +37,30 @@ text: ?bool, id: usize, stat: os.system.Stat, -pub fn updateStats(self: *Self) void { - if (self.dir.visible and context.dirmap.dirViewByDir(self.dir) == context.dirmap.focusedDirView().?) { - // The file is in our current cwd. - _ = os.system.stat(self.name, &self.stat); - self.kind = fileKindFromStatMode(self.stat.mode); - self.text = null; - } else { +has_link_target: bool = false, +link_target: []const u8, + +pub fn updateStats(self: *Self) !void { + const alloc = context.gpa.allocator(); + + if (self.has_link_target) alloc.free(self.link_target); + self.has_link_target = false; + self.text = null; + + const path = try fmt.allocPrintZ(alloc, "{s}/{s}", .{ self.dir.name, self.name }); + defer alloc.free(path); + + _ = os.system.lstat(path, &self.stat); + self.kind = fileKindFromStatMode(self.stat.mode); + + if (self.kind == .SymLink) { + var file_dir = try fs.openDirAbsolute(self.dir.name, .{}); + defer file_dir.close(); + var buf: [1024]u8 = undefined; - var fba = heap.FixedBufferAllocator.init(buf[0..]); - const falloc = fba.allocator(); - const path = fmt.allocPrintZ(falloc, "{s}/{s}", .{ self.dir.name, self.name }) catch return; - _ = os.system.stat(path, &self.stat); - self.kind = fileKindFromStatMode(self.stat.mode); - self.text = null; + const target = file_dir.readLink(self.name, &buf) catch return; + self.link_target = try alloc.dupe(u8, target); + self.has_link_target = true; } } @@ -71,6 +81,7 @@ fn fileKindFromStatMode(mode: u32) fs.Dir.Entry.Kind { pub fn deinit(self: *const Self) void { const alloc = context.gpa.allocator(); alloc.free(self.name); + if (self.kind == .SymLink) alloc.free(self.link_target); } pub fn rename(self: *Self, new_name: []const u8) !void { diff --git a/src/UserInterface.zig b/src/UserInterface.zig index 32c7c96..31bb65e 100644 --- a/src/UserInterface.zig +++ b/src/UserInterface.zig @@ -459,7 +459,6 @@ fn drawRightMessage(rc: *spoon.Term.RenderContext, y: usize, x: usize, width: us } fn drawFileName(_: *Self, rc: *spoon.Term.RenderContext, y: usize, x: usize, _width: usize, file: *File, selected: bool) !void { - // TODO Draw '->target' after name of links if (selected) { try rc.setAttribute(switch (file.kind) { .Directory => context.config.theme.getAttribute("directory_sel", .{ .bold = file.mark }), @@ -509,7 +508,15 @@ fn drawFileName(_: *Self, rc: *spoon.Term.RenderContext, y: usize, x: usize, _wi var rpw = rc.restrictedPaddingWriter(width); const writer = rpw.writer(); try writer.writeAll(prefix); - try writer.writeAll(file.name); + if (file.kind == .SymLink) { + if (file.name.len + " -> ".len + file.link_target.len < try rpw.getRemaining()) { + try writer.print("{s} -> {s}", .{ file.name, file.link_target }); + } else { + try writer.print("-> {s}", .{file.link_target}); + } + } else { + try writer.writeAll(file.name); + } if (file.kind == .Directory) { try writer.writeByte('/'); } -- 2.38.1
Thanks! This works great! There were just two minor things left, but I decided to just change them myself quickly so that we can merge this feature to master already. Friendly greetings, Leon Henrik Plickat