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.
This commit is contained in:
zeertzjq
2026-02-13 09:06:23 +08:00
committed by GitHub
parent 39d8a9c353
commit cc7022c544
2 changed files with 24 additions and 5 deletions

View File

@@ -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);

View File

@@ -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()