summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-03 13:30:15 -0300
committerGabriel Schneider <[email protected]>2026-09-03 13:30:15 -0300
commit3d8d4425c969d3df21915c9c14b144460a1c0086 (patch)
treef54635093525f610630a2ca850a73ecd2df7393e /src/main.zig
parente6c9f1726cca910c464fc807aefebc404c8e7a12 (diff)
downloadpardes-3d8d4425c969d3df21915c9c14b144460a1c0086.tar.gz
pardes-3d8d4425c969d3df21915c9c14b144460a1c0086.zip
boot: the errors pane keeps the launch directory, and a typo inside pardes stays one line
Two defects in the +Errors boot, both found by adversarial re-review. The pane was opened with `dir = ""` — copied from the board's boot buffer, which can afford it because that platform has no filesystem — so its path came out `/+Errors` and `paneDir` answered `/`. An output pane's directory is where a `Grep` from it walks, where its `Newtty` spawns a shell and what its `Save` prefills, so the boot screen rooted all three at the filesystem root, and the one word the pane prints resolved against `/` and could never be clicked. The launch directory rides in `Options.missing` beside the word now, and the test asserts the pane's path rather than only its contents. A typo INSIDE pardes stacked a second full-screen UI. The hand-off block above resolves the word and sends it to the outer instance; `.none` sent nothing and fell through, which was harmless while the classification below refused it and became the one input that stacks the UI that block exists to prevent — with no shell pane in it, so the only way out is `Del`. Its own comment said as much and was falsified by the +Errors boot. `.none` is refused in that shell now, in one line and without a stack trace, and the outer session is not told: `Look` on a word naming nothing is not something to do to somebody else's session. Also recorded, not fixed: the commonest permission case never reaches the `.dir` arm this arm's comment defends. `look.isDir` probes with O_DIRECTORY| O_RDONLY, so a directory you cannot read resolves as `.file` and dies in `file_pane.open` with `error.OpenFailed` out of `main` — still a trace at a human, and a different fault than the one fixed here. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_016Q4RATpafkwahrovHQLKRf
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig50
1 files changed, 42 insertions, 8 deletions
diff --git a/src/main.zig b/src/main.zig
index 92b59bc2..00eff433 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -305,8 +305,13 @@ fn nativeMain(init: std.process.Init) !void {
// rather than stacking a second full-screen UI inside one of its panes.
// The word is resolved here rather than sent raw because the outer
// instance resolves against ITS panes' directories, which are not ours.
- // A word naming nothing on disk sends nothing and falls through to the
- // classification below, which already refuses it — no second UI either way.
+ // A word naming nothing on disk is REFUSED HERE, in this shell, and does
+ // not fall through: the classification below used to refuse it too, and
+ // once it started booting an `+Errors` pane instead, a typo became the one
+ // input that stacked the second full-screen UI this whole block exists to
+ // prevent — and one with no shell pane in it, so the only way out is `Del`.
+ // The outer instance is not told either: `Look` on a word naming nothing
+ // is not something to do to somebody else's session.
//
// `--detach` is exempt for the same reason `--nested` is, arrived at from
// the other side: it stacks no UI at all. A detached session started from a
@@ -329,6 +334,17 @@ fn nativeMain(init: std.process.Init) !void {
.dir => |d| nested.sendLook(outer_pid, d, 0),
.file => |t| nested.sendLook(outer_pid, t.path, t.at.line),
.image => |t| nested.sendLook(outer_pid, t.path, 0),
+ // Nothing of that name. One line on this shell's stderr and out,
+ // which is what the paragraph above promises: the outer session is
+ // not disturbed and no UI is stacked. Said in words rather than
+ // returned as an error, because an error out of `main` is the
+ // stack trace this release stopped showing people for a typo.
+ .none => {
+ var buf: [4096]u8 = undefined;
+ const line = std.fmt.bufPrint(&buf, "pardes: file or directory not found: {s}\n", .{word}) catch "pardes: file or directory not found\n";
+ try std.Io.File.stderr().writeStreamingAll(init.io, line);
+ std.process.exit(1);
+ },
// an unreachable outer instance (an older build, a stale socket
// path) is not worth failing a launch over: run normally instead
else => false,
@@ -350,12 +366,30 @@ fn nativeMain(init: std.process.Init) !void {
.image => |t| opts.file = try arena.dupe(u8, t.path),
// Nothing of that name is there. A typo is not a reason to
// refuse to start: the session boots with one `+Errors` pane
- // naming what was asked for (pardes.zig `missing_path`). The
- // other arms stay `BadArgs` — a `.dir` here means `chdir`
- // refused a directory that IS one, which is a permission
- // problem and not a typo, and `.url`/`.pane` are targets no
- // launch can act on.
- .none => opts.missing_path = try arena.dupe(u8, a),
+ // naming what was asked for (pardes.zig `missing`).
+ //
+ // The LAUNCH DIRECTORY goes with it, and it is not decoration:
+ // an output pane's directory is where a `Grep` from it walks,
+ // where a `Newtty` spawns its shell and what a `Save` prefills.
+ // The first draft passed "" — copied from the board's boot
+ // buffer, which can afford it because that platform has no
+ // filesystem — and the pane came out at `/+Errors`, so `Grep`
+ // on the boot screen walked from the root of the filesystem.
+ //
+ // The other arms stay `BadArgs`. `.url` and `.pane` are targets
+ // no LAUNCH can act on, and `.dir` here is a directory that
+ // resolves but `chdir` refused, which is a permission problem
+ // rather than a typo. NOTE that the commonest permission case
+ // does not arrive here at all: `look.isDir` probes with
+ // `O_DIRECTORY|O_RDONLY`, so a directory you cannot read (say
+ // `/root`) fails that probe, resolves as `.file`, and dies in
+ // `file_pane.open` with `error.OpenFailed` out of `main` —
+ // still a stack trace at a human. Left as it was, because it is
+ // a different fault than the one this arm fixes.
+ .none => opts.missing = .{
+ .word = try arena.dupe(u8, a),
+ .dir = try arena.dupe(u8, std.mem.span(@as([*:0]u8, @ptrCast(cwd)))),
+ },
else => return error.BadArgs,
}
}