summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-10-01 05:10:37 -0300
committerGabriel Schneider <[email protected]>2026-10-01 05:18:09 -0300
commitd378de9c497f46090a3d0d30508f504eae5cd48f (patch)
treec8bc4bcc09836bd1062b9d7581de545b3fb6a112 /src/ninep
parentc95f2703875880e583dfbce5ce19c38faa3d5b76 (diff)
downloadpardes-d378de9c497f46090a3d0d30508f504eae5cd48f.tar.gz
pardes-d378de9c497f46090a3d0d30508f504eae5cd48f.zip
A pane ctl takes Tty+bash as exec and the tag do: a word that takes its argument after a + is no unknown control message there
checkBuiltin split a line at its first blank only, so `Tty+bash` was one unknown word on a ctl while exec ran it. It now splits at the + for the words whose registry entry says they take one so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/ctl.zig14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 1e274e0c..b7c529e1 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -471,7 +471,11 @@ fn blanked(line: []const u8, buf: []u8) []const u8 {
/// Answers the refusal, or null. Words are the builtins' own, capitalised
/// as on a tag; acme's lowercase verbs are the pane ctl's and alias none.
fn checkBuiltin(p: *Pardes, req: Req, line: []const u8, scope: builtins.Scope) ?Reply {
- const sp = std.mem.indexOfAny(u8, line, " \t");
+ var sp = std.mem.indexOfAny(u8, line, " \t");
+ // `Word+arg` for a word that takes one so (`Tty+bash`), as exec does.
+ if (sp == null) if (std.mem.indexOfScalar(u8, line, '+')) |at| if (std.meta.stringToEnum(Builtin, line[0..at])) |head| {
+ if (builtins.registry.plusArg(head)) sp = at;
+ };
const typed = line[0 .. sp orelse line.len];
// acme's words: checked as the pardes word they run as, or refused.
const word = for (pardes.exec.acme_words) |w| {
@@ -4081,3 +4085,11 @@ test "a body write to an image pane says its body takes none, not that terminals
doc.image = .{ .path = try p.gpa.dupe(u8, "/tmp/pardes-pic.ppm") };
try testing.expectEqualStrings(pane_files.e_no_body, wr(p, Node.of(doc.serial, .body), "x").reply.ename);
}
+
+test "Tty+bash on a pane ctl is Tty with its argument, as exec and the tag take it" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ const r = call(p, .{ .tag = 1, .op = .write, .node = Node.of(serialOf(p), .ctl), .data = "Tty+sh\n" });
+ try testing.expectEqual(Status.ok, r.reply.status);
+ try testing.expect(r.spawned);
+}