signs: Add "numhl" argument #9113

close #9113
ref #9040
This commit is contained in:
Reto Schnyder 2018-10-13 19:33:08 +02:00 committed by Justin M. Keyes
parent 8bbb28b973
commit bddcbbb571
10 changed files with 127 additions and 53 deletions

View File

@ -4256,12 +4256,11 @@ A jump table for the options with a short description can be found at |Q_op|.
Print the line number in front of each line. When the 'n' option is
excluded from 'cpoptions' a wrapped line will not use the column of
line numbers.
The 'numberwidth' option can be used to set the room used for the line
number.
Use the 'numberwidth' option to adjust the room for the line 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|, |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

View File

@ -85,6 +85,10 @@ DEFINING A SIGN. *:sign-define* *E255* *E160* *E612*
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 'number' column at the associated
line. Overrides |hl-LineNr|, |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

View File

@ -136,6 +136,7 @@ Commands:
|:cquit| can use [count] to set the exit code
|:drop| is always available
|:Man| is available by default, with many improvements such as completion
|:sign-define| accepts a `numhl` argument, to highlight the line number
|:tchdir| tab-local |current-directory|
Events:

View File

@ -5084,13 +5084,16 @@ linenr_T buf_change_sign_type(
return (linenr_T)0;
}
int buf_getsigntype(
buf_T *buf,
linenr_T lnum,
int type /* SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL */
)
/// Gets a sign from a given line.
/// In case of multiple signs, returns the most recently placed one.
///
/// @param buf Buffer in which to search
/// @param lnum Line in which to search
/// @param type Type of sign to look for
/// @return Identifier of the first matching sign, or 0
int buf_getsigntype(buf_T *buf, linenr_T lnum, SignType type)
{
signlist_T *sign; /* a sign in a b_signlist */
signlist_T *sign; // a sign in a b_signlist
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
if (sign->lnum == lnum
@ -5098,7 +5101,9 @@ int buf_getsigntype(
|| (type == SIGN_TEXT
&& sign_get_text(sign->typenr) != NULL)
|| (type == SIGN_LINEHL
&& sign_get_attr(sign->typenr, TRUE) != 0))) {
&& sign_get_attr(sign->typenr, SIGN_LINEHL) != 0)
|| (type == SIGN_NUMHL
&& sign_get_attr(sign->typenr, SIGN_NUMHL) != 0))) {
return sign->typenr;
}
}

View File

