From 2a842d241c462c11959102f96a3945aec493cb86 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 16:18:03 -0300 Subject: A click written back to event is done as the click, REPL and all; a REPL's ctl line names it Writing an M record back from a .py body with a REPL bound ran the text as a shell command (exit 127), where the click itself went to the REPL. acme does what the click would have done (xfideventwrite, xfid.c:842-844), so a body X record written back now goes the way a middle click goes: to a bound REPL, bracketed or line by line, the several-REPLs question included. An F record, a line written to exec, was never a click and still runs as a command. For a readable list of bindings, the smallest place: a bound terminal's ctl line ends with its id after current/notcurrent. Co-Authored-By: Claude Opus 5.5 --- src/ninep/events.zig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/ninep/events.zig') diff --git a/src/ninep/events.zig b/src/ninep/events.zig index 9ebb4bc1..cff42c55 100644 --- a/src/ninep/events.zig +++ b/src/ninep/events.zig @@ -468,7 +468,7 @@ pub fn notePtyOutput(p: *Pardes, id: usize, bytes: []const u8) void { p.fs.news = true; } -const EventRecord = struct { action: Action, q0: u32, q1: u32, text: ?[]const u8 = null }; +const EventRecord = struct { origin: u8, action: Action, q0: u32, q1: u32, text: ?[]const u8 = null }; const EventReader = struct { data: []const u8, @@ -478,6 +478,7 @@ const EventReader = struct { if (er.i >= er.data.len) return null; var i = er.i; if (i + 2 > er.data.len) return null; + const origin = er.data[i]; i += 1; const action = Action.fromChar(er.data[i]) orelse return null; i += 1; @@ -497,7 +498,7 @@ const EventReader = struct { } if (i >= er.data.len or er.data[i] != '\n') return null; er.i = i + 1; - return .{ .action = action, .q0 = q0, .q1 = q1, .text = text }; + return .{ .origin = origin, .action = action, .q0 = q0, .q1 = q1, .text = text }; } }; @@ -539,7 +540,12 @@ pub fn writeEvent(p: *Pardes, req: Req, id: usize) Reply { const said = if (r.q0 == r.q1) r.text orelse whole[lo..hi] else whole[lo..hi]; const text = p.scratch.allocator().dupe(u8, said) catch continue; switch (r.action) { - .body_exec, .tag_exec => _ = exec.execute(p, live, text), + // A body's click written back is done as the click would have + // been (acme's xfideventwrite, xfid.c:842-844): a REPL bound for + // it takes it. One that came from a write to exec (`F`) was + // never a click, and runs as the command it was. + .body_exec => _ = exec.executeFrom(p, live, text, r.origin != 'F'), + .tag_exec => _ = exec.execute(p, live, text), .body_look, .tag_look => look.lookAt(p, live, text), else => unreachable, } -- cgit v1.3