summaryrefslogtreecommitdiff
path: root/src/layout.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-24 10:06:08 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit3f6ad1bc30570348297ae4aa6d1fd676de229a09 (patch)
treeb52037635072e90e0ff20c80a15c5d18c578d445 /src/layout.zig
parent82c4f9e7212f569d6343dd03ddbab3520a784993 (diff)
downloadpardes-3f6ad1bc30570348297ae4aa6d1fd676de229a09.tar.gz
pardes-3f6ad1bc30570348297ae4aa6d1fd676de229a09.zip
Ask from the keyboard which neighbour a closed pane's rows go to
Del takes a side: `Del k` gives the closed pane's rows to the nearest expanded pane above it, `Del j` to the one below, each falling back to the other side when it has none. DelAbove and DelBelow are those two lines, with no path of their own under SPC. A bare Del started from a key -- SPC d, Enter on the tag word, a row run from an output buffer -- on a pane with expanded panes both above and below asks instead of guessing. The question is a prompt like Save's or a search's (Pane.Prompt.del_side), so it is painted on the pane's notice band by the same path, and the next key answers it before any mode sees it: k or Up, j or Down, anything else keeps the pane, as does a click. Only a key press sets Pardes.can_ask, so a click, a 9P ctl or event write, a startup line, a restore and a shell exiting all close the pane at once, the rows going where layout.absorbVWeight has always sent them. A collapsed pane is not asked about (it has only a tag row to give), and collapsed neighbours are passed over (layout.expandedNeighbor, which Collapse now uses too). removePane and absorbVWeight take the recipient; every other caller passes null. Three scripts that closed a middle pane with SPC d answer k, which is where the rows went before, and their goldens are unchanged. delask.snap covers the question, Esc, j, a clicked DelBelow and a clicked Del. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Diffstat (limited to 'src/layout.zig')
-rw-r--r--src/layout.zig29
1 files changed, 17 insertions, 12 deletions
diff --git a/src/layout.zig b/src/layout.zig
index 3637f30e..116a64b8 100644
--- a/src/layout.zig
+++ b/src/layout.zig
@@ -995,7 +995,7 @@ pub fn splitColumn(p: *Pardes, source_id: usize, id: usize, before: bool) bool {
if (needs_rebase) old_weight *= 2;
if (id == source_id) {
if (p.col_n[source_col] <= 1) return false;
- absorbVWeight(p, id);
+ absorbVWeight(p, id, null);
removePane(p, id);
} else if (findPane(p, id) != null) return false;
@@ -1033,13 +1033,16 @@ pub fn snapColWeights(p: *Pardes, c: usize) void {
}
}
-pub fn absorbVWeight(p: *Pardes, id: usize) void {
+/// Hand a closing pane's rows to `to`. With none named they go up: past any
+/// results listing to the nearest pane above that is not one, or to the
+/// pane below when the closing one is first in its column.
+pub fn absorbVWeight(p: *Pardes, id: usize, to: ?usize) void {
const f = findPane(p, id) orelse return;
if (p.col_n[f.col] <= 1) return;
snapColWeights(p, f.col);
- var sib = if (f.idx > 0) p.col_panes[f.col][f.idx - 1] else p.col_panes[f.col][f.idx + 1];
+ var sib = to orelse if (f.idx > 0) p.col_panes[f.col][f.idx - 1] else p.col_panes[f.col][f.idx + 1];
var k = f.idx;
- while (k > 0) : (k -= 1) {
+ while (to == null and k > 0) : (k -= 1) {
sib = p.col_panes[f.col][k - 1];
if (p.panes[sib]) |pp| if (if (pp.file) |ff| panes.Output.fileTraits(ff.output).doc else true) break;
}
@@ -1119,7 +1122,7 @@ pub fn toggleCollapse(p: *Pardes, id: usize) void {
// Convert only visible panes to row weights. The toggle then changes one
// pair, rather than letting the column redistribute the released space.
snapColWeights(p, at.col);
- const neighbor = collapseNeighbor(p, at.col, at.idx);
+ const neighbor = expandedNeighbor(p, at.col, at.idx, .above) orelse expandedNeighbor(p, at.col, at.idx, .below);
if (was_collapsed) {
if (neighbor) |other| {
const wanted: u16 = @intFromFloat(@min(@as(f32, @floatFromInt(std.math.maxInt(u16))), @max(1, @round(remembered_height))));
@@ -1139,15 +1142,17 @@ pub fn toggleCollapse(p: *Pardes, id: usize) void {
compute(p);
}
-fn collapseNeighbor(p: *Pardes, col: usize, index: usize) ?usize {
- var above = index;
- while (above > 0) {
- above -= 1;
- const id = p.col_panes[col][above];
+/// The nearest pane on one side of `index` in its column that is not folded
+/// to its tag: the one Collapse lends rows to and Del k / Del j gives them
+/// to. A folded pane only keeps its weight for later, so rows handed to it
+/// would spread over the whole column instead.
+pub fn expandedNeighbor(p: *const Pardes, col: usize, index: usize, side: enum { above, below }) ?usize {
+ var k = index;
+ while (if (side == .above) k > 0 else k + 1 < p.col_n[col]) {
+ k = if (side == .above) k - 1 else k + 1;
+ const id = p.col_panes[col][k];
if (p.panes[id]) |pane| if (!pane.collapsed) return id;
}
- for (p.col_panes[col][index + 1 .. p.col_n[col]]) |id|
- if (p.panes[id]) |pane| if (!pane.collapsed) return id;
return null;
}