From 12c257e624d3f1f80ca3df041b54026ff772d638 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Wed, 30 Sep 2026 14:53:46 -0300 Subject: A path typed with a leading ~ is the home directory, at every entry point that takes one, through one helper Only DumpDir (dump.zig) and ShaderBuild expanded `~/`, each its own way. So a look at `~/notes.txt`, `name ~/x`, `Save ~/x`, ThemeFile, Restore and a quoted `pardes '~/x'` all took `~` as a directory of that name under the pane's. There is now one rule, filesystem.expandHome. A leading `~`, alone or before `/` or `:`, is $HOME, else the passwd entry's home; `~user` is that user's (getpwnam). As in a shell, it applies even beside a file named `~`, and `./~` names that file. Every entry point runs its typed path through it: - look, B3 and 9P, before any parsing, so `~/x:12`, `~/x:12:3` and `~/x:/re/` all work; - name, and a tag's rename; - Save ; - ThemeFile, DumpDir, Restore and ShaderBuild's shader files; - the forwarding launch. Recent rows are not shown with `~` and need nothing. How names are shown is unchanged. Tests: expandHome's cases, and HOME unset (passwd), with HOME passed in rather than set, since setenv moves the environ a spawned child reads. fs.py covers Save into missing directories under `~`, `name ~/x`, a look at `~/x:3`, and a forwarded `pardes '~/x'`. Co-Authored-By: Claude Opus 5.5 --- src/main.zig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/main.zig') diff --git a/src/main.zig b/src/main.zig index 576efc8e..dfeed52d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -407,7 +407,7 @@ fn nativeMain(init: std.process.Init) !void { // itself, which is what a right click in that pane would have been. var look_buf: [64]u8 = undefined; const look = try std.fmt.bufPrint(&look_buf, "/pane/{d}/look", .{parent.serial}); - const word = positional orelse { + const typed_word = positional orelse { var tag_buf: [64]u8 = undefined; const tag = try std.fmt.bufPrint(&tag_buf, "/pane/{d}/tag", .{parent.serial}); const contents = ninep_io.Client.read(arena, parent.dial, tag, tag) catch |err| Refuse.with(init.io, tag, err); @@ -415,7 +415,10 @@ fn nativeMain(init: std.process.Init) !void { try std.Io.File.stderr().writeStreamingAll(init.io, nested_text); std.process.exit(1); }; - if (std.mem.indexOfAny(u8, word, "\r\n") != null) Refuse.with(init.io, "a file name", error.NotOneLine); + if (std.mem.indexOfAny(u8, typed_word, "\r\n") != null) Refuse.with(init.io, "a file name", error.NotOneLine); + // `pardes '~/x'`, quoted so the shell left it: home, as a look's. + var home_buf: [4096]u8 = undefined; + const word = pardes.filesystem.expandHome(typed_word, &home_buf); const target = @import("look.zig").parsePathLine(word); var realbuf: [4096]u8 = undefined; var newbuf: [4096]u8 = undefined; -- cgit v1.3