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)
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 3e71ba1..b4e7761 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -5601,8 +5601,8 @@
number.
When a long, wrapped line doesn't start with the first character, '-'
characters are put before the number.
- See |hl-LineNr| and |hl-CursorLineNr| for the highlighting used for
- the number.
+ For highlighting see |hl-LineNr|, and |hl-CursorLineNr|, and the
+ |:sign-define| "numhl" argument.
*number_relativenumber*
The 'relativenumber' option changes the displayed number to be
relative to the cursor. Together with 'number' there are these
diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt
index 7976cec..125e592 100644
--- a/runtime/doc/sign.txt
+++ b/runtime/doc/sign.txt
@@ -140,6 +140,11 @@
Highlighting group used for the whole line the sign is placed
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*
Define the text that is displayed when there is no icon or the
GUI is not being used. Only printable characters are allowed
@@ -396,6 +401,8 @@
icon full path to the bitmap file for the sign.
linehl highlight group used for the whole line the
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
or the GUI is not being used.
texthl highlight group used for the text item
@@ -443,6 +450,8 @@
linehl highlight group used for the whole line the
sign is placed in; not present if not set
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
or the GUI is not being used.
texthl highlight group used for the text item; not
diff --git a/src/drawline.c b/src/drawline.c
index 3106196..7125b80 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -377,6 +377,7 @@
#ifdef FEAT_SIGNS
int sign_present = FALSE;
sign_attrs_T sattr;
+ int num_attr = 0; // attribute for the number column
#endif
#ifdef FEAT_ARABIC
int prev_c = 0; // previous Arabic character
@@ -699,6 +700,8 @@
#ifdef FEAT_SIGNS
sign_present = buf_get_signattrs(wp, lnum, &sattr);
+ if (sign_present)
+ num_attr = sattr.sat_numhl;
#endif
#ifdef LINE_ATTR
@@ -1206,6 +1209,10 @@
char_attr = hl_combine_attr(wcr_attr,
HL_ATTR(HLF_LNB));
}
+#ifdef FEAT_SIGNS
+ if (num_attr)
+ char_attr = num_attr;
+#endif
}
}
diff --git a/src/popupwin.c b/src/popupwin.c
index 266e113..7b74261 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -632,7 +632,7 @@
if (syn_name2id((char_u *)linehl) == 0)
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,
diff --git a/src/proto/sign.pro b/src/proto/sign.pro
index 4e8abb3..a042bad 100644
--- a/src/proto/sign.pro
+++ b/src/proto/sign.pro
@@ -8,7 +8,7 @@
int buf_signcount(buf_T *buf, linenr_T lnum);
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);
-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_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);
diff --git a/src/sign.c b/src/sign.c
index e358ee9..50210d0 100644
--- a/src/sign.c
+++ b/src/sign.c
@@ -33,6 +33,7 @@
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
};
static sign_T *first_sign = NULL;
@@ -520,6 +521,8 @@
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);
sattr->sat_priority = sign->se_priority;
// If there is another sign next with the same priority, may
@@ -545,6 +548,8 @@
sattr->sat_linehl = syn_id2attr(next_sp->sn_line_hl);
if (sp->sn_cul_hl <= 0 && next_sp->sn_cul_hl > 0)
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;
@@ -1041,7 +1046,8 @@
char_u *linehl,
char_u *text,
char_u *texthl,
- char_u *culhl)
+ char_u *culhl,
+ char_u *numhl)
{
sign_T *sp_prev;
sign_T *sp;
@@ -1101,6 +1107,14 @@
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;
}
@@ -1323,6 +1337,7 @@
char_u *linehl = NULL;
char_u *texthl = NULL;
char_u *culhl = NULL;
+ char_u *numhl = NULL;
int failed = FALSE;
// set values for a defined sign.
@@ -1357,6 +1372,11 @@
arg += 6;
culhl = vim_strnsave(arg, p - arg);
}
+ else if (STRNCMP(arg, "numhl=", 6) == 0)
+ {
+ arg += 6;
+ numhl = vim_strnsave(arg, p - arg);
+ }
else
{
semsg(_(e_invarg2), arg);
@@ -1366,13 +1386,14 @@
}
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(text);
vim_free(linehl);
vim_free(texthl);
vim_free(culhl);
+ vim_free(numhl);
}
/*
@@ -1750,6 +1771,13 @@
p = (char_u *)"NONE";
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 @@
else
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 @@
{
char *define_arg[] =
{
- "icon=", "linehl=", "text=", "texthl=", NULL
+ "culhl=", "icon=", "linehl=", "numhl=", "text=", "texthl=", NULL
};
return (char_u *)define_arg[idx];
}
@@ -2176,7 +2213,9 @@
{
case SIGNCMD_DEFINE:
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;
else if (STRNCMP(last, "icon", 4) == 0)
xp->xp_context = EXPAND_FILES;
@@ -2221,6 +2260,7 @@
char_u *text = NULL;
char_u *texthl = NULL;
char_u *culhl = NULL;
+ char_u *numhl = NULL;
int retval = -1;
if (name_arg == NULL)
@@ -2240,9 +2280,10 @@
text = dict_get_string(dict, (char_u *)"text", TRUE);
texthl = dict_get_string(dict, (char_u *)"texthl", 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;
cleanup:
@@ -2252,6 +2293,7 @@
vim_free(text);
vim_free(texthl);
vim_free(culhl);
+ vim_free(numhl);
return retval;
}
diff --git a/src/structs.h b/src/structs.h
index 7023ac3..4160453 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -854,6 +854,7 @@
int sat_texthl;
int sat_linehl;
int sat_culhl;
+ int sat_numhl;
int sat_priority;
} sign_attrs_T;
diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim
index a1ffdf5..77bb049 100644
--- a/src/testdir/test_signs.vim
+++ b/src/testdir/test_signs.vim
@@ -15,13 +15,13 @@
" 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 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.
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 culhl=Search$', a)
+ \ 'linehl=Error texthl=Title culhl=Search numhl=Number$', a)
let a=execute('sign list Sign1')
call assert_equal("\nsign Sign1 text=x ", a)
@@ -127,26 +127,34 @@
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
+ sign define SignY texthl=TextHl culhl=CulHl linehl=LineHl numhl=NumHl
let sl = sign_getdefined('SignY')[0]
call assert_equal('TextHl', sl.texthl)
call assert_equal('CulHl', sl.culhl)
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]
call assert_false(has_key(sl, 'texthl'))
call assert_equal('CulHl', sl.culhl)
call assert_equal('LineHl', sl.linehl)
+ call assert_equal('NumHl', sl.numhl)
sign define SignY linehl=
let sl = sign_getdefined('SignY')[0]
call assert_false(has_key(sl, 'linehl'))
call assert_equal('CulHl', sl.culhl)
+ call assert_equal('NumHl', sl.numhl)
sign define SignY culhl=
let sl = sign_getdefined('SignY')[0]
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
@@ -218,15 +226,13 @@
call assert_equal('"sign define jump list place undefine unplace', @:)
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')
- call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' .
- \ 'SpellLocal SpellRare', @:)
-
- call feedkeys(":sign define Sign texthl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_equal('"sign define Sign texthl=SpellBad SpellCap ' .
- \ 'SpellLocal SpellRare', @:)
+ for hl in ['culhl', 'linehl', 'numhl', 'texthl']
+ call feedkeys(":sign define Sign "..hl.."=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign define Sign '..hl..'=SpellBad SpellCap ' .
+ \ 'SpellLocal SpellRare', @:)
+ endfor
call writefile(repeat(["Sun is shining"], 30), "XsignOne")
call writefile(repeat(["Sky is blue"], 30), "XsignTwo")
@@ -417,20 +423,21 @@
" Tests for sign_define()
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error',
- \ 'culhl': 'Visual'}
+ \ 'culhl': 'Visual', 'numhl': 'Number'}
call assert_equal(0, "sign1"->sign_define(attr))
- call assert_equal([{'name' : 'sign1', 'texthl' : 'Error',
- \ 'linehl' : 'Search', 'culhl' : 'Visual', 'text' : '=>'}],
+ call assert_equal([{'name' : 'sign1', 'texthl' : 'Error', 'linehl' : 'Search',
+ \ 'culhl' : 'Visual', 'numhl': 'Number', 'text' : '=>'}],
\ sign_getdefined())
" Define a new sign without attributes and then update it
call sign_define("sign2")
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 assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange',
\ '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
call assert_equal(0, sign_define(0002, {'linehl' : 'StatusLine'}))
diff --git a/src/version.c b/src/version.c
index 53d3b57..072e884 100644
--- a/src/version.c
+++ b/src/version.c
@@ -750,6 +750,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3874,
+/**/
3873,
/**/
3872,