diff options
Diffstat (limited to 'src/pardes.zig')
| -rw-r--r-- | src/pardes.zig | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index b64b62d7..8c643be6 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -5841,6 +5841,17 @@ pub const Options = struct { /// not consulted at all (it never was — the file arm always won). file: ?[]const u8 = null, file_line: usize = 0, + /// argv NAMED SOMETHING THAT IS NOT THERE — no file, no directory, nothing + /// `look.resolve` could make a target of. The word as the human typed it, + /// and it boots one `+Errors` pane saying so. + /// + /// A launch is not a failure worth refusing. `pardes nosuchfile` used to + /// return `BadArgs` out of `main`, which std prints as `error: BadArgs` + /// with a return trace under it — indistinguishable from a crash for a + /// typo, and it left the human with no editor at all. Outranked by `file` + /// for the same reason `file` outranks `shells`: only one of them can name + /// the boot layout, and they are never both set. + missing_path: ?[]const u8 = null, tty_toggle: u21 = config.tty_toggle_default, /// load a dump of another instance instead of spawning shells (acme -l) load_path: ?[]const u8 = null, @@ -6322,6 +6333,28 @@ pub const Pardes = struct { p.ncol = 1; p.col_n[0] = 1; p.col_terms[0][0] = 0; + } else if (opts.missing_path) |word| { + // ARGV NAMED NOTHING. `+Errors` and not the message row, because a + // launch has no pane to put a message row on yet — and because + // this is exactly what acme's `+Errors` is: output from the + // program rather than from a word anybody clicked (output_pane + // `Origin.errors`). Filling the window with it makes the answer + // unmissable, which a one-line message under a shell prompt is + // not. + // + // The word AS TYPED, not a resolved path: there is nothing to + // resolve, and `pardes ~/notes/tdoo.md` wants to see its own typo + // back rather than an absolute path built around it. + const content = try std.fmt.allocPrint( + gpa, + "file or directory not found\n\n\t{s}\n", + .{word}, + ); + errdefer gpa.free(content); + _ = try output_pane.open(p, 0, "", .errors, "", content); + p.ncol = 1; + p.col_n[0] = 1; + p.col_terms[0][0] = 0; } else if (comptime platform == .esp32p4) { // BARE METAL BOOTS AN EMPTY OUTPUT BUFFER, and a shell is not a layout preference // here but an impossibility: there is no operating system under this, so there is @@ -16419,6 +16452,26 @@ test "Esc alternates between two panes of the SAME kind" { } } +test "argv naming nothing boots an errors pane rather than failing the launch" { + const gpa = std.testing.allocator; + const p = try Pardes.init(gpa, .{ .cols = 80, .rows = 24, .missing_path = "notes/tdoo.md" }); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 80, .rows = 24 } }); + + // One pane, filling the window, and it is an OUTPUT pane rather than the + // shell a bare `pardes` boots: the answer is the whole screen. + try std.testing.expectEqual(@as(u8, 1), p.ncol); + try std.testing.expectEqual(@as(usize, 1), p.col_n[0]); + const pane = p.panes[0].?; + try std.testing.expect(!pane.isTerminal()); + const f = pane.file.?; + try std.testing.expectEqual(output_pane.Origin.errors, f.output.?.from); + // ...and it says what happened AND what was asked for. The word as typed, + // which is the half a bare "not found" leaves out. + try std.testing.expect(std.mem.indexOf(u8, f.content, "not found") != null); + try std.testing.expect(std.mem.indexOf(u8, f.content, "notes/tdoo.md") != null); +} + test "Esc back into a tty leaves its view at the prompt" { if (platform == .web) return; const gpa = std.testing.allocator; |
