'guicursor': Empty means "block cursor in all modes".

Also: update default 'guicursor' to match the documentation.
This commit is contained in:
Justin M. Keyes 2017-04-01 13:08:42 +02:00
parent 54bab0019b
commit c2826a7830
11 changed files with 214 additions and 61 deletions

View File

@ -371,27 +371,6 @@ See
Used to set the 'shell' option, which determines the shell used by the Used to set the 'shell' option, which determines the shell used by the
.Ic :terminal .Ic :terminal
command. command.
.It Ev NVIM_TUI_ENABLE_CURSOR_SHAPE
Set to 0 to prevent Nvim from changing the cursor shape.
Set to 1 to enable non-blinking mode-sensitive cursor (this is the default).
Set to 2 to enable blinking mode-sensitive cursor.
Host terminal must support the DECSCUSR CSI escape sequence.
.Pp
Depending on the terminal emulator, using this option with
.Nm
under
.Xr tmux 1
might require adding the following to
.Pa ~/.tmux.conf :
.Bd -literal -offset indent
set -ga terminal-overrides ',*:Ss=\eE[%p1%d q:Se=\eE[2 q'
.Ed
.Pp
See
.Ic terminal-overrides
in the
.Xr tmux 1
manual page for more information.
.El .El
.Sh FILES .Sh FILES
.Bl -tag -width "~/.config/nvim/init.vim" .Bl -tag -width "~/.config/nvim/init.vim"

View File

@ -250,23 +250,21 @@ connect to another with different type codes.
============================================================================== ==============================================================================
6. Remote UIs *rpc-remote-ui* 6. Remote UIs *rpc-remote-ui*
Nvim allows Graphical user interfaces to be implemented by separate processes GUIs can be implemented as external processes communicating with Nvim over the
communicating with Nvim over the RPC API. Currently the ui model conists of a RPC API. Currently the UI model consists of a terminal-like grid with one
terminal-like grid with one single, monospace font size, with a few elements single, monospace font size. Some elements (UI "widgets") can be drawn
that could be drawn separately from the grid (for the momemnt only the popup separately from the grid.
menu)
After connecting to a nvim instance (typically a spawned, embedded instance) After connecting to Nvim (usually a spawned, embedded instance) use the
use the |nvim_ui_attach|(width, height, options) API method to tell nvim that your |nvim_ui_attach| API method to tell Nvim that your program wants to draw the
program wants to draw the nvim screen on a grid with "width" times Nvim screen on a grid of width × height cells. `options` must be
"height" cells. "options" should be a dictionary with the following (all a dictionary with these (optional) keys:
optional) keys: `rgb` Controls what color format to use.
`rgb`: Controls what color format to use.
Set to true (default) to use 24-bit rgb Set to true (default) to use 24-bit rgb
colors. colors.
Set to false to use terminal color codes (at Set to false to use terminal color codes (at
most 256 different colors). most 256 different colors).
`popupmenu_external`: Instead of drawing the completion popupmenu on `popupmenu_external` Instead of drawing the completion popupmenu on
the grid, Nvim will send higher-level events to the grid, Nvim will send higher-level events to
the ui and let it draw the popupmenu. the ui and let it draw the popupmenu.
Defaults to false. Defaults to false.

View File

@ -2790,22 +2790,17 @@ A jump table for the options with a short description can be found at |Q_op|.
i-ci:ver25-Cursor/lCursor, i-ci:ver25-Cursor/lCursor,
r-cr:hor20-Cursor/lCursor, r-cr:hor20-Cursor/lCursor,
sm:block-Cursor sm:block-Cursor
-blinkwait175-blinkoff150-blinkon175", -blinkwait175-blinkoff150-blinkon175")
for Windows console:
"n-v-c:block,o:hor50,i-ci:hor15,
r-cr:hor30,sm:block")
global global
{only available when compiled with GUI enabled, and Configures the cursor style for each mode. Works in the GUI and some
for Windows console} terminals. Empty means "non-blinking block cursor in all modes": >
This option tells Vim what the cursor should look like in different :set guicursor=
modes. It fully works in the GUI. In a Windows console, only <
the height of the cursor can be changed. This can be done by With tmux you might need this in ~/.tmux.conf (see terminal-overrides
specifying a block cursor, or a percentage for a vertical or in the tmux(1) manual page): >
horizontal cursor. set -ga terminal-overrides ',*:Ss=\E[%p1%d q:Se=\E[2 q'
For a console, shape is taken into account and color as well if <
'termguicolors' is set. 't_SI' and 't_EI' are deprecated in neovim. The option is a comma separated list of parts. Each part consists of a
The option is a comma separated list of parts. Each part consist of a
mode-list and an argument-list: mode-list and an argument-list:
mode-list:argument-list,mode-list:argument-list,.. mode-list:argument-list,mode-list:argument-list,..
The mode-list is a dash separated list of these modes: The mode-list is a dash separated list of these modes:

