---
src/Dir.zig | 9 +++++++++
src/DirMap.zig | 14 ++++++++++++++
src/File.zig | 13 +++++++++----
src/UserInterface.zig | 10 +++++++++-
4 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/src/Dir.zig b/src/Dir.zig
index 376cb66..ab59f27 100644
--- a/src/Dir.zig
+++ b/src/Dir.zig
@@ -52,6 +52,15 @@ pub fn init(self: *Self, map: *DirMap, alloc: mem.Allocator, dir: fs.Dir, name:
file.kind = entry.kind;
file.mark = false;
file.text = null;
+
+ if (file.kind == .SymLink) {
+ var buf: [1024]u8 = undefined;
+ const target_path = try dir.readLink(entry.name, &buf);
+ file.target_path = try alloc.dupeZ(u8, target_path);
+ } else {
+ file.target_path = try alloc.dupeZ(u8, "");
+ }
+
file.id = map.genId();
file.updateStats();
}
diff --git a/src/DirMap.zig b/src/DirMap.zig
index 64336b1..4f3d5ef 100644
--- a/src/DirMap.zig
+++ b/src/DirMap.zig
@@ -489,8 +489,22 @@ fn addNewFileToDir(self: *Self, dir: *Dir, name: []const u8) !void {
.id = self.genId(),
.stat = undefined,
.kind = undefined,
+ .lstat = undefined,
+ .target_path = undefined,
};
f.updateStats();
+
+ if (f.kind == .SymLink) {
+ var fs_dir = try fs.openDirAbsolute(dir.name, .{});
+ defer fs_dir.close();
+
+ var buf: [1024]u8 = undefined;
+ const target_path = try fs_dir.readLink(name, &buf);
+ f.target_path = try alloc.dupeZ(u8, target_path);
+ } else {
+ f.target_path = try alloc.dupeZ(u8, "");
+ }
+
try dir.files.append(alloc, f);
// If the dir is visible, we need to update the DirView.
diff --git a/src/File.zig b/src/File.zig
index 385ec23..360e604 100644
--- a/src/File.zig
+++ b/src/File.zig
@@ -37,21 +37,25 @@ text: ?bool,
id: usize,
stat: os.system.Stat,
+// usefull only if kind == .SymLink
+lstat: os.system.Stat,
+target_path: [:0]const u8,
+
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;
+ _ = os.system.lstat(self.name, &self.lstat);
} else {
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;
+ _ = os.system.lstat(path, &self.lstat);
}
+ self.kind = fileKindFromStatMode(self.lstat.mode);
+ self.text = null;
}
fn fileKindFromStatMode(mode: u32) fs.Dir.Entry.Kind {
@@ -71,6 +75,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);
+ alloc.free(self.target_path);
}
pub fn rename(self: *Self, new_name: []const u8) !void {
diff --git a/src/UserInterface.zig b/src/UserInterface.zig
index 32c7c96..c07c891 100644
--- a/src/UserInterface.zig
+++ b/src/UserInterface.zig
@@ -509,7 +509,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.target_path.len < try rpw.getRemaining()) {
+ try writer.print("{s} -> {s}", .{ file.name, file.target_path });
+ } else {
+ try writer.print("-> {s}", .{file.target_path});
+ }
+ } else {
+ try writer.writeAll(file.name);
+ }
if (file.kind == .Directory) {
try writer.writeByte('/');
}
--
2.38.1
Thanks for working on this! Managed to find some review time today
already.
On Sun Oct 23, 2022 at 8:24 PM CEST, Andrea Feletto wrote:
> +
> + if (file.kind == .SymLink) {
> + var buf: [1024]u8 = undefined;
> + const target_path = try dir.readLink(entry.name, &buf);
> + file.target_path = try alloc.dupeZ(u8, target_path);
> + } else {
> + file.target_path = try alloc.dupeZ(u8, "");
> + }
> +
* This should probably live inside of File.updateStats().
* The target of a link can change, so check if file.target_path
already has a string and free that.
* Should probably be nullable for the above point.
* Rename target_path to link_target.
> + .lstat = undefined,
> + .target_path = undefined,
Since we get the target path with dir.readLink(), we don't need lstat
anymore, I think.
> };
> f.updateStats();
> +
> + if (f.kind == .SymLink) {
> + var fs_dir = try fs.openDirAbsolute(dir.name, .{});
> + defer fs_dir.close();
> +
> + var buf: [1024]u8 = undefined;
> + const target_path = try fs_dir.readLink(name, &buf);
> + f.target_path = try alloc.dupeZ(u8, target_path);
> + } else {
> + f.target_path = try alloc.dupeZ(u8, "");
> + }
> +
Can be removed if this logic is moved to File.updateStats().
> + if (file.kind == .SymLink) {
> + if (file.name.len + " -> ".len + file.target_path.len < try rpw.getRemaining()) {
You can get roughly the same result a bit simpler by just checking if the
combined lengths are longer than the width variable.
Friendly greetings,
Leon Henrik Plickat