1
0
forked from aniani/vim

patch 8.2.3874: cannot highlight the number column for a sign

Problem:    Cannot highlight the number column for a sign.
Solution:   Add the "numhl" argument. (James McCoy, closes #9381)
This commit is contained in:
James McCoy 2021-12-22 19:45:28 +00:00 committed by Bram Moolenaar
parent 82b3b4c6cf
commit a80aad7174
9 changed files with 94 additions and 26 deletions

View File

@ -5601,8 +5601,8 @@ A jump table for the options with a short description can be found at |Q_op|.
number. number.
When a long, wrapped line doesn't start with the first character, '-' When a long, wrapped line doesn't start with the first character, '-'
characters are put before the number. characters are put before the number.
See |hl-LineNr| and |hl-CursorLineNr| for the highlighting used for For highlighting see |hl-LineNr|, and |hl-CursorLineNr|, and the
the number. |:sign-define| "numhl" argument.
*number_relativenumber* *number_relativenumber*
The 'relativenumber' option changes the displayed number to be The 'relativenumber' option changes the displayed number to be
relative to the cursor. Together with 'number' there are these relative to the cursor. Together with 'number' there are these

View File

@ -140,6 +140,11 @@ See |sign_define()| for the equivalent Vim script function.
Highlighting group used for the whole line the sign is placed Highlighting group used for the whole line the sign is placed
in. Most useful is defining a background color. in. Most useful is defining a background color.
numhl={group}
Highlighting group used for the line number on the line where
the sign is placed. Overrides |hl-LineNr|, |hl-LineNrAbove|,
|hl-LineNrBelow|, and |hl-CursorLineNr|.
text={text} *E239* text={text} *E239*
Define the text that is displayed when there is no icon or the Define the text that is displayed when there is no icon or the
GUI is not being used. Only printable characters are allowed GUI is not being used. Only printable characters are allowed
@ -396,6 +401,8 @@ sign_define({list})
icon full path to the bitmap file for the sign. icon full path to the bitmap file for the sign.
linehl highlight group used for the whole line the linehl highlight group used for the whole line the
sign is placed in. sign is placed in.
numhl highlight group used for the line number where
the sign is placed.
text text that is displayed when there is no icon text text that is displayed when there is no icon
or the GUI is not being used. or the GUI is not being used.
texthl highlight group used for the text item texthl highlight group used for the text item
@ -443,6 +450,8 @@ sign_getdefined([{name}]) *sign_getdefined()*
linehl highlight group used for the whole line the linehl highlight group used for the whole line the
sign is placed in; not present if not set sign is placed in; not present if not set
name name of the sign name name of the sign
numhl highlight group used for the line number where
the sign is placed; not present if not set
text text that is displayed when there is no icon text text that is displayed when there is no icon
or the GUI is not being used. or the GUI is not being used.
texthl highlight group used for the text item; not texthl highlight group used for the text item; not

View File

@ -377,6 +377,7 @@ win_line(
#ifdef FEAT_SIGNS #ifdef FEAT_SIGNS
int sign_present = FALSE; int sign_present = FALSE;
sign_attrs_T sattr; sign_attrs_T sattr;
int num_attr = 0; // attribute for the number column
#endif #endif
#ifdef FEAT_ARABIC #ifdef FEAT_ARABIC
int prev_c = 0; // previous Arabic character int prev_c = 0; // previous Arabic character
@ -699,6 +700,8 @@ win_line(
#ifdef FEAT_SIGNS #ifdef FEAT_SIGNS
sign_present = buf_get_signattrs(wp, lnum, &sattr); sign_present = buf_get_signattrs(wp, lnum, &sattr);
if (sign_present)
num_attr = sattr.sat_numhl;
#endif #endif
#ifdef LINE_ATTR #ifdef LINE_ATTR
@ -1206,6 +1209,10 @@ win_line(
char_attr = hl_combine_attr(wcr_attr, char_attr = hl_combine_attr(wcr_attr,
HL_ATTR(HLF_LNB)); HL_ATTR(HLF_LNB));
} }
#ifdef FEAT_SIGNS
if (num_attr)
char_attr = num_attr;
#endif
} }
} }

View File

