~leon_plickat/nfm

draw both source and target for symlinks v2 PROPOSED

Andrea Feletto: 1
 draw both source and target for symlinks

 4 files changed, 39 insertions(+), 20 deletions(-)
Export patchset (mbox)
How do I use this?

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 -3
Learn more about email & git

[PATCH v2] draw both source and target for symlinks Export this patch

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