summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig39
1 files changed, 29 insertions, 10 deletions
diff --git a/src/pardes.zig b/src/pardes.zig
index 9b21ec79..0c7c0363 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -3857,15 +3857,29 @@ pub const Pardes = struct {
// still gets its own buffer, and that IS the old rule: two searches are
// two lists, both stay open at their sizes, and the new one stacks
// directly below this pane (placeDoc). Focus stays here either way.
- if (output_pane.resultsFrom(p, pane, from)) {
- const rp = p.panes[pane.search_pane.?].?;
- const rf = &rp.file.?;
- if (std.mem.eql(u8, rf.output.?.arg(), pat)) {
- file_pane.setContent(p, rf, content);
- rf.scroll = 0;
- pane.search_row = anchor;
- return;
- }
+ // ...and it is ANY open list this search already filled, not only the
+ // one n/N are armed on: search `foo`, then `bar`, then `foo` again and
+ // the third search re-arms foo's own buffer rather than opening its
+ // identical twin below it. Same directory only — the rows are written
+ // relative to it, so another dir's list is a different list. Never the
+ // searching pane itself (a `/` inside a +Search writes its own rows).
+ 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 = rf.output orelse continue;
+ if (!std.meta.eql(o.from, from) or !std.mem.eql(u8, o.arg(), pat)) continue;
+ if (!std.mem.eql(u8, std.fs.path.dirname(rf.path) orelse "", dir)) continue;
+ // 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;
+ pane.search_pane = i;
+ pane.search_row = anchor;
+ return;
}
const free = p.freeSlot() orelse {
p.gpa.free(content);
@@ -3910,7 +3924,12 @@ pub const Pardes = struct {
rp.cur_row = r;
rp.cur_col = 0;
rp.cur_pinned = true;
- rp.ensureCursorVisible();
+ // in view, but WITHOUT scrolloff: a results pane is short, and a
+ // three-row margin on a seven-row one means every single n scrolls the
+ // list out from under the eye. A row already on screen moves nothing.
+ const off = rp.scroll();
+ const last = off + @as(i32, rp.rows) - 1;
+ if (r < off) rp.scrollBy(r - off) else if (r > last) rp.scrollBy(r - last);
const ln = modal.lineSlice(rf.content, @intCast(step));
// Both arms are the BUILTIN, run on the results pane — the same call a
// middle or right click on that row would make, so a stepped row and a