@ -632,7 +632,7 @@ popup_highlight_curline(win_T *wp)
if (syn_name2id((char_u *)linehl) == 0) if (syn_name2id((char_u *)linehl) == 0)
linehl = "PmenuSel"; linehl = "PmenuSel";
sign_define_by_name(sign_name, NULL, (char_u *)linehl, NULL, NULL, NULL); sign_define_by_name(sign_name, NULL, (char_u *)linehl, NULL, NULL, NULL, NULL);
} }
sign_place(&sign_id, (char_u *)"PopUpMenu", sign_name, sign_place(&sign_id, (char_u *)"PopUpMenu", sign_name,

View File

@ -8,7 +8,7 @@ int buf_findsigntype_id(buf_T *buf, linenr_T lnum, int typenr);
int buf_signcount(buf_T *buf, linenr_T lnum); int buf_signcount(buf_T *buf, linenr_T lnum);
void buf_delete_signs(buf_T *buf, char_u *group); void buf_delete_signs(buf_T *buf, char_u *group);
void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after); void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after);
int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl, char_u *culhl); int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl, char_u *culhl, char_u *numhl);
int sign_exists_by_name(char_u *name); int sign_exists_by_name(char_u *name);
int sign_undefine_by_name(char_u *name, int give_error); int sign_undefine_by_name(char_u *name, int give_error);
int sign_place(int *sign_id, char_u *sign_group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio); int sign_place(int *sign_id, char_u *sign_group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio);

View File

