tui: 'guicursor' shape #6044

Closes #2583
This commit is contained in:
Matthieu Coudron
2017-03-20 22:56:58 +01:00
committed by Justin M. Keyes
parent 16babc6687
commit dd4a5fcbb6
10 changed files with 336 additions and 147 deletions

View File

@@ -7,40 +7,84 @@
#include "nvim/charset.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ui.h"
/*
* Handling of cursor and mouse pointer shapes in various modes.
*/
/// Handling of cursor and mouse pointer shapes in various modes.
static cursorentry_T shape_table[SHAPE_IDX_COUNT] =
{
/* The values will be filled in from the 'guicursor' and 'mouseshape'
* defaults when Vim starts.
* Adjust the SHAPE_IDX_ defines when making changes! */
{0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
{0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE},
{0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE},
{0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE},
{0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE},
{0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE},
{0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE},
{0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE},
{0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
// The values will be filled in from the 'guicursor' and 'mouseshape'
// defaults when Vim starts.
// Adjust the SHAPE_IDX_ defines when making changes!
{ "normal",
0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE },
{ "visual",
0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE },
{ "insert",
0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE },
{ "replace",
0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE },
{ "cmd_normal",
0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE },
{ "cmd_insert", 0,
0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE },
{ "cmd_replace",
0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE },
{ "pending",
0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE },
{ "visual_select",
0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE },
{ "cmd_line", 0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE },
{ "statusline", 0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE },
{ "drag_statusline", 0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE },
{ "vsep", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE },
{ "vdrag", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE },
{ "more", 0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE },
{ "more_lastline", 0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE },
{ "match_paren", 0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR },
};
/*
* Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
* ("what" is SHAPE_MOUSE).
* Returns error message for an illegal option, NULL otherwise.
*/
/// Converts cursor_shapes into a Dictionary of dictionaries
/// @return a dictionary of the form {"normal" : { "cursor_shape": ... }, ...}
Dictionary cursor_shape_dict(void)
{
Dictionary all = ARRAY_DICT_INIT;
for (int i = 0; i < SHAPE_IDX_COUNT; i++) {
Dictionary dic = ARRAY_DICT_INIT;
cursorentry_T *cur = &shape_table[i];
if (cur->used_for & SHAPE_MOUSE) {
PUT(dic, "mouse_shape", INTEGER_OBJ(cur->mshape));
}
if (cur->used_for & SHAPE_CURSOR) {
String shape_str;
switch (cur->shape) {
case SHAPE_BLOCK: shape_str = cstr_to_string("block"); break;
case SHAPE_VER: shape_str = cstr_to_string("vertical"); break;
case SHAPE_HOR: shape_str = cstr_to_string("horizontal"); break;
default: shape_str = cstr_to_string("unknown");
}
PUT(dic, "cursor_shape", STRING_OBJ(shape_str));
PUT(dic, "cell_percentage", INTEGER_OBJ(cur->percentage));
PUT(dic, "blinkwait", INTEGER_OBJ(cur->blinkwait));
PUT(dic, "blinkon", INTEGER_OBJ(cur->blinkon));
PUT(dic, "blinkoff", INTEGER_OBJ(cur->blinkoff));
PUT(dic, "hl_id", INTEGER_OBJ(cur->id));
PUT(dic, "id_lm", INTEGER_OBJ(cur->id_lm));
}
PUT(dic, "short_name", STRING_OBJ(cstr_to_string(cur->name)));
PUT(all, cur->full_name, DICTIONARY_OBJ(dic));
}
return all;
}
/// Parse the 'guicursor' option
///
/// @param what either SHAPE_CURSOR or SHAPE_MOUSE ('mouseshape')
///
/// @returns error message for an illegal option, NULL otherwise.
char_u *parse_shape_opt(int what)
{
char_u *modep;
@@ -71,19 +115,18 @@ char_u *parse_shape_opt(int what)
return (char_u *)N_("E546: Illegal mode");
commap = vim_strchr(modep, ',');
/*
* Repeat for all mode's before the colon.
* For the 'a' mode, we loop to handle all the modes.
*/
// Repeat for all mode's before the colon.
// For the 'a' mode, we loop to handle all the modes.
all_idx = -1;
assert(modep < colonp);
while (modep < colonp || all_idx >= 0) {
if (all_idx < 0) {
/* Find the mode. */
if (modep[1] == '-' || modep[1] == ':')
// Find the mode
if (modep[1] == '-' || modep[1] == ':') {
len = 1;
else
} else {
len = 2;
}
if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') {
all_idx = SHAPE_IDX_COUNT - 1;
@@ -100,11 +143,11 @@ char_u *parse_shape_opt(int what)
modep += len + 1;
}
if (all_idx >= 0)
if (all_idx >= 0) {
idx = all_idx--;
else if (round == 2) {
} else if (round == 2) {
{
/* Set the defaults, for the missing parts */
// Set the defaults, for the missing parts
shape_table[idx].shape = SHAPE_BLOCK;
shape_table[idx].blinkwait = 700L;
shape_table[idx].blinkon = 400L;
@@ -208,6 +251,23 @@ char_u *parse_shape_opt(int what)
shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
}
}
ui_cursor_style_set();
return NULL;
}
/// Map cursor mode from string to integer
///
/// @param mode Fullname of the mode whose id we are looking for
/// @return -1 in case of failure, else the matching SHAPE_ID* integer
int cursor_mode_str2int(const char *mode)
{
for (int current_mode = 0; current_mode < SHAPE_IDX_COUNT; current_mode++) {
if (strcmp(shape_table[current_mode].full_name, mode) == 0) {
return current_mode;
}
}
ELOG("Unknown mode %s", mode);
return -1;
}