From 8305af9bd2eb645d4a0be39d32bea5dc81fe69a1 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Sat, 3 May 2025 23:24:11 +0200 Subject: [PATCH] fix(statusline): clear ruler when it is no longer drawn #33765 Problem: Ruler is not cleared from the screen/ext_messages state when it is no longer drawn after e.g. `set noruler` or when moving from a floating to a regular window. Solution: Remember if ruler was drawn and clear it. --- src/nvim/drawscreen.c | 15 +---------- src/nvim/statusline.c | 40 +++++++++++++++++----------- test/functional/ui/messages_spec.lua | 26 +++++++++--------- 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 7f9785e075..8afae3f938 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1118,20 +1118,7 @@ int showmode(void) clear_showcmd(); } - // If the current or last window has no status line and global statusline is disabled, - // the ruler is after the mode message and must be redrawn - win_T *ruler_win = curwin->w_status_height == 0 ? curwin : lastwin_nofloating(); - if (redrawing() && ruler_win->w_status_height == 0 && global_stl_height() == 0 - && !(p_ch == 0 && !ui_has(kUIMessages))) { - if (!ui_has(kUIMessages)) { - grid_line_start(&msg_grid_adj, Rows - 1); - } - win_redr_ruler(ruler_win); - if (!ui_has(kUIMessages)) { - grid_line_flush(); - } - } - + redraw_ruler(); // check if ruler should be redrawn redraw_cmdline = false; redraw_mode = false; clear_cmdline = false; diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 849f083e46..29ca338afa 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -333,9 +333,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) int start_col = col; // Draw each snippet with the specified highlighting. - if (!draw_ruler) { - screengrid_line_start(grid, row, 0); - } + screengrid_line_start(grid, row, 0); int curattr = attr; char *p = buf; @@ -363,10 +361,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) // fill up with "fillchar" grid_line_fill(col, maxcol, fillchar, curattr); - - if (!draw_ruler) { - grid_line_flush(); - } + grid_line_flush(); // Fill the tab_page_click_defs, w_status_click_defs or w_winbar_click_defs array for clicking // in the tab page line, status line or window bar @@ -399,14 +394,24 @@ void win_redr_winbar(win_T *wp) entered = false; } -/// must be called after a grid_line_start() at the intended row -void win_redr_ruler(win_T *wp) +void redraw_ruler(void) { - bool is_stl_global = global_stl_height() > 0; + static int did_ruler_col = -1; static bool did_show_ext_ruler = false; + win_T *wp = curwin->w_status_height == 0 ? curwin : lastwin_nofloating(); + bool is_stl_global = global_stl_height() > 0; - // If 'ruler' off, don't do anything - if (!p_ru) { + // Check if ruler should be drawn, clear if it was drawn before. + if (!p_ru || wp->w_status_height > 0 || is_stl_global || (p_ch == 0 && !ui_has(kUIMessages))) { + if (did_ruler_col > 0 && ui_has(kUIMessages)) { + ui_call_msg_ruler((Array)ARRAY_DICT_INIT); + did_show_ext_ruler = false; + } else if (did_ruler_col > 0) { + msg_col = did_ruler_col; + msg_row = Rows - 1; + msg_clr_eos(); + } + did_ruler_col = -1; return; } @@ -418,8 +423,7 @@ void win_redr_ruler(win_T *wp) // Don't draw the ruler while doing insert-completion, it might overwrite // the (long) mode message. - win_T *ruler_win = curwin->w_status_height == 0 ? curwin : lastwin_nofloating(); - if (wp == ruler_win && ruler_win->w_status_height == 0 && !is_stl_global) { + if (wp->w_status_height == 0 && !is_stl_global) { if (edit_submode != NULL) { return; } @@ -513,6 +517,7 @@ void win_redr_ruler(win_T *wp) ADD_C(content, ARRAY_OBJ(chunk)); ui_call_msg_ruler(content); did_show_ext_ruler = true; + did_ruler_col = 1; } else { if (did_show_ext_ruler) { ui_call_msg_ruler((Array)ARRAY_DICT_INIT); @@ -528,8 +533,11 @@ void win_redr_ruler(win_T *wp) } } - int w = grid_line_puts(off + this_ru_col, buffer, -1, attr); - grid_line_fill(off + this_ru_col + w, off + width, fillchar, attr); + grid_line_start(&msg_grid_adj, Rows - 1); + did_ruler_col = off + this_ru_col; + int w = grid_line_puts(did_ruler_col, buffer, -1, attr); + grid_line_fill(did_ruler_col + w, off + width, fillchar, attr); + grid_line_flush(); } } diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 6725d17068..4e1aca2b7c 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -1834,31 +1834,33 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim it('supports ruler with laststatus=0', function() command('set ruler laststatus=0') - screen:expect { - grid = [[ + screen:expect([[ ^ | {1:~ }|*5 0,0-1 All | - ]], - } + ]]) command('hi MsgArea guibg=#333333') - screen:expect { - grid = [[ + screen:expect([[ ^ | {1:~ }|*5 {101: 0,0-1 All }| - ]], - } + ]]) command('set rulerformat=%15(%c%V\\ %p%%%)') - screen:expect { - grid = [[ + screen:expect([[ ^ | {1:~ }|*5 {101: 0,0-1 100% }| - ]], - } + ]]) + + -- Ruler is cleared when it is no longer drawn. + command('set noruler') + screen:expect([[ + ^ | + {1:~ }|*5 + {101: }| + ]]) end) it('supports echo with CRLF line separators', function()