Merge pull request #16541 from jamessan/vim-8.2.3664

vim-patch:8.2.3664,8.2.3743,8.2.3747,8.2.3748,8.2.3757
This commit is contained in:
James McCoy
2021-12-09 21:29:15 -05:00
committed by GitHub
14 changed files with 369 additions and 29 deletions

View File

@@ -997,6 +997,8 @@ EXTERN char e_non_empty_string_required[] INIT(= N_("E1142: Non-empty string req
EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cannot define autocommands for ALL events"));
EXTERN char e_highlight_group_name_too_long[] INIT(= N_("E1249: Highlight group name too long"));
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
EXTERN char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP"));

View File

@@ -65,6 +65,8 @@ typedef enum {
HLF_LNA, // LineNrAbove
HLF_LNB, // LineNrBelow
HLF_CLN, // current line number when 'cursorline' is set
HLF_CLS, // current line sign column
HLF_CLF, // current line fold
HLF_R, // return to continue message and yes/no questions
HLF_S, // status lines
HLF_SNC, // status lines of not-current windows
@@ -122,6 +124,8 @@ EXTERN const char *hlf_names[] INIT(= {
[HLF_LNA] = "LineNrAbove",
[HLF_LNB] = "LineNrBelow",
[HLF_CLN] = "CursorLineNr",
[HLF_CLS] = "CursorLineSign",
[HLF_CLF] = "CursorLineFold",
[HLF_R] = "Question",
[HLF_S] = "StatusLine",
[HLF_SNC] = "StatusLineNC",

View File

@@ -262,6 +262,7 @@ typedef struct vimoption {
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \
"i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr," \
"G:CursorLineSign,O:CursorLineFold" \
"r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg," \
"W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn," \
"-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar," \

View File

@@ -2746,7 +2746,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
p_extra = p_extra_free;
c_extra = NUL;
c_final = NUL;
char_attr = win_hl_attr(wp, HLF_FC);
if (use_cursor_line_sign(wp, lnum)) {
char_attr = win_hl_attr(wp, HLF_CLF);
} else {
char_attr = win_hl_attr(wp, HLF_FC);
}
}
}
@@ -2757,7 +2761,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
* buffer or when using Netbeans. */
int count = win_signcol_count(wp);
if (count > 0) {
get_sign_display_info(false, wp, sattrs, row,
get_sign_display_info(false, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo, count,
&c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra,
@@ -2778,7 +2782,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u'
&& num_signs > 0) {
int count = win_signcol_count(wp);
get_sign_display_info(true, wp, sattrs, row,
get_sign_display_info(true, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo, count,
&c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra,
@@ -4617,6 +4621,14 @@ void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off)
}
}
// Return true if CursorLineSign highlight is to be used.
static bool use_cursor_line_sign(win_T *wp, linenr_T lnum)
{
return wp->w_p_cul
&& lnum == wp->w_cursor.lnum
&& (wp->w_p_culopt_flags & CULOPT_NBR);
}
// Get information needed to display the sign in line 'lnum' in window 'wp'.
// If 'nrcol' is TRUE, the sign is going to be displayed in the number column.
// Otherwise the sign is going to be displayed in the sign column.
@@ -4624,11 +4636,11 @@ void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off)
// @param count max number of signs
// @param[out] n_extrap number of characters from pp_extra to display
// @param[in, out] sign_idxp Index of the displayed sign
static void get_sign_display_info(bool nrcol, win_T *wp, sign_attrs_T sattrs[], int row,
int startrow, int filler_lines, int filler_todo, int count,
int *c_extrap, int *c_finalp, char_u *extra, size_t extra_size,
char_u **pp_extra, int *n_extrap, int *char_attrp,
int *draw_statep, int *sign_idxp)
static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, sign_attrs_T sattrs[],
int row, int startrow, int filler_lines, int filler_todo,
int count, int *c_extrap, int *c_finalp, char_u *extra,
size_t extra_size, char_u **pp_extra, int *n_extrap,
int *char_attrp, int *draw_statep, int *sign_idxp)
{
// Draw cells with the sign value or blank.
*c_extrap = ' ';
@@ -4636,7 +4648,11 @@ static void get_sign_display_info(bool nrcol, win_T *wp, sign_attrs_T sattrs[],
if (nrcol) {
*n_extrap = number_width(wp) + 1;
} else {
*char_attrp = win_hl_attr(wp, HLF_SC);
if (use_cursor_line_sign(wp, lnum)) {
*char_attrp = win_hl_attr(wp, HLF_CLS);
} else {
*char_attrp = win_hl_attr(wp, HLF_SC);
}
*n_extrap = win_signcol_width(wp);
}
@@ -4676,7 +4692,12 @@ static void get_sign_display_info(bool nrcol, win_T *wp, sign_attrs_T sattrs[],
(*pp_extra)[*n_extrap] = NUL;
}
}
*char_attrp = sattr->sat_texthl;
if (use_cursor_line_sign(wp, lnum) && sattr->sat_culhl > 0) {
*char_attrp = sattr->sat_culhl;
} else {
*char_attrp = sattr->sat_texthl;
}
}
}

View File

@@ -31,6 +31,7 @@ struct sign {
char_u *sn_text; // text used instead of pixmap
int sn_line_hl; // highlight ID for line
int sn_text_hl; // highlight ID for text
int sn_cul_hl; // highlight ID for text on current line when 'cursorline' is set
int sn_num_hl; // highlight ID for line number
};
@@ -499,6 +500,9 @@ int buf_get_signattrs(buf_T *buf, linenr_T lnum, sign_attrs_T sattrs[])
if (sp->sn_line_hl != 0) {
sattr.sat_linehl = syn_id2attr(sp->sn_line_hl);
}
if (sp->sn_cul_hl != 0) {
sattr.sat_culhl = syn_id2attr(sp->sn_cul_hl);
}
if (sp->sn_num_hl != 0) {
sattr.sat_numhl = syn_id2attr(sp->sn_num_hl);
}
@@ -901,7 +905,7 @@ static int sign_define_init_text(sign_T *sp, char_u *text)
/// Define a new sign or update an existing sign
int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl,
char *numhl)
char_u *culhl, char *numhl)
{
sign_T *sp_prev;
sign_T *sp;
@@ -939,15 +943,35 @@ int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text
}
if (linehl != NULL) {
sp->sn_line_hl = syn_check_group((char *)linehl, (int)STRLEN(linehl));
if (*linehl == NUL) {
sp->sn_line_hl = 0;
} else {
sp->sn_line_hl = syn_check_group((char *)linehl, (int)STRLEN(linehl));
}
}
if (texthl != NULL) {
sp->sn_text_hl = syn_check_group((char *)texthl, (int)STRLEN(texthl));
if (*texthl == NUL) {
sp->sn_text_hl = 0;
} else {
sp->sn_text_hl = syn_check_group((char *)texthl, (int)STRLEN(texthl));
}
}
if (culhl != NULL) {
if (*culhl == NUL) {
sp->sn_cul_hl = 0;
} else {
sp->sn_cul_hl = syn_check_group((char *)culhl, (int)STRLEN(culhl));
}
}
if (numhl != NULL) {
sp->sn_num_hl = syn_check_group(numhl, (int)STRLEN(numhl));
if (*numhl == NUL) {
sp->sn_num_hl = 0;
} else {
sp->sn_num_hl = syn_check_group(numhl, (int)STRLEN(numhl));
}
}
return OK;
@@ -1133,6 +1157,7 @@ static void sign_define_cmd(char_u *sign_name, char_u *cmdline)
char_u *text = NULL;
char_u *linehl = NULL;
char_u *texthl = NULL;
char_u *culhl = NULL;
char_u *numhl = NULL;
int failed = false;
@@ -1155,6 +1180,9 @@ static void sign_define_cmd(char_u *sign_name, char_u *cmdline)
} else if (STRNCMP(arg, "texthl=", 7) == 0) {
arg += 7;
texthl = vim_strnsave(arg, (size_t)(p - arg));
} else if (STRNCMP(arg, "culhl=", 6) == 0) {
arg += 6;
culhl = vim_strnsave(arg, (size_t)(p - arg));
} else if (STRNCMP(arg, "numhl=", 6) == 0) {
arg += 6;
numhl = vim_strnsave(arg, (size_t)(p - arg));
@@ -1166,13 +1194,14 @@ static void sign_define_cmd(char_u *sign_name, char_u *cmdline)
}
if (!failed) {
sign_define_by_name(sign_name, icon, linehl, text, texthl, (char *)numhl);
sign_define_by_name(sign_name, icon, linehl, text, texthl, culhl, (char *)numhl);
}
xfree(icon);
xfree(text);
xfree(linehl);
xfree(texthl);
xfree(culhl);
xfree(numhl);
}
@@ -1481,6 +1510,13 @@ static void sign_getinfo(sign_T *sp, dict_T *retdict)
}
tv_dict_add_str(retdict, S_LEN("texthl"), (char *)p);
}
if (sp->sn_cul_hl > 0) {
p = get_highlight_name_ext(NULL, sp->sn_cul_hl - 1, false);
if (p == NULL) {
p = "NONE";
}
tv_dict_add_str(retdict, S_LEN("culhl"), (char *)p);
}
if (sp->sn_num_hl > 0) {
p = get_highlight_name_ext(NULL, sp->sn_num_hl - 1, false);
if (p == NULL) {
@@ -1609,6 +1645,16 @@ static void sign_list_defined(sign_T *sp)
msg_puts(p);
}
}
if (sp->sn_cul_hl > 0) {
msg_puts(" culhl=");
const char *const p = get_highlight_name_ext(NULL,
sp->sn_cul_hl - 1, false);
if (p == NULL) {
msg_puts("NONE");
} else {
msg_puts(p);
}
}
if (sp->sn_num_hl > 0) {
msg_puts(" numhl=");
const char *const p = get_highlight_name_ext(NULL,
@@ -1847,6 +1893,7 @@ int sign_define_from_dict(const char *name_arg, dict_T *dict)
char *linehl = NULL;
char *text = NULL;
char *texthl = NULL;
char *culhl = NULL;
char *numhl = NULL;
int retval = -1;
@@ -1866,11 +1913,12 @@ int sign_define_from_dict(const char *name_arg, dict_T *dict)
linehl = tv_dict_get_string(dict, "linehl", true);
text = tv_dict_get_string(dict, "text", true);
texthl = tv_dict_get_string(dict, "texthl", true);
culhl = tv_dict_get_string(dict, "culhl", true);
numhl = tv_dict_get_string(dict, "numhl", true);
}
if (sign_define_by_name((char_u *)name, (char_u *)icon, (char_u *)linehl,
(char_u *)text, (char_u *)texthl, numhl)
(char_u *)text, (char_u *)texthl, (char_u *)culhl, numhl)
== OK) {
retval = 0;
}
@@ -1881,6 +1929,7 @@ cleanup:
xfree(linehl);
xfree(text);
xfree(texthl);
xfree(culhl);
xfree(numhl);
return retval;

