Visual: highlight char-at-cursor

Decide whether to highlight the visual-selected character under the
cursor, depending on 'guicursor' style:

- Highlight if cursor is blinking or non-block (vertical, horiz).
- Do NOT highlight if cursor is non-blinking block.

Traditionally Vim's visual selection does "reverse mode", which perhaps
conflicts with the non-blinking block cursor. But 'guicursor' defaults
to a vertical bar for selection=exclusive, and this confuses users who
expect to see the text highlighted.

closes #8983
This commit is contained in:
Justin M. Keyes
2019-01-03 00:09:35 +01:00
parent e2d71d11de
commit 37a499148f
5 changed files with 62 additions and 13 deletions

View File

@@ -357,6 +357,9 @@ TUI:
and has a 'ttybuiltin' setting to control how that combination works. Nvim and has a 'ttybuiltin' setting to control how that combination works. Nvim
uses one or the other, it does not attempt to merge the two. uses one or the other, it does not attempt to merge the two.
UI/Display:
|Visual| selection highlights the character at cursor. |visual-use|
VimL (Vim script) compatibility: VimL (Vim script) compatibility:
`count` does not alias to |v:count| `count` does not alias to |v:count|
`errmsg` does not alias to |v:errmsg| `errmsg` does not alias to |v:errmsg|

View File

@@ -254,6 +254,16 @@ char_u *parse_shape_opt(int what)
return NULL; return NULL;
} }
/// Returns true if the cursor is non-blinking "block" shape during
/// visual selection.
///
/// @param exclusive If 'selection' option is "exclusive".
bool cursor_is_block_during_visual(bool exclusive)
{
int mode_idx = exclusive ? SHAPE_IDX_VE : SHAPE_IDX_V;
return (SHAPE_BLOCK == shape_table[mode_idx].shape
&& 0 == shape_table[mode_idx].blinkon);
}
/// Map cursor mode from string to integer /// Map cursor mode from string to integer
/// ///

View File

@@ -2761,9 +2761,9 @@ do_mouse (
} else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT)) } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))
&& mouse_has(MOUSE_VISUAL)) { && mouse_has(MOUSE_VISUAL)) {
if (is_click || !VIsual_active) { if (is_click || !VIsual_active) {
if (VIsual_active) if (VIsual_active) {
orig_cursor = VIsual; orig_cursor = VIsual;
else { } else {
VIsual = curwin->w_cursor; VIsual = curwin->w_cursor;
orig_cursor = VIsual; orig_cursor = VIsual;
VIsual_active = true; VIsual_active = true;
@@ -6401,8 +6401,8 @@ static void nv_visual(cmdarg_T *cap)
VIsual_mode = cap->cmdchar; VIsual_mode = cap->cmdchar;
showmode(); showmode();
} }
redraw_curbuf_later(INVERTED); /* update the inversion */ redraw_curbuf_later(INVERTED); // update the inversion
} else { /* start Visual mode */ } else { // start Visual mode
if (cap->count0 > 0 && resel_VIsual_mode != NUL) { if (cap->count0 > 0 && resel_VIsual_mode != NUL) {
/* use previously selected part */ /* use previously selected part */
VIsual = curwin->w_cursor; VIsual = curwin->w_cursor;

View File

@@ -73,6 +73,7 @@
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/charset.h" #include "nvim/charset.h"
#include "nvim/cursor.h" #include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
#include "nvim/diff.h" #include "nvim/diff.h"
#include "nvim/eval.h" #include "nvim/eval.h"
#include "nvim/ex_cmds.h" #include "nvim/ex_cmds.h"
@@ -679,9 +680,9 @@ static void win_update(win_T *wp)
int old_botline = wp->w_botline; int old_botline = wp->w_botline;
long fold_count; long fold_count;
// Remember what happened to the previous line. // Remember what happened to the previous line.
#define DID_NONE 1 /* didn't update a line */ #define DID_NONE 1 // didn't update a line
#define DID_LINE 2 /* updated a normal line */ #define DID_LINE 2 // updated a normal line
#define DID_FOLD 3 /* updated a folded line */ #define DID_FOLD 3 // updated a folded line
int did_update = DID_NONE; int did_update = DID_NONE;
linenr_T syntax_last_parsed = 0; /* last parsed text line */ linenr_T syntax_last_parsed = 0; /* last parsed text line */
linenr_T mod_top = 0; linenr_T mod_top = 0;
@@ -2180,10 +2181,10 @@ win_line (
int syntax_attr = 0; /* attributes desired by syntax */ int syntax_attr = 0; /* attributes desired by syntax */
int has_syntax = FALSE; /* this buffer has syntax highl. */ int has_syntax = FALSE; /* this buffer has syntax highl. */
int save_did_emsg; int save_did_emsg;
int eol_hl_off = 0; /* 1 if highlighted char after EOL */ int eol_hl_off = 0; // 1 if highlighted char after EOL
int draw_color_col = FALSE; /* highlight colorcolumn */ int draw_color_col = false; // highlight colorcolumn
int *color_cols = NULL; /* pointer to according columns array */ int *color_cols = NULL; // pointer to according columns array
bool has_spell = false; /* this buffer has spell checking */ bool has_spell = false; // this buffer has spell checking
# define SPWORDLEN 150 # define SPWORDLEN 150
char_u nextline[SPWORDLEN * 2]; /* text with start of the next line */ char_u nextline[SPWORDLEN * 2]; /* text with start of the next line */
int nextlinecol = 0; /* column where nextline[] starts */ int nextlinecol = 0; /* column where nextline[] starts */
@@ -2389,8 +2390,9 @@ win_line (
} }
} }
// Check if the character under the cursor should not be inverted // Check if the char under the cursor should be inverted (highlighted).
if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin) { if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin
&& cursor_is_block_during_visual(*p_sel == 'e')) {
noinvcur = true; noinvcur = true;
} }

View File

@@ -322,6 +322,40 @@ describe('highlight', function()
screen:attach() screen:attach()
end) end)
it('visual', function()
screen:detach()
screen = Screen.new(20,4)
screen:attach()
screen:set_default_attr_ids({
[1] = {background = Screen.colors.LightGrey},
[2] = {bold = true, foreground = Screen.colors.Blue1},
[3] = {bold = true},
})
insert([[
line1 foo bar
]])
-- Non-blinking block cursor: does NOT highlight char-at-cursor.
command('set guicursor=a:block-blinkon0')
feed('gg$vhhh')
screen:expect([[
line1 foo^ {1:bar} |
|
{2:~ }|
{3:-- VISUAL --} |
]])
-- Vertical cursor: highlights char-at-cursor. #8983
command('set guicursor=a:block-blinkon175')
feed('<esc>gg$vhhh')
screen:expect([[
line1 foo{1:^ bar} |
|
{2:~ }|
{3:-- VISUAL --} |
]])
end)
it('cterm=standout gui=standout', function() it('cterm=standout gui=standout', function()
screen:detach() screen:detach()
screen = Screen.new(20,5) screen = Screen.new(20,5)