From b660adabce36e90cbfbb52d95715528983376ab5 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 22:02:04 -0300 Subject: A pane whose whole text fits in its rows never scrolls to keep a margin The scroll margin reveals text; with none off screen there is nothing to reveal. ensureCursorVisible and a centred look both leave such a pane at its top. A longer file keeps helix's clamp (hxdiff and hxparity unchanged). Co-Authored-By: Claude Opus 5.5 --- src/panes.zig | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/panes.zig') diff --git a/src/panes.zig b/src/panes.zig index a7e5c668..47582692 100644 --- a/src/panes.zig +++ b/src/panes.zig @@ -512,6 +512,16 @@ pub const Pane = struct { } } + /// Every line of the file's text fits in the body's rows; the empty + /// line after a final newline is no text. + pub fn textFits(pane: *Pane) bool { + if (pane.file) |*f| { + const lines = File.nlines(pane.gpa, f) - @intFromBool(std.mem.endsWith(u8, f.content, "\n")); + return lines <= pane.rows; + } + return false; + } + pub fn ensureCursorVisible(pane: *Pane) void { const off = pane.scroll(); var in_context = false; @@ -539,7 +549,13 @@ pub const Pane = struct { pane.scrollBy(pane.body.cur_row - margin - off); } else if (pane.body.cur_row > last - margin) { var to = pane.body.cur_row + margin; - if (pane.file) |*f| to = @min(to, @as(i32, @intCast(File.nlines(pane.gpa, f) -| 1))); + if (pane.file) |*f| { + // The margin only reveals text: a pane its whole text + // fits in never scrolls for it. A longer one keeps + // helix's clamp at the buffer's last line. + const lines: i32 = @intCast(File.nlines(pane.gpa, f)); + to = @min(to, if (off == 0 and pane.textFits()) @max(pane.body.cur_row, lines - 1 - @intFromBool(std.mem.endsWith(u8, f.content, "\n"))) else lines - 1); + } if (comptime Pdf.enabled) { if (pane.pdf) |pv| to = @min(to, @as(i32, @intCast(modal.lineCount(pv.text) -| 1))); -- cgit v1.3