summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builtins.zig11
-rw-r--r--src/exec.zig8
-rw-r--r--src/pardes.zig3
3 files changed, 20 insertions, 2 deletions
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" {