neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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:
Msrc/nvim/terminal.c | 10+++++-----
Mtest/functional/terminal/scrollback_spec.lua | 19+++++++++++++++++++
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()