vim-patch:9.1.0538: not possible to assign priority when defining a sign (#29592)

Problem:  not possible to assign priority when defining a sign
          (Mathias Fußenegger)
Solution: Add the priority argument for the :sign-define ex command and
          the sign_define() function (LemonBoy)

Use the specified value instead of the default one (SIGN_DEF_PRIO) when
no priority is explicitly specified in sign_place or :sign place.

fixes: vim/vim#8334
closes: vim/vim#15124

b975ddfdf9

Co-authored-by: LemonBoy <thatlemon@gmail.com>
This commit is contained in:
zeertzjq 2024-07-07 07:21:14 +08:00 committed by GitHub
parent 472b5b9b20
commit 6a886a2511
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 96 additions and 26 deletions

View File

@ -7110,6 +7110,7 @@ sign_getdefined([{name}]) *sign_getdefined()*
linehl highlight group used for the whole line the
sign is placed in; not present if not set.
name name of the sign
priority default priority value 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
@ -7282,7 +7283,8 @@ sign_placelist({list}) *sign_placelist()*
priority Priority of the sign. When multiple signs are
placed on a line, the sign with the highest
priority is used. If not specified, the
default value of 10 is used. See
default value of 10 is used, unless specified
otherwise by the sign definition. See
|sign-priority| for more information.
If {id} refers to an existing sign, then the existing sign is

View File

@ -68,11 +68,12 @@ other plugins using signs.
*sign-priority*
Each placed sign is assigned a priority value independently of the sign group.
The default priority for a sign is 10. When multiple signs that each have an
icon or text are placed on the same line, signs are ordered with decreasing
priority from left to right, up until the maximum width set in 'signcolumn'.
Lower priority signs that do not fit are hidden. Highest priority signs with
highlight attributes are always shown.
The default priority for a sign is 10, this value can be changed for different
signs by specifying a different value at definition time. When multiple signs
that each have an icon or text are placed on the same line, signs are ordered
with decreasing priority from left to right, up until the maximum width set in
'signcolumn'. Low priority signs that do not fit are hidden. Highest priority
signs with highlight attributes are always shown.
When the line on which the sign is placed is deleted, the sign is removed along
with it.
@ -113,6 +114,9 @@ See |sign_define()| for the equivalent Vim script function.
toolkit supports ~
Win32 .bmp, .ico, .cur
priority={prio}
Default priority for the sign, see |sign-priority|.
linehl={group}
Highlighting group used for the whole line the sign is placed
in. Most useful is defining a background color.
@ -183,11 +187,11 @@ See |sign_place()| for the equivalent Vim script function.
By default, the sign is placed in the global sign group.
By default, the sign is assigned a default priority of 10. To
assign a different priority value, use "priority={prio}" to
specify a value. The priority is used to determine the sign
that is displayed when multiple signs are placed on the same
line.
By default, the sign is assigned a default priority of 10,
unless specified otherwise by the sign definition. To assign a
different priority value, use "priority={prio}" to specify a
value. The priority is used to determine the sign that is
displayed when multiple signs are placed on the same line.
Examples: >
:sign place 5 line=3 name=sign1 file=a.py

View File

@ -8477,6 +8477,7 @@ function vim.fn.sign_define(list) end
--- linehl highlight group used for the whole line the
--- sign is placed in; not present if not set.
--- name name of the sign
--- priority default priority value 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
@ -8668,7 +8669,8 @@ function vim.fn.sign_place(id, group, name, buf, dict) end
--- priority Priority of the sign. When multiple signs are
--- placed on a line, the sign with the highest
--- priority is used. If not specified, the
--- default value of 10 is used. See
--- default value of 10 is used, unless specified
--- otherwise by the sign definition. See
--- |sign-priority| for more information.
---
--- If {id} refers to an existing sign, then the existing sign is

View File

@ -10112,6 +10112,7 @@ M.funcs = {
linehl highlight group used for the whole line the
sign is placed in; not present if not set.
name name of the sign
priority default priority value 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
@ -10322,7 +10323,8 @@ M.funcs = {
priority Priority of the sign. When multiple signs are
placed on a line, the sign with the highest
priority is used. If not specified, the
default value of 10 is used. See
default value of 10 is used, unless specified
otherwise by the sign definition. See
|sign-priority| for more information.
If {id} refers to an existing sign, then the existing sign is

View File

@ -401,7 +401,7 @@ int init_sign_text(sign_T *sp, schar_T *sign_text, char *text)
/// Define a new sign or update an existing sign
static int sign_define_by_name(char *name, char *icon, char *text, char *linehl, char *texthl,
char *culhl, char *numhl)
char *culhl, char *numhl, int prio)
{
cstr_t *key;
sign_T **sp = (sign_T **)pmap_put_ref(cstr_t)(&sign_map, name, &key, NULL);
@ -431,6 +431,8 @@ static int sign_define_by_name(char *name, char *icon, char *text, char *linehl,
return FAIL;
}
(*sp)->sn_priority = prio;
char *arg[] = { linehl, texthl, culhl, numhl };
int *hl[] = { &(*sp)->sn_line_hl, &(*sp)->sn_text_hl, &(*sp)->sn_cul_hl, &(*sp)->sn_num_hl };
for (int i = 0; i < 4; i++) {
@ -472,6 +474,11 @@ static void sign_list_defined(sign_T *sp)
describe_sign_text(buf, sp->sn_text);
msg_outtrans(buf, 0);
}
if (sp->sn_priority > 0) {
char lbuf[MSG_BUF_LEN];
vim_snprintf(lbuf, MSG_BUF_LEN, " priority=%d", sp->sn_priority);
msg_puts(lbuf);
}
static char *arg[] = { " linehl=", " texthl=", " culhl=", " numhl=" };
int hl[] = { sp->sn_line_hl, sp->sn_text_hl, sp->sn_cul_hl, sp->sn_num_hl };
for (int i = 0; i < 4; i++) {
@ -508,6 +515,11 @@ static int sign_place(uint32_t *id, char *group, char *name, buf_T *buf, linenr_
return FAIL;
}
// Use the default priority value for this sign.
if (prio == -1) {
prio = (sp->sn_priority != -1) ? sp->sn_priority : SIGN_DEF_PRIO;
}
if (lnum > 0) {
// ":sign place {id} line={lnum} name={name} file={fname}": place a sign
buf_set_sign(buf, id, group, prio, lnum, sp);
@ -602,6 +614,7 @@ static void sign_define_cmd(char *name, char *cmdline)
char *texthl = NULL;
char *culhl = NULL;
char *numhl = NULL;
int prio = -1;
// set values for a defined sign.
while (true) {
@ -622,6 +635,8 @@ static void sign_define_cmd(char *name, char *cmdline)
culhl = arg + 6;
} else if (strncmp(arg, "numhl=", 6) == 0) {
numhl = arg + 6;
} else if (strncmp(arg, "priority=", 9) == 0) {
prio = atoi(arg + 9);
} else {
semsg(_(e_invarg2), arg);
return;
@ -632,7 +647,7 @@ static void sign_define_cmd(char *name, char *cmdline)
*cmdline++ = NUL;
}
sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl);
sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl, prio);
}
/// ":sign place" command
@ -847,7 +862,7 @@ void ex_sign(exarg_T *eap)
linenr_T lnum = -1;
char *name = NULL;
char *group = NULL;
int prio = SIGN_DEF_PRIO;
int prio = -1;
buf_T *buf = NULL;
// Parse command line arguments
@ -880,6 +895,9 @@ static dict_T *sign_get_info_dict(sign_T *sp)
describe_sign_text(buf, sp->sn_text);
tv_dict_add_str(d, S_LEN("text"), buf);
}
if (sp->sn_priority > 0) {
tv_dict_add_nr(d, S_LEN("priority"), sp->sn_priority);
}
static char *arg[] = { "linehl", "texthl", "culhl", "numhl" };
int hl[] = { sp->sn_line_hl, sp->sn_text_hl, sp->sn_cul_hl, sp->sn_num_hl };
for (int i = 0; i < 4; i++) {
@ -1044,7 +1062,8 @@ char *get_sign_name(expand_T *xp, int idx)
case EXP_SUBCMD:
return cmds[idx];
case EXP_DEFINE: {
char *define_arg[] = { "culhl=", "icon=", "linehl=", "numhl=", "text=", "texthl=", NULL };
char *define_arg[] = { "culhl=", "icon=", "linehl=", "numhl=", "text=", "texthl=",
"priority=", NULL };
return define_arg[idx];
}
case EXP_PLACE: {
@ -1200,6 +1219,7 @@ static int sign_define_from_dict(char *name, dict_T *dict)
char *texthl = NULL;
char *culhl = NULL;
char *numhl = NULL;
int prio = -1;
if (dict != NULL) {
icon = tv_dict_get_string(dict, "icon", false);
@ -1208,9 +1228,10 @@ static int sign_define_from_dict(char *name, dict_T *dict)
texthl = tv_dict_get_string(dict, "texthl", false);
culhl = tv_dict_get_string(dict, "culhl", false);
numhl = tv_dict_get_string(dict, "numhl", false);
prio = (int)tv_dict_get_number_def(dict, "priority", -1);
}
return sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl) - 1;
return sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl, prio) - 1;
}
/// Define multiple signs using attributes from list 'l' and store the return
@ -1442,7 +1463,7 @@ static int sign_place_from_dict(typval_T *id_tv, typval_T *group_tv, typval_T *n
}
}
int prio = SIGN_DEF_PRIO;
int prio = -1;
di = tv_dict_find(dict, "priority", -1);
if (di != NULL) {
prio = (int)tv_get_number_chk(&di->di_tv, &notanum);

View File

@ -18,6 +18,7 @@ typedef struct {
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
int sn_priority; // default priority of this sign, -1 means SIGN_DEF_PRIO
} sign_T;
typedef struct {

View File

@ -2920,11 +2920,12 @@ describe('builtin popupmenu', function()
feed('<C-U>sign define <Tab>')
screen:expect([[
|
{1:~ }|*2
{1:~ }|
{1:~ }{s: culhl= }{1: }|
{1:~ }{n: icon= }{1: }|
{1:~ }{n: linehl= }{1: }|
{1:~ }{n: numhl= }{1: }|
{1:~ }{n: priority= }{1: }|
{1:~ }{n: text= }{1: }|
{1:~ }{n: texthl= }{1: }|
:sign define culhl=^ |
@ -2933,11 +2934,12 @@ describe('builtin popupmenu', function()
feed('<Space><Tab>')
screen:expect([[
|
{1:~ }|*2
{1:~ }|
{1:~ }{s: culhl= }{1: }|
{1:~ }{n: icon= }{1: }|
{1:~ }{n: linehl= }{1: }|
{1:~ }{n: numhl= }{1: }|
{1:~ }{n: priority= }{1: }|
{1:~ }{n: text= }{1: }|
{1:~ }{n: texthl= }{1: }|
:sign define culhl= culhl=^ |

View File

@ -246,7 +246,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 culhl= icon= linehl= numhl= text= texthl=', @:)
call assert_equal('"sign define Sign culhl= icon= linehl= numhl= priority= text= texthl=', @:)
for hl in ['culhl', 'linehl', 'numhl', 'texthl']
call feedkeys(":sign define Sign "..hl.."=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
@ -1240,9 +1240,28 @@ func Test_sign_priority()
call sign_define("sign1", attr)
call sign_define("sign2", attr)
call sign_define("sign3", attr)
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Search', 'priority': 60}
call sign_define("sign4", attr)
" Test for :sign list
let a = execute('sign list')
call assert_equal("\nsign sign1 text==> linehl=Search texthl=Search\n" .
\ "sign sign2 text==> linehl=Search texthl=Search\n" .
\ "sign sign3 text==> linehl=Search texthl=Search\n" .
\ "sign sign4 text==> priority=60 linehl=Search texthl=Search", a)
" Test for sign_getdefined()
let s = sign_getdefined()
call assert_equal([
\ {'name': 'sign1', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'},
\ {'name': 'sign2', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'},
\ {'name': 'sign3', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'},
\ {'name': 'sign4', 'priority': 60, 'texthl': 'Search', 'linehl': 'Search',
\ 'text': '=>'}],
\ s)
" Place three signs with different priority in the same line
call writefile(repeat(["Sun is shining"], 30), "Xsign")
call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
edit Xsign
call sign_place(1, 'g1', 'sign1', 'Xsign',
@ -1577,16 +1596,34 @@ func Test_sign_priority()
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=10 id=5 group=g1 name=sign1 priority=20\n", a)
call sign_unplace('*')
" Test for sign with default priority.
call sign_place(1, 'g1', 'sign4', 'Xsign', {'lnum' : 3})
sign place 2 line=5 name=sign4 group=g1 file=Xsign
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign4', 'lnum' : 3, 'group' : 'g1',
\ 'priority' : 60},
\ {'id' : 2, 'name' : 'sign4', 'lnum' : 5, 'group' : 'g1',
\ 'priority' : 60}],
\ s[0].signs)
let a = execute('sign place group=g1')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=3 id=1 group=g1 name=sign4 priority=60\n" .
\ " line=5 id=2 group=g1 name=sign4 priority=60\n", a)
call sign_unplace('*')
call sign_undefine()
enew | only
call delete("Xsign")
endfunc
" Tests for memory allocation failures in sign functions
func Test_sign_memfailures()
CheckFunction test_alloc_fail
call writefile(repeat(["Sun is shining"], 30), "Xsign")
call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
edit Xsign
call test_alloc_fail(GetAllocId('sign_getdefined'), 0, 0)
@ -1623,7 +1660,6 @@ func Test_sign_memfailures()
call sign_unplace('*')
call sign_undefine()
enew | only
call delete("Xsign")
endfunc
" Test for auto-adjusting the line number of a placed sign.