From fb330ce04c4eec4de317637d26310b74e2ee5923 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Thu, 1 Oct 2026 06:22:44 -0300 Subject: A Rename that previews other files answers its preview pane to the 9P write that asked it, and says on the message row that it previewed and applied nothing A multi-file Rename filled a +Search preview but the waiting exec write answered the pane it was asked from, and nothing was said. lspResponse now notes the pane it filled (fs.lsp_result); the write that waited for the answer reads that pane back, as a look or an exec answers the pane it went to, and the message row says `Rename: N edit(s) across files, previewed, not applied`. Co-Authored-By: Claude Opus 5.5 --- src/9p_io.zig | 13 +++++++++++++ src/fs.zig | 3 +++ src/ninep/ctl.zig | 12 ++++++++++++ src/pardes.zig | 9 +++++++++ 4 files changed, 37 insertions(+) (limited to 'src') diff --git a/src/9p_io.zig b/src/9p_io.zig index ea3f799c..a4340ddf 100644 --- a/src/9p_io.zig +++ b/src/9p_io.zig @@ -317,7 +317,20 @@ pub const Listener = struct { if (core.effects_len != 0) pardes.turn.awaitSettled(epoch); if (core.fs.lsp_answer_at) |n| { core.fs.lsp_answer_at = null; + core.fs.lsp_result = null; pardes.turn.awaitLsp(n); + // The answer filled a pane (a Rename's preview): that is what + // this write's open reads back, as look and exec answer. + if (l.core == core) if (core.fs.lsp_result) |serial| { + core.fs.lsp_result = null; + core.fs.results[0] = serial; + core.fs.results_len = 1; + if (pardes.ctlfs.openOf(core, req)) |o| { + o.results.list[0] = serial; + o.results.len = 1; + o.results.read = 0; + } + }; } core.fs.write_waits = false; // ponytail: one slot, so a failure of another client's effects that diff --git a/src/fs.zig b/src/fs.zig index 0c04e873..7d6b0d71 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -1529,6 +1529,9 @@ pub const Namespace = struct { /// A 9P write asked a language server something: the answer count it /// waits to change (`turn.lsp_answers`), so its failure is the write's. lsp_answer_at: ?u64 = null, + /// The pane a language answer filled (a Rename's preview): what the + /// waiting 9P write answers once it is in (9p_io). + lsp_result: ?u32 = null, /// The most a Twrite of the request being served can carry (msize less /// its header), 0 when unknown: a write shorter than it is the whole of /// what its client wrote, one that fills it may be cut and go on. diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index b17f150a..f0dab28d 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -4105,3 +4105,15 @@ test "Tty+bash on a pane ctl is Tty with its argument, as exec and the tag take try testing.expectEqual(Status.ok, r.reply.status); try testing.expect(r.spawned); } + +test "a Rename that reaches other files previews them, says so, and is the pane a waiting write answers" { + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + const id = p.active; + p.fs.lsp_result = null; + p.lspRequest(id, .rename, "sum"); + p.lspResponse(p.lsp_wait.?.id, "lib.rs:2:8 sum\nmain.rs:4:13-15 sum\n"); + const preview = p.panes[p.panes[id].?.search_pane.?].?; + try testing.expectEqual(preview.serial, p.fs.lsp_result.?); + try testing.expect(th.logHas(p, "Rename: 2 edit(s) across files, previewed, not applied")); +} diff --git a/src/pardes.zig b/src/pardes.zig index f5001797..ca0980f4 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -6764,6 +6764,15 @@ pub const Pardes = struct { p.reportError(w.pane, "language response", err); return; }; + // What a 9P write that asked it answers: the pane the rows are in + // (a multi-file Rename's preview), not the pane it was asked from. + if (pane.search_pane) |rid| if (p.panes[rid]) |rp| { + p.fs.lsp_result = rp.serial; + }; + if (w.kind == .rename) { + var said_buf: [96]u8 = undefined; + p.setMessage(w.pane, std.fmt.bufPrint(&said_buf, "Rename: {d} edit(s) across files, previewed, not applied", .{nrows}) catch "Rename: previewed"); + } if (panes.Output.traits(from).jumps) { const result = p.panes[pane.search_pane orelse return] orelse return; const file = pane.file orelse return; -- cgit v1.3