summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 17:58:05 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commitc5fcbc0cb9c1e76bb01283e9ccfa00ed5bc4bef8 (patch)
tree967ca08153c0385d5fc3e05a69468bee45dfa7b0
parent08c4a01f799ae250577d99a61f23eef7d66e439a (diff)
downloadpardes-c5fcbc0cb9c1e76bb01283e9ccfa00ed5bc4bef8.tar.gz
pardes-c5fcbc0cb9c1e76bb01283e9ccfa00ed5bc4bef8.zip
What a root ctl write says is the session's in the log, msg -, not the active pane's
A session builtin written to /ctl runs at the active pane, so its messages were logged under that pane's serial, as if the pane had said them. They are now `msg -`, and still shown on the active pane. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/Messages.zig2
-rw-r--r--src/fs.zig3
-rw-r--r--src/ninep/ctl.zig17
3 files changed, 21 insertions, 1 deletions
diff --git a/src/Messages.zig b/src/Messages.zig
index ea62041f..cc4b3656 100644
--- a/src/Messages.zig
+++ b/src/Messages.zig
@@ -407,7 +407,7 @@ pub fn blendRgb(from: [3]u8, to: [3]u8, amount: f32) [3]u8 {
fn logMessage(p: *Pardes, id: usize, text: []const u8) void {
if (text.len == 0) return;
- const serial: u32 = if (id < MAX_PANES) if (p.panes[id]) |pane| pane.serial else 0 else 0;
+ const serial: u32 = if (p.fs.session_write) 0 else if (id < MAX_PANES) if (p.panes[id]) |pane| pane.serial else 0 else 0;
const kept = text[0..@min(text.len, LoggedMessage.cap)];
// /log hears every one: a client that retried and failed the same way
// is waiting on that second line. Only the +Messages view collapses.
diff --git a/src/fs.zig b/src/fs.zig
index 2dc3394b..42d761ca 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -1260,6 +1260,9 @@ pub const Namespace = struct {
/// the first error one reports (`failure`) fails the write, as acme's
/// ctl answers a command's error (editors/acme/xfid.c:700).
no_prompt: bool = false,
+ /// The root ctl is running a session builtin: its messages are the
+ /// session's, logged `msg -`, though shown on the active pane.
+ session_write: bool = false,
refused: bool = false,
failure: [256]u8 = undefined,
failure_len: u16 = 0,
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 8b73e8f7..bb562672 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -344,6 +344,8 @@ pub fn writeRoot(p: *Pardes, req: Req) Reply {
continue;
}
if (p.panes[p.active] == null) return Reply.fail(req.tag, E.NOENT);
+ p.fs.session_write = true;
+ defer p.fs.session_write = false;
if (runBuiltin(p, req, p.active, line)) |refusal| return refusal;
}
}
@@ -742,6 +744,21 @@ test "a second lock is refused until the holder unlocks or closes, and binds nob
for (p.fs.opens) |o| try testing.expect(o.node == 0);
}
+test "a message from a root ctl write is the session's in the log" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ p.update(.tick); // the pane's `new` is logged before the log is opened
+ while (p.nextEffect()) |_| {}
+ const log = @intFromEnum(tree.TopFile.log);
+ const f = call(p, .{ .tag = 1, .op = .open, .node = log }).reply.handle;
+ const frozen = call(p, .{ .tag = 2, .op = .read, .node = log, .handle = f, .size = 8192 }).bytes.len;
+ _ = call(p, .{ .tag = 3, .op = .write, .node = log, .handle = f, .data = "follow" });
+ try testing.expectEqual(Status.ok, wr(p, @intFromEnum(tree.TopFile.ctl), "Kill\n").reply.status);
+ // The builtin's name, then what it said: both the session's.
+ try testing.expectEqualStrings("msg - Kill\n", call(p, .{ .tag = 4, .op = .read, .node = log, .handle = f, .off = frozen, .size = 4096 }).bytes);
+ try testing.expectEqualStrings("msg - Kill: nothing running\n", call(p, .{ .tag = 5, .op = .read, .node = log, .handle = f, .off = frozen, .size = 4096 }).bytes);
+}
+
test "a look takes acme's :addr and file:addr, and a miss changes nothing" {
const gpa = testing.allocator;
const p = try withFile(gpa, "foo x foo y\nbar\n");