@ -33,6 +33,7 @@ struct sign
int sn_line_hl; // highlight ID for line int sn_line_hl; // highlight ID for line
int sn_text_hl; // highlight ID for text 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_cul_hl; // highlight ID for text on current line when 'cursorline' is set
int sn_num_hl; // highlight ID for line number
}; };
static sign_T *first_sign = NULL; static sign_T *first_sign = NULL;
@ -520,6 +521,8 @@ buf_get_signattrs(win_T *wp, linenr_T lnum, sign_attrs_T *sattr)
sattr->sat_linehl = syn_id2attr(sp->sn_line_hl); sattr->sat_linehl = syn_id2attr(sp->sn_line_hl);
if (sp->sn_cul_hl > 0) if (sp->sn_cul_hl > 0)
sattr->sat_culhl = syn_id2attr(sp->sn_cul_hl); sattr->sat_culhl = syn_id2attr(sp->sn_cul_hl);
if (sp->sn_num_hl > 0)
sattr->sat_numhl = syn_id2attr(sp->sn_num_hl);
sattr->sat_priority = sign->se_priority; sattr->sat_priority = sign->se_priority;
// If there is another sign next with the same priority, may // If there is another sign next with the same priority, may
@ -545,6 +548,8 @@ buf_get_signattrs(win_T *wp, linenr_T lnum, sign_attrs_T *sattr)
sattr->sat_linehl = syn_id2attr(next_sp->sn_line_hl); sattr->sat_linehl = syn_id2attr(next_sp->sn_line_hl);
if (sp->sn_cul_hl <= 0 && next_sp->sn_cul_hl > 0) if (sp->sn_cul_hl <= 0 && next_sp->sn_cul_hl > 0)
sattr->sat_culhl = syn_id2attr(next_sp->sn_cul_hl); sattr->sat_culhl = syn_id2attr(next_sp->sn_cul_hl);
if (sp->sn_num_hl <= 0 && next_sp->sn_num_hl > 0)
sattr->sat_numhl = syn_id2attr(next_sp->sn_num_hl);
} }
} }
return TRUE; return TRUE;
@ -1041,7 +1046,8 @@ sign_define_by_name(
char_u *linehl, char_u *linehl,
char_u *text, char_u *text,
char_u *texthl, char_u *texthl,
char_u *culhl) char_u *culhl,
char_u *numhl)
{ {
sign_T *sp_prev; sign_T *sp_prev;
sign_T *sp; sign_T *sp;
@ -1101,6 +1107,14 @@ sign_define_by_name(
sp->sn_cul_hl = syn_check_group(culhl, (int)STRLEN(culhl)); sp->sn_cul_hl = syn_check_group(culhl, (int)STRLEN(culhl));
} }
if (numhl != NULL)
{
if (*numhl == NUL)
sp->sn_num_hl = 0;
else
sp->sn_num_hl = syn_check_group(numhl, (int)STRLEN(numhl));
}
return OK; return OK;
} }
@ -1323,6 +1337,7 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline)
char_u *linehl = NULL; char_u *linehl = NULL;
char_u *texthl = NULL; char_u *texthl = NULL;
char_u *culhl = NULL; char_u *culhl = NULL;
char_u *numhl = NULL;
int failed = FALSE; int failed = FALSE;
// set values for a defined sign. // set values for a defined sign.
@ -1357,6 +1372,11 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline)
arg += 6; arg += 6;
culhl = vim_strnsave(arg, p - arg); culhl = vim_strnsave(arg, p - arg);
} }
else if (STRNCMP(arg, "numhl=", 6) == 0)
{
arg += 6;
numhl = vim_strnsave(arg, p - arg);
}
else else
{ {
semsg(_(e_invarg2), arg); semsg(_(e_invarg2), arg);
@ -1366,13 +1386,14 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline)
} }
if (!failed) if (!failed)
sign_define_by_name(sign_name, icon, linehl, text, texthl, culhl); sign_define_by_name(sign_name, icon, linehl, text, texthl, culhl, numhl);
vim_free(icon); vim_free(icon);
vim_free(text); vim_free(text);
vim_free(linehl); vim_free(linehl);
vim_free(texthl); vim_free(texthl);
vim_free(culhl); vim_free(culhl);
vim_free(numhl);
} }
/* /*
@ -1750,6 +1771,13 @@ sign_getinfo(sign_T *sp, dict_T *retdict)
p = (char_u *)"NONE"; p = (char_u *)"NONE";
dict_add_string(retdict, "culhl", (char_u *)p); dict_add_string(retdict, "culhl", (char_u *)p);
} }
if (sp->sn_num_hl > 0)
{
p = get_highlight_name_ext(NULL, sp->sn_num_hl - 1, FALSE);
if (p == NULL)
p = (char_u *)"NONE";
dict_add_string(retdict, "numhl", (char_u *)p);
}
} }
/* /*
@ -1930,6 +1958,15 @@ sign_list_defined(sign_T *sp)
else else
msg_puts((char *)p); msg_puts((char *)p);
} }
if (sp->sn_num_hl > 0)
{
msg_puts(" numhl=");
p = get_highlight_name_ext(NULL, sp->sn_num_hl - 1, FALSE);
if (p == NULL)
msg_puts("NONE");
else
msg_puts((char *)p);
}
} }
/* /*
@ -2051,7 +2088,7 @@ get_sign_name(expand_T *xp UNUSED, int idx)
{ {
char *define_arg[] = char *define_arg[] =
{ {
"icon=", "linehl=", "text=", "texthl=", NULL "culhl=", "icon=", "linehl=", "numhl=", "text=", "texthl=", NULL
}; };
return (char_u *)define_arg[idx]; return (char_u *)define_arg[idx];
} }
@ -2176,7 +2213,9 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
{ {
case SIGNCMD_DEFINE: case SIGNCMD_DEFINE:
if (STRNCMP(last, "texthl", 6) == 0 if (STRNCMP(last, "texthl", 6) == 0
|| STRNCMP(last, "linehl", 6) == 0) || STRNCMP(last, "linehl", 6) == 0
|| STRNCMP(last, "culhl", 5) == 0
|| STRNCMP(last, "numhl", 5) == 0)
xp->xp_context = EXPAND_HIGHLIGHT; xp->xp_context = EXPAND_HIGHLIGHT;
else if (STRNCMP(last, "icon", 4) == 0) else if (STRNCMP(last, "icon", 4) == 0)
xp->xp_context = EXPAND_FILES; xp->xp_context = EXPAND_FILES;
@ -2221,6 +2260,7 @@ sign_define_from_dict(char_u *name_arg, dict_T *dict)
char_u *text = NULL; char_u *text = NULL;
char_u *texthl = NULL; char_u *texthl = NULL;
char_u *culhl = NULL; char_u *culhl = NULL;
char_u *numhl = NULL;
int retval = -1; int retval = -1;
if (name_arg == NULL) if (name_arg == NULL)
@ -2240,9 +2280,10 @@ sign_define_from_dict(char_u *name_arg, dict_T *dict)
text = dict_get_string(dict, (char_u *)"text", TRUE); text = dict_get_string(dict, (char_u *)"text", TRUE);
texthl = dict_get_string(dict, (char_u *)"texthl", TRUE); texthl = dict_get_string(dict, (char_u *)"texthl", TRUE);
culhl = dict_get_string(dict, (char_u *)"culhl", TRUE); culhl = dict_get_string(dict, (char_u *)"culhl", TRUE);
numhl = dict_get_string(dict, (char_u *)"numhl", TRUE);
} }
if (sign_define_by_name(name, icon, linehl, text, texthl, culhl) == OK) if (sign_define_by_name(name, icon, linehl, text, texthl, culhl, numhl) == OK)
retval = 0; retval = 0;
cleanup: cleanup:
@ -2252,6 +2293,7 @@ cleanup:
vim_free(text); vim_free(text);
vim_free(texthl); vim_free(texthl);
vim_free(culhl); vim_free(culhl);
vim_free(numhl);
return retval; return retval;
} }

View File

@ -854,6 +854,7 @@ typedef struct sign_attrs_S {
int sat_texthl; int sat_texthl;
int sat_linehl; int sat_linehl;
int sat_culhl; int sat_culhl;
int sat_numhl;
int sat_priority; int sat_priority;
} sign_attrs_T; } sign_attrs_T;

View File

@ -15,13 +15,13 @@ func Test_sign()
" the icon name when listing signs. " the icon name when listing signs.
sign define Sign1 text=x sign define Sign1 text=x
call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error culhl=Search icon=../../pixmaps/stock_vim_find_help.png') call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error culhl=Search numhl=Number icon=../../pixmaps/stock_vim_find_help.png')
" Test listing signs. " Test listing signs.
let a=execute('sign list') let a=execute('sign list')
call assert_match('^\nsign Sign1 text=x \nsign Sign2 ' . call assert_match('^\nsign Sign1 text=x \nsign Sign2 ' .
\ 'icon=../../pixmaps/stock_vim_find_help.png .*text=xy ' . \ 'icon=../../pixmaps/stock_vim_find_help.png .*text=xy ' .
\ 'linehl=Error texthl=Title culhl=Search$', a) \ 'linehl=Error texthl=Title culhl=Search numhl=Number$', a)
let a=execute('sign list Sign1') let a=execute('sign list Sign1')
call assert_equal("\nsign Sign1 text=x ", a) call assert_equal("\nsign Sign1 text=x ", a)
@ -127,26 +127,34 @@ func Test_sign()
call assert_fails("sign define Sign4 text=\\ ab linehl=Comment", 'E239:') call assert_fails("sign define Sign4 text=\\ ab linehl=Comment", 'E239:')
" an empty highlight argument for an existing sign clears it " an empty highlight argument for an existing sign clears it
sign define SignY texthl=TextHl culhl=CulHl linehl=LineHl sign define SignY texthl=TextHl culhl=CulHl linehl=LineHl numhl=NumHl
let sl = sign_getdefined('SignY')[0] let sl = sign_getdefined('SignY')[0]
call assert_equal('TextHl', sl.texthl) call assert_equal('TextHl', sl.texthl)
call assert_equal('CulHl', sl.culhl) call assert_equal('CulHl', sl.culhl)
call assert_equal('LineHl', sl.linehl) call assert_equal('LineHl', sl.linehl)
call assert_equal('NumHl', sl.numhl)
sign define SignY texthl= culhl=CulHl linehl=LineHl sign define SignY texthl= culhl=CulHl linehl=LineHl numhl=NumHl
let sl = sign_getdefined('SignY')[0] let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'texthl')) call assert_false(has_key(sl, 'texthl'))
call assert_equal('CulHl', sl.culhl) call assert_equal('CulHl', sl.culhl)
call assert_equal('LineHl', sl.linehl) call assert_equal('LineHl', sl.linehl)
call assert_equal('NumHl', sl.numhl)
sign define SignY linehl= sign define SignY linehl=
let sl = sign_getdefined('SignY')[0] let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'linehl')) call assert_false(has_key(sl, 'linehl'))
call assert_equal('CulHl', sl.culhl) call assert_equal('CulHl', sl.culhl)
call assert_equal('NumHl', sl.numhl)
sign define SignY culhl= sign define SignY culhl=
let sl = sign_getdefined('SignY')[0] let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'culhl')) call assert_false(has_key(sl, 'culhl'))
call assert_equal('NumHl', sl.numhl)
sign define SignY numhl=
let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'numhl'))
sign undefine SignY sign undefine SignY
@ -218,15 +226,13 @@ func Test_sign_completion()
call assert_equal('"sign define jump list place undefine unplace', @:) call assert_equal('"sign define jump list place undefine unplace', @:)
call feedkeys(":sign define Sign \<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":sign define Sign \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define Sign icon= linehl= text= texthl=', @:) call assert_equal('"sign define Sign culhl= icon= linehl= numhl= text= texthl=', @:)
call feedkeys(":sign define Sign linehl=Spell\<C-A>\<C-B>\"\<CR>", 'tx') for hl in ['culhl', 'linehl', 'numhl', 'texthl']
call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' . call feedkeys(":sign define Sign "..hl.."=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
\ 'SpellLocal SpellRare', @:) call assert_equal('"sign define Sign '..hl..'=SpellBad SpellCap ' .
call feedkeys(":sign define Sign texthl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define Sign texthl=SpellBad SpellCap ' .
\ 'SpellLocal SpellRare', @:) \ 'SpellLocal SpellRare', @:)
endfor
call writefile(repeat(["Sun is shining"], 30), "XsignOne") call writefile(repeat(["Sun is shining"], 30), "XsignOne")
call writefile(repeat(["Sky is blue"], 30), "XsignTwo") call writefile(repeat(["Sky is blue"], 30), "XsignTwo")
@ -417,20 +423,21 @@ func Test_sign_funcs()
" Tests for sign_define() " Tests for sign_define()
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error', let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error',
\ 'culhl': 'Visual'} \ 'culhl': 'Visual', 'numhl': 'Number'}
call assert_equal(0, "sign1"->sign_define(attr)) call assert_equal(0, "sign1"->sign_define(attr))
call assert_equal([{'name' : 'sign1', 'texthl' : 'Error', call assert_equal([{'name' : 'sign1', 'texthl' : 'Error', 'linehl' : 'Search',
\ 'linehl' : 'Search', 'culhl' : 'Visual', 'text' : '=>'}], \ 'culhl' : 'Visual', 'numhl': 'Number', 'text' : '=>'}],
\ sign_getdefined()) \ sign_getdefined())
" Define a new sign without attributes and then update it " Define a new sign without attributes and then update it
call sign_define("sign2") call sign_define("sign2")
let attr = {'text' : '!!', 'linehl' : 'DiffAdd', 'texthl' : 'DiffChange', let attr = {'text' : '!!', 'linehl' : 'DiffAdd', 'texthl' : 'DiffChange',
\ 'culhl': 'DiffDelete', 'icon' : 'sign2.ico'} \ 'culhl': 'DiffDelete', 'numhl': 'Number', 'icon' : 'sign2.ico'}
call Sign_define_ignore_error("sign2", attr) call Sign_define_ignore_error("sign2", attr)
call assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange', call assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange',
\ 'linehl' : 'DiffAdd', 'culhl' : 'DiffDelete', 'text' : '!!', \ 'linehl' : 'DiffAdd', 'culhl' : 'DiffDelete', 'text' : '!!',
\ 'icon' : 'sign2.ico'}], "sign2"->sign_getdefined()) \ 'numhl': 'Number', 'icon' : 'sign2.ico'}],
\ "sign2"->sign_getdefined())
" Test for a sign name with digits " Test for a sign name with digits
call assert_equal(0, sign_define(0002, {'linehl' : 'StatusLine'})) call assert_equal(0, sign_define(0002, {'linehl' : 'StatusLine'}))

View File

@ -749,6 +749,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
3874,
/**/ /**/
3873, 3873,
/**/ /**/