[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