diff --git a/src/nvim/move.c b/src/nvim/move.c index ea35813d21..1402b03f6d 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -135,32 +135,43 @@ static void comp_botline(win_T *wp) win_check_anchored_floats(wp); } -/// Redraw when w_virtcol changes and 'cursorcolumn' is set or 'cursorlineopt' -/// contains "screenline" or when the "CurSearch" highlight is in use. -/// Also when concealing is on and 'concealcursor' is active. +/// Redraw when w_virtcol changes and +/// - 'cursorcolumn' is set, or +/// - 'cursorlineopt' contains "screenline", or +/// - "CurSearch" highlight is in use, or +/// - 'concealcursor' is active, or +/// - Visual mode is active. static void redraw_for_cursorcolumn(win_T *wp) FUNC_ATTR_NONNULL_ALL { - if ((wp->w_valid & VALID_VIRTCOL) == 0 && !pum_visible()) { - if (wp->w_p_cuc - || (win_hl_attr(wp, HLF_LC) != win_hl_attr(wp, HLF_L) && using_hlsearch())) { - // When 'cursorcolumn' is set or "CurSearch" is in use - // need to redraw with UPD_SOME_VALID. - redraw_later(wp, UPD_SOME_VALID); - } else if (VIsual_active) { - // In Visual mode need to redraw with UPD_INVERTED. - redraw_later(wp, UPD_INVERTED); - } else if (wp->w_p_cul && (wp->w_p_culopt_flags & CULOPT_SCRLINE)) { - // When 'cursorlineopt' contains "screenline" need to redraw with UPD_VALID. - redraw_later(wp, UPD_VALID); - } + if (wp->w_valid & VALID_VIRTCOL) { + return; } + // If the cursor moves horizontally when 'concealcursor' is active, then the - // current line needs to be redrawn in order to calculate the correct - // cursor position. - if ((wp->w_valid & VALID_VIRTCOL) == 0 && wp->w_p_cole > 0 && conceal_cursor_line(wp)) { + // current line needs to be redrawn to calculate the correct cursor position. + if (wp->w_p_cole > 0 && conceal_cursor_line(wp)) { redrawWinline(wp, wp->w_cursor.lnum); } + + if (pum_visible()) { + return; + } + + if (wp->w_p_cuc + || (win_hl_attr(wp, HLF_LC) != win_hl_attr(wp, HLF_L) && using_hlsearch())) { + // When 'cursorcolumn' is set or "CurSearch" is in use + // need to redraw with UPD_SOME_VALID. + redraw_later(wp, UPD_SOME_VALID); + } else if (wp->w_p_cul && (wp->w_p_culopt_flags & CULOPT_SCRLINE)) { + // When 'cursorlineopt' contains "screenline" need to redraw with UPD_VALID. + redraw_later(wp, UPD_VALID); + } + + // When current buffer's cursor moves in Visual mode, redraw it with UPD_INVERTED. + if (VIsual_active && wp->w_buffer == curbuf) { + redraw_curbuf_later(UPD_INVERTED); + } } /// Calculates how much the 'listchars' "precedes" or 'smoothscroll' "<<<" diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 00e024e735..518208a037 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1967,8 +1967,8 @@ const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) return e_invarg; } if (VIsual_active) { - // In Visual mode cursor may be drawn differently. - redrawWinline(curwin, curwin->w_cursor.lnum); + // Visual selection may be drawn differently. + redraw_curbuf_later(UPD_INVERTED); } return NULL; } diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index fc692f47bb..af6ae5bf46 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -313,35 +313,136 @@ end) describe('highlight', function() before_each(clear) - it('visual', function() - local screen = Screen.new(20, 4) + it('Visual', function() + local screen = Screen.new(45, 5) screen:attach() screen:set_default_attr_ids({ [1] = { background = Screen.colors.LightGrey }, [2] = { bold = true, foreground = Screen.colors.Blue1 }, [3] = { bold = true }, + [4] = { reverse = true, bold = true }, + [5] = { reverse = true }, + [6] = { background = Screen.colors.Grey90 }, }) insert([[ line1 foo bar + abcdefghijklmnopqrs + ABCDEFGHIJKLMNOPQRS ]]) + feed('gg') + command('vsplit') -- Non-blinking block cursor: does NOT highlight char-at-cursor. command('set guicursor=a:block-blinkon0') - feed('gg$vhhh') + feed('V') screen:expect([[ - line1 foo^ {1:bar} | - | - {2:~ }| - {3:-- VISUAL --} | + {1: }^l{1:ine1 foo bar} │{1: line1 foo bar} | + abcdefghijklmnopqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL LINE --} | + ]]) + + feed('$vhhh') + screen:expect([[ + line1 foo^ {1:bar} │ line1 foo{1: bar} | + abcdefghijklmnopqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL --} | ]]) -- Vertical cursor: highlights char-at-cursor. #8983 command('set guicursor=a:block-blinkon175') screen:expect([[ - line1 foo{1:^ bar} | - | - {2:~ }| - {3:-- VISUAL --} | + line1 foo{1:^ bar} │ line1 foo{1: bar} | + abcdefghijklmnopqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL --} | + ]]) + + command('set selection=exclusive') + screen:expect([[ + line1 foo{1:^ ba}r │ line1 foo{1: ba}r | + abcdefghijklmnopqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL --} | + ]]) + + feed('o') + screen:expect([[ + line1 foo{1: ba}^r │ line1 foo{1: ba}r | + abcdefghijklmnopqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL --} | + ]]) + + feed('V') + screen:expect([[ + {1: line1 foo ba^r} │{1: line1 foo bar} | + abcdefghijklmnopqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL LINE --} | + ]]) + + command('set cursorcolumn') + feed('') + screen:expect([[ + line1 foo{1: ba}^r │ line1 foo{1: ba}r | + abcdefghijklmn{6:o}pqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMN{6:O}PQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL BLOCK --} | + ]]) + + command('set selection&') + screen:expect([[ + line1 foo{1: ba^r} │ line1 foo{1: bar} | + abcdefghijklmn{6:o}pqrs │abcdefghijklmnopqrs | + ABCDEFGHIJKLMN{6:O}PQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL BLOCK --} | + ]]) + + feed('^') + screen:expect([[ + {1:^line1 foo }bar │ {1:line1 foo }bar | + ab{6:c}defghijklmnopqrs │abcdefghijklmnopqrs | + AB{6:C}DEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL BLOCK --} | + ]]) + + feed('2j') + screen:expect([[ + {1:line1 foo }bar │ {1:line1 foo }bar | + ab{1:cdefghijkl}mnopqrs │ab{1:cdefghijkl}mnopqrs | + AB{1:^CDEFGHIJKL}MNOPQRS │AB{1:CDEFGHIJKL}MNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL BLOCK --} | + ]]) + + command('set nocursorcolumn') + feed('O') + screen:expect([[ + {1:line1 foo }bar │ {1:line1 foo }bar | + ab{1:cdefghijkl}mnopqrs │ab{1:cdefghijkl}mnopqrs | + AB{1:CDEFGHIJK^L}MNOPQRS │AB{1:CDEFGHIJKL}MNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL BLOCK --} | + ]]) + + command('set selection=exclusive') + screen:expect([[ + {1:line1 foo} bar │ {1:line1 foo} bar | + ab{1:cdefghijk}lmnopqrs │ab{1:cdefghijk}lmnopqrs | + AB{1:CDEFGHIJK}^LMNOPQRS │AB{1:CDEFGHIJK}LMNOPQRS | + {4:[No Name] [+] }{5:[No Name] [+] }| + {3:-- VISUAL BLOCK --} | ]]) end)