commit cc7022c5444cc718dd7a0c5a3297664c37406889
parent 39d8a9c353d61fa68da5370afec1f32b6387607a
Author: zeertzjq <zeertzjq@outlook.com>
Date: Fri, 13 Feb 2026 09:06:23 +0800
fix(terminal): scrollback may still be wrong on height increase (#37835)
Problem: Terminal scrollback may be wrong when increasing height after
outputting lines with full scrollback.
Solution: Ensure enough number of scrollback lines have been deleted.
Diffstat:
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
@@ -2397,19 +2397,18 @@ static void refresh_scrollback(Terminal *term, buf_T *buf)
mark_adjust_buf(buf, 1, deleted, MAXLNUM, -deleted, true, kMarkAdjustTerm, kExtmarkUndo);
term->old_sb_deleted = term->sb_deleted;
+ int old_height = term->old_height;
int width, height;
vterm_get_size(term->vt, &height, &width);
- int max_line_count = (int)term->sb_current - term->sb_pending + height;
- // Remove extra lines at the top if scrollback lines have been deleted.
- while (deleted > 0 && buf->b_ml.ml_line_count > max_line_count) {
+ // Remove deleted scrollback lines at the top, but don't unnecessarily remove
+ // lines that will be overwritten by refresh_screen().
+ while (deleted > 0 && buf->b_ml.ml_line_count > old_height) {
ml_delete_buf(buf, 1, false);
deleted_lines_buf(buf, 1, 1);
deleted--;
}
- max_line_count += term->sb_pending;
- int old_height = MIN(term->old_height, buf->b_ml.ml_line_count);
while (term->sb_pending > 0) {
// This means that either the window height has decreased or the screen
// became full and libvterm had to push all rows up. Convert the first
@@ -2422,6 +2421,7 @@ static void refresh_scrollback(Terminal *term, buf_T *buf)
term->sb_pending--;
}
+ int max_line_count = (int)term->sb_current + height;
// Remove extra lines at the bottom.
while (buf->b_ml.ml_line_count > max_line_count) {
ml_delete_buf(buf, buf->b_ml.ml_line_count, false);
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
@@ -1263,6 +1263,25 @@ describe('scrollback is correct', function()
check_buffer_lines(0, 99)
end)
end
+
+ describe('with full scrollback,', function()
+ before_each(function()
+ api.nvim_set_option_value('scrollback', 6, { buf = buf })
+ check_buffer_lines(82, 94)
+ end)
+
+ it('output first', function()
+ command(send_cmd .. ' | resize +2')
+ screen:expect(screen_final)
+ check_buffer_lines(87, 99)
+ end)
+
+ it('resize first', function()
+ command('resize +2 | ' .. send_cmd)
+ screen:expect(screen_final)
+ check_buffer_lines(85, 99)
+ end)
+ end)
end)
describe('decreases in the same refresh cycle as outputting lines', function()