diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 09:45:38 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 157df8cb547ba4cf900b1f9eb75df15384985708 (patch) | |
| tree | 248a415fe9431989e9468ef001a1dd364e249afe /src/look.zig | |
| parent | 2c03f710535a0b0aa143cd6c1fad04a45857a777 (diff) | |
| download | pardes-157df8cb547ba4cf900b1f9eb75df15384985708.tar.gz pardes-157df8cb547ba4cf900b1f9eb75df15384985708.zip | |
A served-tree pane spoils no Grep, and `look .` from a gone directory is ENOENT
A pane named `/virtual` gave Grep the root `/`, which swallowed every
other pane's directory and ran out of walk before any file: every Grep
missed. Grep passes over panes of the served tree. And `.` from a pane
whose directory was gone resolved to the served tree's root (/virtual/),
or through the jump list to another pane's directory: a dot path is the
looking pane's own, and gone it fails, `look: <dir>: no such directory`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/look.zig')
| -rw-r--r-- | src/look.zig | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/src/look.zig b/src/look.zig index fa86aee4..9a81a5c9 100644 --- a/src/look.zig +++ b/src/look.zig @@ -593,7 +593,11 @@ pub fn runSearch(p: *Pardes, id: usize, pat_raw: []const u8, kind: Search, start var nroots: usize = 0; for (p.panes) |slot| { const pp = slot orelse continue; - const d = Pardes.paneDir(pp); + // A pane of the served tree (/virtual/, /n/<peer>/) has no + // directory on this host to walk, and one that named `/` would + // swallow every other root: passed over. + const d = filesystem.localPath(Pardes.paneDir(pp)) orelse continue; + if (filesystem.isVirtual(if (pp.file) |f| f.path else d)) continue; var covered = false; var k: usize = 0; while (k < nroots) { @@ -1107,7 +1111,8 @@ fn resolveLookTarget(p: *Pardes, id: usize, txt: []const u8, realbuf: *[4096]u8) if (openPaneTarget(p, j, pl.at)) |target| return target; } found = resolve(p, txt, dir, realbuf); - if (found != .none or pl.path.len == 0 or pl.path[0] == '/') break; + // `.`, `..`, `./x` are this pane's directory's, not another's. + if (found != .none or pl.path.len == 0 or pl.path[0] == '/' or filesystem.dotRelative(pl.path)) break; } return found; } @@ -1407,6 +1412,13 @@ pub fn lookAt(p: *Pardes, id: usize, operand: []const u8) void { } switch (found) { .none => { + // `.` or `..` from a pane whose directory is gone: said, ENOENT, + // not searched for as a word. + if (filesystem.dotRelative(trimmed)) { + const dir = Pardes.paneDir(pane); + var said: [4200]u8 = undefined; + return p.reportFailure(id, std.fmt.bufPrint(&said, "look: {s}: no such directory", .{dir[0..@min(dir.len, 4096)]}) catch "look: no such directory"); + } // A raw terminal's clicks are its program's; a look written over // 9P is no keyboard input, and searches whatever the key mode. if (pane.image != null or (pane.body.mode == .tty and !p.fs.serving)) return; @@ -1439,6 +1451,12 @@ pub fn lookAt(p: *Pardes, id: usize, operand: []const u8) void { }, .url => |u| if (u.len <= 256) p.emit(.{ .open_link = .from(u) }), .dir => |dir| { + // A directory that is not there (the pane's own, gone): said, + // ENOENT, no terminal made in it. + if (comptime pardes.hosted) if (filesystem.localPath(dir)) |local| if (!exec.isDirectory(local)) { + var said: [4200]u8 = undefined; + return p.reportFailure(id, std.fmt.bufPrint(&said, "look: {s}: no such directory", .{dir[0..@min(dir.len, 4096)]}) catch "look: no such directory"); + }; for (p.panes, 0..) |slot, i| { if (slot) |tt| if (std.mem.eql(u8, tt.cwdSlice(), dir) and exec.takesCommandLine(p, i)) { clearNavigationSelection(p, tt); |