View File

@@ -38,6 +38,7 @@ typedef struct sign_attrs_S {
char_u *sat_text;
int sat_texthl;
int sat_linehl;
int sat_culhl;
int sat_numhl;
} sign_attrs_T;

View File

@@ -115,6 +115,8 @@ static int include_none = 0; // when 1 include "nvim/None"
static int include_default = 0; // when 1 include "nvim/default"
static int include_link = 0; // when 2 include "nvim/link" and "clear"
#define MAX_SYN_NAME 200
/// The "term", "cterm" and "gui" arguments can be any combination of the
/// following names, separated by commas (but no spaces!).
static char *(hl_name_table[]) =
@@ -6175,6 +6177,8 @@ static const char *highlight_init_both[] = {
"default link LineNrAbove LineNr",
"default link LineNrBelow LineNr",
"default link QuickFixLine Search",
"default link CursorLineSign SignColumn",
"default link CursorLineFold FoldColumn",
"default link Substitute Search",
"default link Whitespace NonText",
"default link MsgSeparator StatusLine",
@@ -7623,10 +7627,9 @@ int syn_name2id(const char *name)
int syn_name2id_len(const char_u *name, size_t len)
FUNC_ATTR_NONNULL_ALL
{
char name_u[201];
char name_u[MAX_SYN_NAME + 1];
if (len == 0 || len > 200) {
// ID names over 200 chars don't deserve to be found!
if (len == 0 || len > MAX_SYN_NAME) {
return 0;
}
@@ -7684,6 +7687,10 @@ char_u *syn_id2name(int id)
/// @return 0 for failure else the id of the group
int syn_check_group(const char *name, int len)
{
if (len > MAX_SYN_NAME) {
emsg(_(e_highlight_group_name_too_long));
return 0;
}
int id = syn_name2id_len((char_u *)name, len);
if (id == 0) { // doesn't exist yet
return syn_add_group(vim_strnsave((char_u *)name, len));

View File

@@ -661,6 +661,13 @@ function Test_no_space_before_xxx()
let &columns = l:org_columns
endfunction
" Test for :highlight command errors
func Test_highlight_cmd_errors()
if has('gui_running') || has('nvim')
call assert_fails('hi ' .. repeat('a', 201) .. ' ctermfg=black', 'E1249:')
endif
endfunc
" Test for using RGB color values in a highlight group
func Test_xxlast_highlight_RGB_color()
CheckCanRunGui

View File

@@ -15,13 +15,13 @@ func Test_sign()
" the icon name when listing signs.
sign define Sign1 text=x
call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error icon=../../pixmaps/stock_vim_find_help.png')
call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error culhl=Search icon=../../pixmaps/stock_vim_find_help.png')
" Test listing signs.
let a=execute('sign list')
call assert_match('^\nsign Sign1 text=x \nsign Sign2 ' .
\ 'icon=../../pixmaps/stock_vim_find_help.png .*text=xy ' .
\ 'linehl=Error texthl=Title$', a)
\ 'linehl=Error texthl=Title culhl=Search$', a)
let a=execute('sign list Sign1')
call assert_equal("\nsign Sign1 text=x ", a)
@@ -126,6 +126,30 @@ func Test_sign()
" call assert_fails("sign define Sign4 text= linehl=Comment", 'E239:')
call assert_fails("sign define Sign4 text=\\ ab linehl=Comment", 'E239:')
" an empty highlight argument for an existing sign clears it
sign define SignY texthl=TextHl culhl=CulHl linehl=LineHl
let sl = sign_getdefined('SignY')[0]
call assert_equal('TextHl', sl.texthl)
call assert_equal('CulHl', sl.culhl)
call assert_equal('LineHl', sl.linehl)
sign define SignY texthl= culhl=CulHl linehl=LineHl
let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'texthl'))
call assert_equal('CulHl', sl.culhl)
call assert_equal('LineHl', sl.linehl)
sign define SignY linehl=
let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'linehl'))
call assert_equal('CulHl', sl.culhl)
sign define SignY culhl=
let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'culhl'))
sign undefine SignY
" define sign with whitespace
sign define Sign4 text=\ X linehl=Comment
sign undefine Sign4
@@ -392,19 +416,21 @@ func Test_sign_funcs()
call sign_undefine()
" Tests for sign_define()
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error',
\ 'culhl': 'Visual'}
call assert_equal(0, "sign1"->sign_define(attr))
call assert_equal([{'name' : 'sign1', 'texthl' : 'Error',
\ 'linehl' : 'Search', 'text' : '=>'}], sign_getdefined())
\ 'linehl' : 'Search', 'culhl': 'Visual', 'text' : '=>'}],
\ sign_getdefined())
" Define a new sign without attributes and then update it
call sign_define("sign2")
let attr = {'text' : '!!', 'linehl' : 'DiffAdd', 'texthl' : 'DiffChange',
\ 'icon' : 'sign2.ico'}
\ 'culhl': 'DiffDelete', 'icon' : 'sign2.ico'}
call Sign_define_ignore_error("sign2", attr)
call assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange',
\ 'linehl' : 'DiffAdd', 'text' : '!!', 'icon' : 'sign2.ico'}],
\ "sign2"->sign_getdefined())
\ 'linehl' : 'DiffAdd', 'culhl' : 'DiffDelete', 'text' : '!!',
\ 'icon' : 'sign2.ico'}], "sign2"->sign_getdefined())
" Test for a sign name with digits
call assert_equal(0, sign_define(0002, {'linehl' : 'StatusLine'}))