summaryrefslogtreecommitdiff
path: root/src/output_pane.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-09 06:54:27 -0300
committerGabriel Schneider <[email protected]>2026-08-10 09:17:07 -0300
commit599dd82f96b9d091aae78300aa6c3fbc81f9eb69 (patch)
tree532d29eb0d79896cd730fb324df4866056306506 /src/output_pane.zig
parent628aa40f13e9bbd313b51ab625f193110aad8dd0 (diff)
downloadpardes-599dd82f96b9d091aae78300aa6c3fbc81f9eb69.tar.gz
pardes-599dd82f96b9d091aae78300aa6c3fbc81f9eb69.zip
review pass: fix the eaten Tab, drop the duplicated code, cover the gaps
Diffstat (limited to 'src/output_pane.zig')
-rw-r--r--src/output_pane.zig69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/output_pane.zig b/src/output_pane.zig
index bce3d503..1bf14b7c 100644
--- a/src/output_pane.zig
+++ b/src/output_pane.zig
@@ -236,6 +236,75 @@ pub fn open(p: *Pardes, id: usize, dir: []const u8, from: Origin, arg: []const u
return pane;
}
+/// Land a freshly produced list of rows in the buffer it belongs in — the one
+/// rule every results buffer follows, whichever side of the core made them.
+///
+/// The SAME command asked again REFILLS the list it already opened rather than
+/// stacking a byte-identical twin under the pane. That was runSearch's rule
+/// from the start (right-clicking a word in four places is one +Search walked
+/// four times) and language answers turned out to need it far more urgently:
+/// Tab after a dot makes a query an ordinary typing keystroke, and without the
+/// refill twenty of them fill every slot and the key is eaten for the rest of
+/// the session — see docs/lsp.md.
+///
+/// What "the same command" means comes off the ORIGIN. A search is identified
+/// by its PATTERN, so `foo`, `bar`, `foo` re-arms foo's own buffer and leaves
+/// bar's open; a language query is asked about a different symbol every time
+/// with the same (usually empty) arg, so the arg cannot tell two apart and the
+/// KIND is the natural unit — a second `gr` replaces the first list. Same
+/// directory only, because the rows are written relative to it, and never the
+/// asking pane itself (a `/` inside a +Search writes its own rows).
+///
+/// `content` is gpa-owned: adopted by the buffer, or freed here when there is
+/// nowhere to put it. `anchor` is the row n/N step from, null for the top.
+pub fn fillResults(p: *Pardes, id: usize, dir: []const u8, from: Origin, arg: []const u8, content: []u8, anchor: ?usize) void {
+ const pane = p.panes[id] orelse {
+ p.gpa.free(content);
+ return;
+ };
+ const by_arg = std.meta.activeTag(from) != .query;
+ for (p.panes, 0..) |slot, i| {
+ if (i == id) continue;
+ const rp = slot orelse continue;
+ const rf = if (rp.file) |*f| f else continue;
+ const o = if (rf.output) |*x| x else continue;
+ if (!std.meta.eql(o.from, from)) continue;
+ if (by_arg and !std.mem.eql(u8, o.arg(), arg)) continue;
+ if (!std.mem.eql(u8, std.fs.path.dirname(rf.path) orelse "", dir)) continue;
+ setArg(o, arg);
+ // a refill that changes NOTHING keeps its place: a right click on an
+ // already-armed word is an `n`, and throwing the list back to the top
+ // only to scroll down to the stepped row is a jump with no information
+ // in it.
+ const same = std.mem.eql(u8, rf.content, content);
+ file_pane.setContent(p, rf, content);
+ if (!same) rf.scroll = 0;
+ p.active = id;
+ if (traits(from).steps) {
+ pane.search_pane = i;
+ pane.search_row = anchor;
+ }
+ return;
+ }
+ const free = p.freeSlot() orelse {
+ p.gpa.free(content);
+ return;
+ };
+ const np = open(p, free, dir, from, arg, content) catch {
+ p.gpa.free(content);
+ return;
+ };
+ p.placeDoc(id, free, np);
+ p.active = id;
+ // prose is not a list of locations: n/N over a hover blurb would step to
+ // nowhere, so only stepping buffers arm the stepper — and WHICH command
+ // filled it is the buffer's own record, not a field on the asking pane.
+ if (traits(from).steps) {
+ pane.search_pane = free;
+ pane.search_row = anchor;
+ }
+}
+
/// The Jumplist builtin: the focus history (Pardes.jumps) written out as text,
/// one row per location, oldest first — the same `location text` shape every
/// results buffer here has, which is what buys n/N stepping and Look-on-a-row