View File

@ -113,6 +113,7 @@ Some `CTRL-SHIFT-...` key chords are distinguished from `CTRL-...` variants
Options: Options:
'cpoptions' flags: |cpo-_| 'cpoptions' flags: |cpo-_|
'guicursor' works in the terminal
'inccommand' shows interactive results for |:substitute|-like commands 'inccommand' shows interactive results for |:substitute|-like commands
'statusline' supports unlimited alignment sections 'statusline' supports unlimited alignment sections
'tabline' %@Func@foo%X can call any function on mouse-click 'tabline' %@Func@foo%X can call any function on mouse-click

View File

@ -45,7 +45,7 @@ static cursorentry_T shape_table[SHAPE_IDX_COUNT] =
}; };
/// Converts cursor_shapes into a Dictionary of dictionaries /// Converts cursor_shapes into a Dictionary of dictionaries
/// @return a dictionary of the form {"normal" : { "cursor_shape": ... }, ...} /// @return dictionary of the form {"normal" : { "cursor_shape": ... }, ...}
Dictionary cursor_shape_dict(void) Dictionary cursor_shape_dict(void)
{ {
Dictionary all = ARRAY_DICT_INIT; Dictionary all = ARRAY_DICT_INIT;
@ -82,7 +82,7 @@ Dictionary cursor_shape_dict(void)
/// Parse the 'guicursor' option /// Parse the 'guicursor' option
/// ///
/// @param what either SHAPE_CURSOR or SHAPE_MOUSE ('mouseshape') /// @param what SHAPE_CURSOR or SHAPE_MOUSE ('mouseshape')
/// ///
/// @returns error message for an illegal option, NULL otherwise. /// @returns error message for an illegal option, NULL otherwise.
char_u *parse_shape_opt(int what) char_u *parse_shape_opt(int what)
@ -103,10 +103,11 @@ char_u *parse_shape_opt(int what)
* First round: check for errors; second round: do it for real. * First round: check for errors; second round: do it for real.
*/ */
for (round = 1; round <= 2; ++round) { for (round = 1; round <= 2; ++round) {
/* // Repeat for all comma separated parts.
* Repeat for all comma separated parts.
*/
modep = p_guicursor; modep = p_guicursor;
if (*p_guicursor == NUL) {
modep = (char_u *)"a:block-blinkon0";
}
while (*modep != NUL) { while (*modep != NUL) {
colonp = vim_strchr(modep, ':'); colonp = vim_strchr(modep, ':');
if (colonp == NULL) if (colonp == NULL)
@ -115,7 +116,7 @@ char_u *parse_shape_opt(int what)
return (char_u *)N_("E546: Illegal mode"); return (char_u *)N_("E546: Illegal mode");
commap = vim_strchr(modep, ','); commap = vim_strchr(modep, ',');
// Repeat for all mode's before the colon. // Repeat for all modes before the colon.
// For the 'a' mode, we loop to handle all the modes. // For the 'a' mode, we loop to handle all the modes.
all_idx = -1; all_idx = -1;
assert(modep < colonp); assert(modep < colonp);

View File

@ -37,7 +37,7 @@ SHAPE_VER = 2 ///< vertical bar cursor
#define SHAPE_CURSOR 2 /* used for text cursor shape */ #define SHAPE_CURSOR 2 /* used for text cursor shape */
typedef struct cursor_entry { typedef struct cursor_entry {
char *full_name; ///< mode full name char *full_name; ///< mode description
CursorShape shape; ///< cursor shape: one of the SHAPE_ defines CursorShape shape; ///< cursor shape: one of the SHAPE_ defines
int mshape; ///< mouse shape: one of the MSHAPE defines int mshape; ///< mouse shape: one of the MSHAPE defines
int percentage; ///< percentage of cell for bar int percentage; ///< percentage of cell for bar

View File

@ -1000,7 +1000,7 @@ return {
deny_duplicates=true, deny_duplicates=true,
vi_def=true, vi_def=true,
varname='p_guicursor', varname='p_guicursor',
defaults={if_true={vi="n-v-c:block,o:hor50,i-ci:hor15,r-cr:hor30,sm:block"}} defaults={if_true={vi="n-v-c:block-Cursor/lCursor,ve:ver35-Cursor,o:hor50-Cursor,i-ci:ver25-Cursor/lCursor,r-cr:hor20-Cursor/lCursor,sm:block-Cursor-blinkwait175-blinkoff150-blinkon175"}}
}, },
{ {
full_name='guifont', abbreviation='gfn', full_name='guifont', abbreviation='gfn',

View File

@ -148,7 +148,6 @@ static void terminfo_start(UI *ui)
data->ut = unibi_dummy(); data->ut = unibi_dummy();
} }
fix_terminfo(data); fix_terminfo(data);
// Initialize the cursor shape.
// Set 't_Co' from the result of unibilium & fix_terminfo. // Set 't_Co' from the result of unibilium & fix_terminfo.
t_colors = unibi_get_num(data->ut, unibi_max_colors); t_colors = unibi_get_num(data->ut, unibi_max_colors);
// Enter alternate screen and clear // Enter alternate screen and clear

View File

@ -0,0 +1,180 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
local insert, execute = helpers.insert, helpers.execute
local eq, funcs = helpers.eq, helpers.funcs
local command = helpers.command
if helpers.pending_win32(pending) then return end
describe('ui/cursor', function()
local screen
before_each(function()
clear()
screen = Screen.new(25, 5)
screen:attach()
end)
after_each(function()
screen:detach()
end)
it("'guicursor' is published as a UI event", function()
command('redraw')
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
local expected_cursor_style = {
cmd_insert = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 25,
cursor_shape = 'vertical',
hl_id = 45,
id_lm = 46,
mouse_shape = 0,
short_name = 'ci' },
cmd_line = {
mouse_shape = 0,
short_name = 'e' },
cmd_normal = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 0,
cursor_shape = 'block',
hl_id = 45,
id_lm = 46,
mouse_shape = 0,
short_name = 'c' },
cmd_replace = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 20,
cursor_shape = 'horizontal',
hl_id = 45,
id_lm = 46,
mouse_shape = 0,
short_name = 'cr' },
drag_statusline = {
mouse_shape = 0,
short_name = 'sd' },
insert = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 25,
cursor_shape = 'vertical',
hl_id = 45,
id_lm = 46,
mouse_shape = 0,
short_name = 'i' },
match_paren = {
blinkoff = 150,
blinkon = 175,
blinkwait = 175,
cell_percentage = 0,
cursor_shape = 'block',
hl_id = 45,
id_lm = 45,
short_name = 'sm' },
more = {
mouse_shape = 0,
short_name = 'm' },
more_lastline = {
mouse_shape = 0,
short_name = 'ml' },
normal = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 0,
cursor_shape = 'block',
hl_id = 45,
id_lm = 46,
mouse_shape = 0,
short_name = 'n' },
pending = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 50,
cursor_shape = 'horizontal',
hl_id = 45,
id_lm = 45,
mouse_shape = 0,
short_name = 'o' },
replace = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 20,
cursor_shape = 'horizontal',
hl_id = 45,
id_lm = 46,
mouse_shape = 0,
short_name = 'r' },
statusline = {
mouse_shape = 0,
short_name = 's' },
vdrag = {
mouse_shape = 0,
short_name = 'vd' },
visual = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 0,
cursor_shape = 'block',
hl_id = 45,
id_lm = 46,
mouse_shape = 0,
short_name = 'v' },
visual_select = {
blinkoff = 250,
blinkon = 400,
blinkwait = 700,
cell_percentage = 35,
cursor_shape = 'vertical',
hl_id = 45,
id_lm = 45,
mouse_shape = 0,
short_name = 've' },
vsep = {
mouse_shape = 0,
short_name = 'vs' }
}
-- Default 'guicursor' published on startup.
eq(expected_cursor_style, screen._cursor_style)
eq('normal', screen.mode)
-- Event is published ONLY if the cursor style changed.
screen._cursor_style = nil
command('redraw')
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
eq(nil, screen._cursor_style)
-- Change the cursor style.
meths.set_option('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173,ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42')
command('redraw')
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
eq('vertical', screen._cursor_style.normal.cursor_shape)
eq('horizontal', screen._cursor_style.visual_select.cursor_shape)
eq('vertical', screen._cursor_style.pending.cursor_shape)
eq('block', screen._cursor_style.insert.cursor_shape)
eq('vertical', screen._cursor_style.match_paren.cursor_shape)
end)
it("empty 'guicursor' sets cursor_shape=block in all modes", function()
meths.set_option('guicursor', '')
command('redraw')
screen:expect('', nil, nil, nil, true) -- Tickle the event-loop.
for _, m in ipairs({ 'cmd_insert', 'cmd_normal', 'cmd_replace', 'insert',
'match_paren', 'normal', 'replace', 'visual',
'visual_select', }) do
eq('block', screen._cursor_style[m].cursor_shape)
end
end)
end)

View File

@ -6,7 +6,7 @@ local eq, funcs = helpers.eq, helpers.funcs
if helpers.pending_win32(pending) then return end if helpers.pending_win32(pending) then return end
describe('Mouse input', function() describe('ui/mouse/input', function()
local screen local screen
before_each(function() before_each(function()

View File

@ -345,8 +345,8 @@ function Screen:_handle_resize(width, height)
} }
end end
function Screen:_handle_cursor_style_set(styles) function Screen:_handle_cursor_style_set(style)
self._cursor_styles = styles self._cursor_style = style
end end
function Screen:_handle_clear() function Screen:_handle_clear()