From 6a886a2511bbfd24a4d6ecc3f3a75f08a6df9de9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 7 Jul 2024 07:21:14 +0800 Subject: [PATCH] vim-patch:9.1.0538: not possible to assign priority when defining a sign (#29592) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 https://github.com/vim/vim/commit/b975ddfdf96644b8df808415dee36f99abd48753 Co-authored-by: LemonBoy --- runtime/doc/builtin.txt | 4 ++- runtime/doc/sign.txt | 24 ++++++++------ runtime/lua/vim/_meta/vimfn.lua | 4 ++- src/nvim/eval.lua | 4 ++- src/nvim/sign.c | 33 +++++++++++++++---- src/nvim/sign_defs.h | 1 + test/functional/ui/popupmenu_spec.lua | 6 ++-- test/old/testdir/test_signs.vim | 46 ++++++++++++++++++++++++--- 8 files changed, 96 insertions(+), 26 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 180d308ef5..3def778e58 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -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 diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index a64ba0ea1c..9d74f1f376 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -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 diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 9d4cc825ec..e51041839b 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -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 diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 82d695d82b..b57482dc9a 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -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 diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 605098fb66..fbd25493ef 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -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, ¬anum); diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h index ad2a2b737d..f6712513b7 100644 --- a/src/nvim/sign_defs.h +++ b/src/nvim/sign_defs.h @@ -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 { diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index db2ee7ff29..e005cfd2e6 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -2920,11 +2920,12 @@ describe('builtin popupmenu', function() feed('sign define ') 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('') 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=^ | diff --git a/test/old/testdir/test_signs.vim b/test/old/testdir/test_signs.vim index 69fefccb3f..baeaeb0f3d 100644 --- a/test/old/testdir/test_signs.vim +++ b/test/old/testdir/test_signs.vim @@ -246,7 +246,7 @@ func Test_sign_completion() call assert_equal('"sign define jump list place undefine unplace', @:) call feedkeys(":sign define Sign \\\"\", '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\\\"\", '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.