diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index dac3a57204cdd..84b2977293a5e 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -1,4 +1,4 @@ -*sign.txt* For Vim version 9.1. Last change: 2024 Jun 08 +*sign.txt* For Vim version 9.1. Last change: 2024 Jul 06 VIM REFERENCE MANUAL by Gordon Prieur @@ -80,8 +80,9 @@ used by popup windows where 'cursorline' is set. *sign-priority* Each placed sign is assigned a priority value. When multiple signs are placed on the same line, the attributes of the sign with the highest priority is used -independently of the sign group. The default priority for a sign is 10. The -priority is assigned at the time of placing a sign. +independently of the sign group. The default priority for a sign is 10, this +value can be changed for different signs by specifying a different value at +definition time. The priority is assigned at the time of placing a sign. When two signs with the same priority are present, and one has an icon or text in the signcolumn while the other has line highlighting, then both are @@ -135,6 +136,8 @@ See |sign_define()| for the equivalent Vim script function. Motif pixmap (.xpm) Win32 .bmp, .ico, .cur pixmap (.xpm) |+xpm_w32| + priority={prio} + Default priority for the sign, see |sign-priority|. linehl={group} Highlighting group used for the whole line the sign is placed @@ -209,11 +212,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 @@ -453,6 +456,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 @@ -646,7 +650,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/version9.txt b/runtime/doc/version9.txt index d70c3b19e3e72..92792b9cd5542 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -41576,6 +41576,7 @@ Changed~ - 'completeopt' is now a |global-local| option. - 'nrformat' accepts the new "blank" suboption, to determine a signed or unsigned number based on whitespace in front of a minus sign. +- allow to specify a priority when defining a new sign |:sign-define| *added-9.2* Added ~ diff --git a/src/popupwin.c b/src/popupwin.c index e35327217e758..9d60aa22aef89 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -699,8 +699,8 @@ popup_highlight_curline(win_T *wp) if (syn_name2id((char_u *)linehl) == 0) linehl = "PmenuSel"; - sign_define_by_name(sign_name, NULL, (char_u *)linehl, - NULL, NULL, NULL, NULL); + sign_define_by_name(sign_name, NULL, (char_u *)linehl, NULL, NULL, NULL, + NULL, SIGN_DEF_PRIO); } sign_place(&sign_id, (char_u *)"PopUpMenu", sign_name, diff --git a/src/proto/sign.pro b/src/proto/sign.pro index a042bad7f1909..1cca0a6963c35 100644 --- a/src/proto/sign.pro +++ b/src/proto/sign.pro @@ -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); 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, char_u *numhl); +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 prio); 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 8aa043bc458fd..1ae714d9a17b6 100644 --- a/src/sign.c +++ b/src/sign.c @@ -34,6 +34,7 @@ struct sign 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 }; static sign_T *first_sign = NULL; @@ -1047,7 +1048,8 @@ sign_define_by_name( char_u *text, char_u *texthl, char_u *culhl, - char_u *numhl) + char_u *numhl, + int prio) { sign_T *sp_prev; sign_T *sp; @@ -1083,6 +1085,8 @@ sign_define_by_name( if (text != NULL && (sign_define_init_text(sp, text) == FAIL)) return FAIL; + sp->sn_priority = prio; + if (linehl != NULL) { if (*linehl == NUL) @@ -1206,6 +1210,10 @@ sign_place( if (*sign_id == 0) *sign_id = sign_group_get_next_signid(buf, sign_group); + // 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 @@ -1338,6 +1346,7 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline) char_u *texthl = NULL; char_u *culhl = NULL; char_u *numhl = NULL; + int prio = -1; int failed = FALSE; // set values for a defined sign. @@ -1377,6 +1386,12 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline) arg += 6; numhl = vim_strnsave(arg, p - arg); } + else if (STRNCMP(arg, "priority=", 9) == 0) + { + arg += 9; + prio = atoi((char *)arg); + arg = skiptowhite(arg); + } else { semsg(_(e_invalid_argument_str), arg); @@ -1386,7 +1401,7 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline) } if (!failed) - sign_define_by_name(sign_name, icon, linehl, text, texthl, culhl, numhl); + sign_define_by_name(sign_name, icon, linehl, text, texthl, culhl, numhl, prio); vim_free(icon); vim_free(text); @@ -1721,7 +1736,7 @@ ex_sign(exarg_T *eap) linenr_T lnum = -1; char_u *sign_name = NULL; char_u *group = NULL; - int prio = SIGN_DEF_PRIO; + int prio = -1; // Parse command line arguments if (parse_sign_cmd_args(idx, arg, &sign_name, &id, &group, &prio, @@ -1750,6 +1765,8 @@ sign_getinfo(sign_T *sp, dict_T *retdict) dict_add_string(retdict, "icon", sp->sn_icon); if (sp->sn_text != NULL) dict_add_string(retdict, "text", sp->sn_text); + if (sp->sn_priority > 0) + dict_add_number(retdict, "priority", sp->sn_priority); if (sp->sn_line_hl > 0) { p = get_highlight_name_ext(NULL, sp->sn_line_hl - 1, FALSE); @@ -1913,6 +1930,7 @@ sign_gui_started(void) sign_list_defined(sign_T *sp) { char_u *p; + char lbuf[MSG_BUF_LEN]; smsg("sign %s", sp->sn_name); if (sp->sn_icon != NULL) @@ -1931,6 +1949,11 @@ sign_list_defined(sign_T *sp) msg_puts(" text="); msg_outtrans(sp->sn_text); } + if (sp->sn_priority > 0) + { + vim_snprintf(lbuf, MSG_BUF_LEN, " priority=%d", sp->sn_priority); + msg_puts(lbuf); + } if (sp->sn_line_hl > 0) { msg_puts(" linehl="); @@ -2088,7 +2111,8 @@ get_sign_name(expand_T *xp UNUSED, int idx) { char *define_arg[] = { - "culhl=", "icon=", "linehl=", "numhl=", "text=", "texthl=", NULL + "culhl=", "icon=", "linehl=", "numhl=", "text=", "texthl=", "priority=", + NULL }; return (char_u *)define_arg[idx]; } @@ -2261,6 +2285,7 @@ sign_define_from_dict(char_u *name_arg, dict_T *dict) char_u *texthl = NULL; char_u *culhl = NULL; char_u *numhl = NULL; + int prio = -1; int retval = -1; if (name_arg == NULL) @@ -2281,9 +2306,10 @@ sign_define_from_dict(char_u *name_arg, dict_T *dict) texthl = dict_get_string(dict, "texthl", TRUE); culhl = dict_get_string(dict, "culhl", TRUE); numhl = dict_get_string(dict, "numhl", TRUE); + prio = dict_get_number_def(dict, "priority", -1); } - if (sign_define_by_name(name, icon, linehl, text, texthl, culhl, numhl) == OK) + if (sign_define_by_name(name, icon, linehl, text, texthl, culhl, numhl, prio) == OK) retval = 0; cleanup: @@ -2511,7 +2537,7 @@ sign_place_from_dict( buf_T *buf = NULL; dictitem_T *di; linenr_T lnum = 0; - int prio = SIGN_DEF_PRIO; + int prio = -1; int notanum = FALSE; int ret_sign_id = -1; diff --git a/src/testdir/dumps/Test_wildmenu_pum_11.dump b/src/testdir/dumps/Test_wildmenu_pum_11.dump index 4697c8a562a65..a0ffc74241c4e 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_11.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_11.dump @@ -1,10 +1,10 @@ | +0&#ffffff0@74 |~+0#4040ff13&| @73 -|~| @73 |~| @10| +0#0000001#e0e0e08|c|u|l|h|l|=| @8| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|i|c|o|n|=| @9| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|l|i|n|e|h|l|=| @7| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|n|u|m|h|l|=| @8| +0#4040ff13#ffffff0@46 +|~| @10| +0#0000001#ffd7ff255|p|r|i|o|r|i|t|y|=| @5| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|t|e|x|t|=| @9| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|t|e|x|t|h|l|=| @7| +0#4040ff13#ffffff0@46 |:+0#0000000&|s|i|g|n| |d|e|f|i|n|e| |c|u|l|h|l|=> @55 diff --git a/src/testdir/dumps/Test_wildmenu_pum_12.dump b/src/testdir/dumps/Test_wildmenu_pum_12.dump index d93631de779fa..12842c4a5bb42 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_12.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_12.dump @@ -1,10 +1,10 @@ | +0&#ffffff0@74 |~+0#4040ff13&| @73 -|~| @73 |~| @17| +0#0000001#e0e0e08|c|u|l|h|l|=| @8| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|i|c|o|n|=| @9| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|l|i|n|e|h|l|=| @7| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|n|u|m|h|l|=| @8| +0#4040ff13#ffffff0@39 +|~| @17| +0#0000001#ffd7ff255|p|r|i|o|r|i|t|y|=| @5| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|t|e|x|t|=| @9| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|t|e|x|t|h|l|=| @7| +0#4040ff13#ffffff0@39 |:+0#0000000&|s|i|g|n| |d|e|f|i|n|e| |c|u|l|h|l|=| |c|u|l|h|l|=> @48 diff --git a/src/testdir/dumps/Test_wildmenu_pum_13.dump b/src/testdir/dumps/Test_wildmenu_pum_13.dump index b2b1424f56a31..94a8ccc6d78ad 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_13.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_13.dump @@ -1,10 +1,10 @@ | +0&#ffffff0@74 |~+0#4040ff13&| @73 -|~| @73 |~| @24| +0#0000001#e0e0e08|c|u|l|h|l|=| @8| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|i|c|o|n|=| @9| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|l|i|n|e|h|l|=| @7| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|n|u|m|h|l|=| @8| +0#4040ff13#ffffff0@32 +|~| @24| +0#0000001#ffd7ff255|p|r|i|o|r|i|t|y|=| @5| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|t|e|x|t|=| @9| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|t|e|x|t|h|l|=| @7| +0#4040ff13#ffffff0@32 |:+0#0000000&|s|i|g|n| |d|e|f|i|n|e| |c|u|l|h|l|=| |c|u|l|h|l|=| |c|u|l|h|l|=> @41 diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim index 0d76d7a445b8a..7f53d62daf339 100644 --- a/src/testdir/test_signs.vim +++ b/src/testdir/test_signs.vim @@ -245,7 +245,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') @@ -1231,6 +1231,25 @@ 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", 'D') @@ -1585,6 +1604,25 @@ 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 diff --git a/src/version.c b/src/version.c index 6b1da3ea7cb6d..7d1c91b8cc9e8 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 538, /**/ 537, /**/