From 7f5427b857273e0eef8df2102d67a4bc46e3f18c Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Thu, 27 Feb 2025 12:46:56 +0000 Subject: [PATCH] fix(terminal): add various missing redraws Problem: missing redraws when restoring saved cursorline/column, plus missing statusline and mode redraws when not updating the screen in terminal mode. Solution: schedule the redraws in a similar manner to other modes and remove some now unnecessary redrawing logic. Redraw if cursorline-related options change from entering terminal mode. This fixes test failures in later commits. WTF: TextChangedT triggers based on must_redraw, which is... fun...? Try to preserve its behaviour as much as we can for now. --- src/nvim/terminal.c | 31 +++-- test/functional/terminal/window_spec.lua | 143 +++++++++++++++++++++++ test/functional/ui/title_spec.lua | 17 ++- 3 files changed, 177 insertions(+), 14 deletions(-) diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index ac903f9adb..6e5f48aded 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -710,18 +710,19 @@ bool terminal_enter(void) } else { curwin->w_p_cul = false; } - if (curwin->w_p_cuc) { - redraw_later(curwin, UPD_SOME_VALID); - } curwin->w_p_cuc = false; curwin->w_p_so = 0; curwin->w_p_siso = 0; + if (curwin->w_p_cuc != save_w_p_cuc) { + redraw_later(curwin, UPD_SOME_VALID); + } else if (curwin->w_p_cul != save_w_p_cul + || (curwin->w_p_cul && curwin->w_p_culopt_flags != save_w_p_culopt_flags)) { + redraw_later(curwin, UPD_VALID); + } s->term->pending.cursor = true; // Update the cursor shape table adjust_topline(s->term, buf, 0); // scroll to end showmode(); - curwin->w_redr_status = true; // For mode() in statusline. #8323 - redraw_custom_title_later(); ui_cursor_shape(); apply_autocmds(EVENT_TERMENTER, NULL, NULL, false, curbuf); may_trigger_modechanged(); @@ -749,6 +750,12 @@ bool terminal_enter(void) (void)parse_shape_opt(SHAPE_CURSOR); if (save_curwin == curwin->handle) { // Else: window was closed. + if (save_w_p_cuc != curwin->w_p_cuc) { + redraw_later(curwin, UPD_SOME_VALID); + } else if (save_w_p_cul != curwin->w_p_cul + || (save_w_p_cul && save_w_p_culopt_flags != curwin->w_p_culopt_flags)) { + redraw_later(curwin, UPD_VALID); + } curwin->w_p_cul = save_w_p_cul; if (save_w_p_culopt) { free_string_option(curwin->w_p_culopt); @@ -813,10 +820,18 @@ static int terminal_check(VimState *state) assert(s->term == curbuf->terminal); terminal_check_cursor(); validate_cursor(curwin); + const bool text_changed = must_redraw != 0; + show_cursor_info_later(false); if (must_redraw) { update_screen(); - + } else { + redraw_statuslines(); + if (clear_cmdline || redraw_cmdline || redraw_mode) { + showmode(); // clear cmdline and show mode + } + } + if (text_changed) { // Make sure an invoked autocmd doesn't delete the buffer (and the // terminal) under our fingers. curbuf->b_locked++; @@ -832,10 +847,6 @@ static int terminal_check(VimState *state) may_trigger_win_scrolled_resized(); - if (need_maketitle) { // Update title in terminal-mode. #7248 - maketitle(); - } - setcursor(); refresh_cursor(s->term, &s->cursor_visible); ui_flush(); diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua index a65d18de70..0fc5e9e7f1 100644 --- a/test/functional/terminal/window_spec.lua +++ b/test/functional/terminal/window_spec.lua @@ -189,6 +189,149 @@ describe(':terminal window', function() ]]) end) end) + + it('redrawn when restoring cursorline/column', function() + screen:set_default_attr_ids({ + [1] = { bold = true }, + [2] = { foreground = 130 }, + [3] = { foreground = 130, underline = true }, + [12] = { underline = true }, + [19] = { background = 7 }, + }) + + feed([[]]) + command('setlocal cursorline') + screen:expect([[ + tty ready | + {12:^ }| + |*5 + ]]) + feed('i') + screen:expect([[ + tty ready | + ^ | + |*4 + {1:-- TERMINAL --} | + ]]) + feed([[]]) + screen:expect([[ + tty ready | + {12:^ }| + |*5 + ]]) + + command('setlocal number') + screen:expect([[ + {2: 1 }tty ready | + {3: 2 }{12:^rows: 6, cols: 46 }| + {2: 3 } | + {2: 4 } | + {2: 5 } | + {2: 6 } | + | + ]]) + feed('i') + screen:expect([[ + {2: 1 }tty ready | + {2: 2 }rows: 6, cols: 46 | + {3: 3 }^ | + {2: 4 } | + {2: 5 } | + {2: 6 } | + {1:-- TERMINAL --} | + ]]) + feed([[]]) + screen:expect([[ + {2: 1 }tty ready | + {2: 2 }rows: 6, cols: 46 | + {3: 3 }{12:^ }| + {2: 4 } | + {2: 5 } | + {2: 6 } | + | + ]]) + + command('setlocal nonumber nocursorline cursorcolumn') + screen:expect([[ + {19:t}ty ready | + {19:r}ows: 6, cols: 46 | + ^rows: 6, cols: 50 | + {19: } |*3 + | + ]]) + feed('i') + screen:expect([[ + tty ready | + rows: 6, cols: 46 | + rows: 6, cols: 50 | + ^ | + |*2 + {1:-- TERMINAL --} | + ]]) + feed([[]]) + screen:expect([[ + {19:t}ty ready | + {19:r}ows: 6, cols: 46 | + {19:r}ows: 6, cols: 50 | + ^ | + {19: } |*2 + | + ]]) + end) + + it('redraws cursor info in terminal mode', function() + skip(is_os('win'), '#31587') + command('file AMOGUS | set laststatus=2 ruler') + screen:expect([[ + tty ready | + rows: 5, cols: 50 | + ^ | + |*2 + {17:AMOGUS 3,0-1 All}| + {3:-- TERMINAL --} | + ]]) + feed_data('you are the imposter') + screen:expect([[ + tty ready | + rows: 5, cols: 50 | + you are the imposter^ | + |*2 + {17:AMOGUS 3,21 All}| + {3:-- TERMINAL --} | + ]]) + feed([[]]) + screen:expect([[ + tty ready | + rows: 5, cols: 50 | + you are the imposte^r | + |*2 + {17:AMOGUS 3,20 All}| + | + ]]) + end) + + it('redraws stale statuslines and mode when not updating screen', function() + command('file foo | set ruler | vsplit') + screen:expect([[ + tty ready │tty ready | + rows: 5, cols: 25 │rows: 5, cols: 25 | + ^ │ | + │ |*2 + {17:foo 3,0-1 All }{18:foo 2,0-1 Top}| + {3:-- TERMINAL --} | + ]]) + command("call win_execute(win_getid(winnr('#')), 'call cursor(1, 1)')") + screen:expect([[ + tty ready │tty ready | + rows: 5, cols: 25 │rows: 5, cols: 25 | + ^ │ | + │ |*2 + {17:foo 3,0-1 All }{18:foo 1,1 All}| + {3:-- TERMINAL --} | + ]]) + command('echo ""') + screen:expect_unchanged() + end) end) describe(':terminal with multigrid', function() diff --git a/test/functional/ui/title_spec.lua b/test/functional/ui/title_spec.lua index 2de1e71457..5e7c9c74b9 100644 --- a/test/functional/ui/title_spec.lua +++ b/test/functional/ui/title_spec.lua @@ -79,18 +79,27 @@ describe('title', function() it('is updated in Terminal mode', function() api.nvim_set_option_value('title', true, {}) - api.nvim_set_option_value('titlestring', '(%{mode(1)}) | nvim', {}) + api.nvim_set_option_value('titlestring', '%t (%{mode(1)}) | nvim', {}) fn.jobstart({ n.testprg('shell-test'), 'INTERACT' }, { term = true }) + api.nvim_buf_set_name(0, 'shell-test') screen:expect(function() - eq('(nt) | nvim', screen.title) + eq('shell-test (nt) | nvim', screen.title) end) feed('i') screen:expect(function() - eq('(t) | nvim', screen.title) + eq('shell-test (t) | nvim', screen.title) + end) + api.nvim_set_option_value('titlelen', 1, {}) + screen:expect(function() + eq(']]) screen:expect(function() - eq('(nt) | nvim', screen.title) + eq('shell-test (nt) | nvim', screen.title) end) end)