@ -5471,13 +5471,14 @@ void ex_helptags(exarg_T *eap)
struct sign
{
sign_T *sn_next; /* next sign in list */
int sn_typenr; /* type number of sign */
char_u *sn_name; /* name of sign */
char_u *sn_icon; /* name of pixmap */
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 */
sign_T *sn_next; // next sign in list
int sn_typenr; // type number of sign
char_u *sn_name; // name of sign
char_u *sn_icon; // name of pixmap
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_num_hl; // highlight ID for line number
};
static sign_T *first_sign = NULL;
@ -5675,6 +5676,9 @@ void ex_sign(exarg_T *eap)
} else if (STRNCMP(arg, "texthl=", 7) == 0) {
arg += 7;
sp->sn_text_hl = syn_check_group(arg, (int)(p - arg));
} else if (STRNCMP(arg, "numhl=", 6) == 0) {
arg += 6;
sp->sn_num_hl = syn_check_group(arg, (int)(p - arg));
} else {
EMSG2(_(e_invarg2), arg);
return;
@ -5901,6 +5905,16 @@ static void sign_list_defined(sign_T *sp)
msg_puts(p);
}
}
if (sp->sn_num_hl > 0) {
msg_puts(" numhl=");
const char *const p = get_highlight_name_ext(NULL,
sp->sn_num_hl - 1, false);
if (p == NULL) {
msg_puts("NONE");
} else {
msg_puts(p);
}
}
}
/*
@ -5918,25 +5932,33 @@ static void sign_undefine(sign_T *sp, sign_T *sp_prev)
xfree(sp);
}
/*
* Get highlighting attribute for sign "typenr".
* If "line" is TRUE: line highl, if FALSE: text highl.
*/
int sign_get_attr(int typenr, int line)
/// Gets highlighting attribute for sign "typenr" corresponding to "type".
int sign_get_attr(int typenr, SignType type)
{
sign_T *sp;
int sign_hl = 0;
for (sp = first_sign; sp != NULL; sp = sp->sn_next)
for (sp = first_sign; sp != NULL; sp = sp->sn_next) {
if (sp->sn_typenr == typenr) {
if (line) {
if (sp->sn_line_hl > 0)
return syn_id2attr(sp->sn_line_hl);
} else {
if (sp->sn_text_hl > 0)
return syn_id2attr(sp->sn_text_hl);
switch (type) {
case SIGN_TEXT:
sign_hl = sp->sn_text_hl;
break;
case SIGN_LINEHL:
sign_hl = sp->sn_line_hl;
break;
case SIGN_NUMHL:
sign_hl = sp->sn_num_hl;
break;
default:
abort();
}
if (sign_hl > 0) {
return syn_id2attr(sign_hl);
}
break;
}
}
return 0;
}
@ -5997,7 +6019,8 @@ char_u * get_sign_name(expand_T *xp, int idx)
case EXP_SUBCMD:
return (char_u *)cmds[idx];
case EXP_DEFINE: {
char *define_arg[] = { "icon=", "linehl=", "text=", "texthl=", NULL };
char *define_arg[] = { "icon=", "linehl=", "text=", "texthl=", "numhl=",
NULL };
return (char_u *)define_arg[idx];
}
case EXP_PLACE: {
@ -6120,7 +6143,8 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
{
case SIGNCMD_DEFINE:
if (STRNCMP(last, "texthl", p - last) == 0
|| STRNCMP(last, "linehl", p - last) == 0) {
|| STRNCMP(last, "linehl", p - last) == 0
|| STRNCMP(last, "numhl", p - last) == 0) {
xp->xp_context = EXPAND_HIGHLIGHT;
} else if (STRNCMP(last, "icon", p - last) == 0) {
xp->xp_context = EXPAND_FILES;

View File

@ -2486,7 +2486,7 @@ win_line (
// If this line has a sign with line highlighting set line_attr.
v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL);
if (v != 0) {
line_attr = sign_get_attr((int)v, true);
line_attr = sign_get_attr((int)v, SIGN_LINEHL);
}
// Highlight the current line in the quickfix window.
@ -2794,7 +2794,7 @@ win_line (
p_extra = extra;
p_extra[n_extra] = NUL;
}
char_attr = sign_get_attr(text_sign, FALSE);
char_attr = sign_get_attr(text_sign, SIGN_TEXT);
}
}
}
@ -2841,12 +2841,17 @@ win_line (
c_extra = ' ';
n_extra = number_width(wp) + 1;
char_attr = win_hl_attr(wp, HLF_N);
int num_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_NUMHL);
if (num_sign != 0) {
// :sign defined with "numhl" highlight.
char_attr = sign_get_attr(num_sign, SIGN_NUMHL);
} else if ((wp->w_p_cul || wp->w_p_rnu)
&& lnum == wp->w_cursor.lnum) {
// When 'cursorline' is set highlight the line number of
// the current line differently.
// TODO(vim): Can we use CursorLine instead of CursorLineNr
// when CursorLineNr isn't set?
if ((wp->w_p_cul || wp->w_p_rnu)
&& lnum == wp->w_cursor.lnum) {
char_attr = win_hl_attr(wp, HLF_CLN);
}
}

View File

@ -9,17 +9,20 @@ typedef struct signlist signlist_T;
struct signlist
{
int id; /* unique identifier for each placed sign */
linenr_T lnum; /* line number which has this sign */
int typenr; /* typenr of sign */
signlist_T *next; /* next signlist entry */
int id; // unique identifier for each placed sign
linenr_T lnum; // line number which has this sign
int typenr; // typenr of sign
signlist_T *next; // next signlist entry
};
/* type argument for buf_getsigntype() */
#define SIGN_ANY 0
#define SIGN_LINEHL 1
#define SIGN_ICON 2
#define SIGN_TEXT 3
// type argument for buf_getsigntype() and sign_get_attr()
typedef enum {
SIGN_ANY,
SIGN_LINEHL,
SIGN_ICON,
SIGN_TEXT,
SIGN_NUMHL,
} SignType;

View File

@ -14,7 +14,7 @@ func Test_sign()
" the icon name when listing signs.
sign define Sign1 text=x
try
sign define Sign2 text=xy texthl=Title linehl=Error icon=../../pixmaps/stock_vim_find_help.png
sign define Sign2 text=xy texthl=Title linehl=Error numhl=Number icon=../../pixmaps/stock_vim_find_help.png
catch /E255:/
" ignore error: E255: Couldn't read in sign data!
" This error can happen when running in gui.
@ -23,7 +23,7 @@ func Test_sign()
" 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)
call assert_match("^\nsign Sign1 text=x \nsign Sign2 icon=../../pixmaps/stock_vim_find_help.png .*text=xy linehl=Error texthl=Title numhl=Number$", a)
let a=execute('sign list Sign1')
call assert_equal("\nsign Sign1 text=x ", a)
@ -140,7 +140,7 @@ func Test_sign_completion()
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 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', @:)

View File

@ -7,7 +7,7 @@ describe('sign', function()
describe('without specifying buffer', function()
it('deletes the sign from all buffers', function()
-- place a sign with id 34 to first buffer
nvim('command', 'sign define Foo text=+ texthl=Delimiter linehl=Comment')
nvim('command', 'sign define Foo text=+ texthl=Delimiter linehl=Comment numhl=Number')
local buf1 = nvim('eval', 'bufnr("%")')
nvim('command', 'sign place 34 line=3 name=Foo buffer='..buf1)
-- create a second buffer and place the sign on it as well

View File

@ -17,6 +17,9 @@ describe('Signs', function()
[3] = {background = Screen.colors.Gray90},
[4] = {bold = true, reverse = true},
[5] = {reverse = true},
[6] = {foreground = Screen.colors.Brown},
[7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
[8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
} )
end)
@ -78,5 +81,35 @@ describe('Signs', function()
|
]])
end)
it('can combine text, linehl and numhl', function()
feed('ia<cr>b<cr>c<cr><esc>')
command('set number')
command('sign define piet text=>> texthl=Search')
command('sign define pietx linehl=ErrorMsg')
command('sign define pietxx numhl=Folded')
command('sign place 1 line=1 name=piet buffer=1')
command('sign place 2 line=2 name=pietx buffer=1')
command('sign place 3 line=3 name=pietxx buffer=1')
command('sign place 4 line=4 name=piet buffer=1')
command('sign place 5 line=4 name=pietx buffer=1')
command('sign place 6 line=4 name=pietxx buffer=1')
screen:expect([[
{1:>>}{6: 1 }a |
{2: }{6: 2 }{8:b }|
{2: }{7: 3 }c |
{1:>>}{7: 4 }{8:^ }|
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
{2: }{0:~ }|
|
]])
end)
end)
end)