diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 14:39:52 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | def16a1bc1c71d2fdcc7954e2ddec1384c2f05f7 (patch) | |
| tree | a84c6f05f83f12efdafb57bf9c091f840eb6e0e9 | |
| parent | 0f18cc317190c2aaaf0efec4cd6da656cb1f3402 (diff) | |
| download | pardes-def16a1bc1c71d2fdcc7954e2ddec1384c2f05f7.tar.gz pardes-def16a1bc1c71d2fdcc7954e2ddec1384c2f05f7.zip | |
Only Tty reads Word+arg as its argument
Every builtin that takes an argument split a word at its first +, so
Dump+2024.zon ran Dump with 2024.zon. A builtin now opts in with plus_arg,
read by the registry, and only Tty does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
| -rw-r--r-- | docs/tags.md | 7 | ||||
| -rw-r--r-- | src/builtins.zig | 11 | ||||
| -rw-r--r-- | src/exec.zig | 8 | ||||
| -rw-r--r-- | src/pardes.zig | 3 |
4 files changed, 24 insertions, 5 deletions
diff --git a/docs/tags.md b/docs/tags.md index 2f68bc0d..f1d7794d 100644 --- a/docs/tags.md +++ b/docs/tags.md @@ -7,9 +7,10 @@ pane (or its first pane when focus comes from another column). This makes `New` appears only in the column tag by default; pane tags keep their own save, terminal, close, and collapse commands. `Tty` opens a new embedded terminal. In a terminal's own tag the word names the shell it runs, `Tty+fish`, tinted -with the tag's name colour: `Word+arg` is one word a tag can hold for -`Word arg`, so clicking it opens another terminal on that shell, as `Tty -fish` would. A command pane's tag reads `<dir> (<line>) running` or `exit N` +with the tag's name colour: `Tty+arg` is one word a tag can hold for `Tty +arg`, so clicking it opens another terminal on that shell, as `Tty fish` +would. Only a builtin that declares `plus_arg` reads a `+` so; `Tty` is the +one, since other arguments (a dump's name) may contain `+`. A command pane's tag reads `<dir> (<line>) running` or `exit N` and offers `Kill`. Pane and column command text leave a small gap after their aligned drag grips. GUI pane mode symbols are centered by their visible ink; changing the font or diff --git a/src/builtins.zig b/src/builtins.zig index 02787cf5..4815a114 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -145,6 +145,16 @@ pub const registry = struct { return true; } + /// Whether the word takes its argument joined by a `+` as one word a + /// tag can hold and a click take whole (`Tty+fish`). Only a builtin + /// that says `pub const plus_arg = true;`: others have arguments a `+` + /// may be in (`Dump+2024.zon` is a name, not Dump's argument). + pub fn plusArg(b: Builtin()) bool { + inline for (manualBuiltinList(), 0..) |T, i| + if (@intFromEnum(b) == i) return @hasDecl(T, "plus_arg") and T.plus_arg; + return false; + } + /// Whether the word means nothing without its argument (`Mount`, /// `Msg`, a setting's value), or would ask for it at a prompt (`Find`): /// a ctl refuses it bare before any line of the write runs. A builtin @@ -822,6 +832,7 @@ pub const DelBelow = struct { /// the one named, `Tty fish`, as a terminal's own tag word `Tty+fish` says. pub const Tty = struct { pub const takes_arg = true; + pub const plus_arg = true; pub fn run(c: Ctx) void { exec.spawnTty(c.p, c.id); const arg = c.arg orelse return; diff --git a/src/exec.zig b/src/exec.zig index 86adfeeb..86dba32a 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -488,8 +488,12 @@ pub fn commandText(txt: []const u8) []const u8 { pub fn executeBuiltinLine(p: *Pardes, id: usize, txt: []const u8) bool { const cmd = commandText(txt); if (cmd.len == 0 or p.exec_depth >= max_exec_depth) return false; - // `Word arg`, or as one word a tag can hold, `Word+arg` (`Tty+fish`). - const sp = std.mem.indexOfAny(u8, cmd, " \t") orelse std.mem.indexOfScalar(u8, cmd, '+'); + // `Word arg`, or for a word that says so, `Word+arg` (`Tty+fish`). + const plus = std.mem.indexOfScalar(u8, cmd, '+'); + var sp = std.mem.indexOfAny(u8, cmd, " \t"); + if (sp == null) if (plus) |at| if (std.meta.stringToEnum(Builtin, cmd[0..at])) |head| { + if (builtins.registry.plusArg(head)) sp = at; + }; const bi: ?Builtin = std.meta.stringToEnum(Builtin, cmd) orelse blk: { const head = std.meta.stringToEnum(Builtin, cmd[0 .. sp orelse break :blk null]) orelse break :blk null; break :blk if (builtins.registry.takesArg(head)) head else null; diff --git a/src/pardes.zig b/src/pardes.zig index 7863e272..74554e0d 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -1400,6 +1400,9 @@ test "Tty+fish, one word a tag can hold, opens a terminal on that shell" { try std.testing.expectEqualStrings("fish", p.panes[p.active].?.shell.?); p.acknowledgeShell(p.active, "/usr/bin/fish", true); try std.testing.expect(std.mem.startsWith(u8, tagline.curTail(p.panes[p.active].?), " Tty+fish ")); + // Only a word that says so splits at `+`: `Dump+x.zon` is no Dump. + try std.testing.expect(!p.executeBuiltinLine(0, "Dump+x.zon")); + try std.testing.expect(!p.executeBuiltinLine(0, "Msg+hello")); } test "a command pane shows how its command ended, and the next command there runs below it" { |
