# HG changeset patch # User Bram Moolenaar # Date 1637083804 -3600 # Node ID 3da380450ccefa902f4a511af2945c2759b96db0 # Parent 18cbc3a4d8b939b41d69bc67ff00c742bccdd410 patch 8.2.3605: cannot clear and unlinke a highlight group with hlset() Commit: https://github.com/vim/vim/commit/2a16dc6613368c54d526850bcbcd03c3fec1be67 Author: Yegappan Lakshmanan Date: Tue Nov 16 17:19:30 2021 +0000 patch 8.2.3605: cannot clear and unlinke a highlight group with hlset() Problem: Cannot clear and unlinke a highlight group with hlset() in a single call. Solution: Add the "force" option. (Yegappan Lakshmanan, closes #9117) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -6750,7 +6750,7 @@ hlget([{name} [, {resolve}]]) *hlget( Each entry in the returned List is a Dictionary with the following items: - cleared Boolean flag, set to v:true if the highlight + cleared boolean flag, set to v:true if the highlight group attributes are cleared or not yet specified. See |highlight-clear|. cterm cterm attributes. See |highlight-cterm|. @@ -6759,6 +6759,9 @@ hlget([{name} [, {resolve}]]) *hlget( ctermfg cterm foreground color. See |highlight-ctermfg|. ctermul cterm underline color. See |highlight-ctermul|. + default boolean flag, set to v:true if the highlight + group link is a default link. See + |highlight-default|. font highlight group font. See |highlight-font|. gui gui attributes. See |highlight-gui|. guibg gui background color. See |highlight-guibg|. @@ -6791,6 +6794,13 @@ hlset({list}) *hlset()* attributes of a highlight group. See |hlget()| for the list of supported items in this dictionary. + In addition to the items described in |hlget()|, the following + additional items are supported in the dictionary: + + force boolean flag to force the creation of + a link for an existing highlight group + with attributes. + The highlight group is identified using the 'name' item and the 'id' item (if supplied) is ignored. If a highlight group with a specified name doesn't exist, then it is created. @@ -6820,6 +6830,11 @@ hlset({list}) *hlset()* :call hlset([#{name: 'Title', term: {}}]) " create the MyHlg group linking it to DiffAdd :call hlset([#{name: 'MyHlg', linksto: 'DiffAdd'}]) + " remove the MyHlg group link + :call hlset([#{name: 'MyHlg', linksto: 'NONE'}]) + " clear the attributes and a link + :call hlset([#{name: 'MyHlg', cleared: v:true, + \ linksto: 'NONE'}]) < Can also be used as a |method|: > GetAttrList()->hlset() diff --git a/src/highlight.c b/src/highlight.c --- a/src/highlight.c +++ b/src/highlight.c @@ -4176,6 +4176,9 @@ highlight_get_info(int hl_idx, int resol link = HL_TABLE()[sgp->sg_link - 1].sg_name; if (link != NULL && dict_add_string(dict, "linksto", link) == FAIL) goto error; + + if (sgp->sg_deflink) + dict_add_bool(dict, "default", VVAL_TRUE); } if (dict_len(dict) == 2) // If only 'name' is present, then the highlight group is cleared. @@ -4337,25 +4340,19 @@ hlg_add_or_update(dict_T *dict) # ifdef FEAT_GUI char_u *font; # endif + int forceit = FALSE; + int dodefault = FALSE; + int done = FALSE; name = hldict_get_string(dict, (char_u *)"name", &error); if (name == NULL || error) return FALSE; - if (dict_find(dict, (char_u *)"linksto", -1) != NULL) - { - char_u *linksto; - - // link highlight groups - linksto = hldict_get_string(dict, (char_u *)"linksto", &error); - if (linksto == NULL || error) - return FALSE; - - vim_snprintf((char *)IObuff, IOSIZE, "link %s %s", name, linksto); - do_highlight(IObuff, FALSE, FALSE); - - return TRUE; - } + if (dict_get_bool(dict, (char_u *)"force", VVAL_FALSE) == VVAL_TRUE) + forceit = TRUE; + + if (dict_get_bool(dict, (char_u *)"default", VVAL_FALSE) == VVAL_TRUE) + dodefault = TRUE; if (dict_find(dict, (char_u *)"cleared", -1) != NULL) { @@ -4366,11 +4363,31 @@ hlg_add_or_update(dict_T *dict) if (cleared == TRUE) { vim_snprintf((char *)IObuff, IOSIZE, "clear %s", name); - do_highlight(IObuff, FALSE, FALSE); + do_highlight(IObuff, forceit, FALSE); + done = TRUE; } - + } + + if (dict_find(dict, (char_u *)"linksto", -1) != NULL) + { + char_u *linksto; + + // link highlight groups + linksto = hldict_get_string(dict, (char_u *)"linksto", &error); + if (linksto == NULL || error) + return FALSE; + + vim_snprintf((char *)IObuff, IOSIZE, "%slink %s %s", + dodefault ? "default " : "", name, linksto); + do_highlight(IObuff, forceit, FALSE); + + done = TRUE; + } + + // If 'cleared' or 'linksto' are specified, then don't process the other + // attributes. + if (done) return TRUE; - } start = hldict_get_string(dict, (char_u *)"start", &error); if (error) @@ -4434,7 +4451,8 @@ hlg_add_or_update(dict_T *dict) return TRUE; vim_snprintf((char *)IObuff, IOSIZE, - "%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s", + "%s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s", + dodefault ? "default " : "", name, term_attr[0] != NUL ? "term=" : "", term_attr[0] != NUL ? term_attr : (char_u *)"", @@ -4466,7 +4484,7 @@ hlg_add_or_update(dict_T *dict) guisp != NULL ? guisp : (char_u *)"" ); - do_highlight(IObuff, FALSE, FALSE); + do_highlight(IObuff, forceit, FALSE); return TRUE; } diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim --- a/src/testdir/test_highlight.vim +++ b/src/testdir/test_highlight.vim @@ -1046,9 +1046,6 @@ endfunc " Test for the hlset() function func Test_hlset() - let save_columns = &columns - let &columns = 80 - let lines =<< trim END call assert_equal(0, hlset(test_null_list())) call assert_equal(0, hlset([])) @@ -1126,12 +1123,10 @@ func Test_hlset() \ 'standout': v:true, 'nocombine': v:true} call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}]) VAR id2 = hlID('myhlg2') - VAR output =<< trim END - myhlg2 xxx term=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough - cterm=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough - gui=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough - END - call assert_equal(output, execute('highlight myhlg2')->split("\n")) + VAR expected = "myhlg2 xxx term=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough cterm=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough gui=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough" + VAR output = execute('highlight myhlg2') + LET output = output->split("\n")->join()->substitute('\s\+', ' ', 'g') + call assert_equal(expected, output) call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr, \ 'term': attr, 'cterm': attr}], hlget('myhlg2')) END @@ -1143,18 +1138,96 @@ func Test_hlset() VAR attr = {'bold': v:false, 'underline': v:true, 'strikethrough': v:true} call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}]) VAR id2 = hlID('myhlg2') - VAR output =<< trim END - myhlg2 xxx term=underline,strikethrough cterm=underline,strikethrough - gui=underline,strikethrough - END - call assert_equal(output, execute('highlight myhlg2')->split("\n")) + VAR expected = "myhlg2 xxx term=underline,strikethrough cterm=underline,strikethrough gui=underline,strikethrough" + VAR output = execute('highlight myhlg2') + LET output = output->split("\n")->join()->substitute('\s\+', ' ', 'g') + call assert_equal(expected, output) LET attr = {'underline': v:true, 'strikethrough': v:true} call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr, \ 'term': attr, 'cterm': attr}], hlget('myhlg2')) END call CheckLegacyAndVim9Success(lines) - let &columns = save_columns + " Test for clearing the attributes and link of a highlight group + let lines =<< trim END + highlight myhlg3 ctermbg=green guibg=green + highlight! default link myhlg3 ErrorMsg + VAR id3 = hlID('myhlg3') + call hlset([{'name': 'myhlg3', 'cleared': v:true, 'linksto': 'NONE'}]) + call assert_equal([{'id': id3, 'name': 'myhlg3', 'cleared': v:true}], + \ hlget('myhlg3')) + highlight clear hlg3 + END + call CheckLegacyAndVim9Success(lines) + + " Test for setting default attributes for a highlight group + let lines =<< trim END + call hlset([{'name': 'hlg4', 'ctermfg': '8'}]) + call hlset([{'name': 'hlg4', 'default': v:true, 'ctermfg': '9'}]) + VAR id4 = hlID('hlg4') + call assert_equal([{'id': id4, 'name': 'hlg4', 'ctermfg': '8'}], + \ hlget('hlg4')) + highlight clear hlg4 + + call hlset([{'name': 'hlg5', 'default': v:true, 'ctermbg': '2'}]) + call hlset([{'name': 'hlg5', 'ctermbg': '4'}]) + VAR id5 = hlID('hlg5') + call assert_equal([{'id': id5, 'name': 'hlg5', 'ctermbg': '4'}], + \ hlget('hlg5')) + highlight clear hlg5 + + call hlset([{'name': 'hlg6', 'linksto': 'Error'}]) + VAR id6 = hlID('hlg6') + call hlset([{'name': 'hlg6', 'default': v:true, 'ctermbg': '2'}]) + call assert_equal([{'id': id6, 'name': 'hlg6', 'linksto': 'Error'}], + \ hlget('hlg6')) + highlight clear hlg6 + END + call CheckLegacyAndVim9Success(lines) + + " Test for setting default links for a highlight group + let lines =<< trim END + call hlset([{'name': 'hlg7', 'ctermfg': '5'}]) + call hlset([{'name': 'hlg7', 'default': v:true, 'linksto': 'Search'}]) + VAR id7 = hlID('hlg7') + call assert_equal([{'id': id7, 'name': 'hlg7', 'ctermfg': '5'}], + \ hlget('hlg7')) + highlight clear hlg7 + + call hlset([{'name': 'hlg8', 'default': v:true, 'linksto': 'Search'}]) + VAR id8 = hlID('hlg8') + call assert_equal([{'id': id8, 'name': 'hlg8', 'default': v:true, + \ 'linksto': 'Search'}], hlget('hlg8')) + call hlset([{'name': 'hlg8', 'ctermbg': '2'}]) + call assert_equal([{'id': id8, 'name': 'hlg8', 'ctermbg': '2'}], + \ hlget('hlg8')) + highlight clear hlg8 + + highlight default link hlg9 ErrorMsg + VAR hlg_save = hlget('hlg9') + LET hlg_save[0]['name'] = 'hlg9dup' + call hlset(hlg_save) + VAR id9 = hlID('hlg9dup') + highlight clear hlg9dup + call assert_equal([{'id': id9, 'name': 'hlg9dup', 'default': v:true, + \ 'linksto': 'ErrorMsg'}], hlget('hlg9dup')) + highlight clear hlg9 + END + call CheckLegacyAndVim9Success(lines) + + " Test for force creating a link to a highlight group + let lines =<< trim END + call hlset([{'name': 'hlg10', 'ctermfg': '8'}]) + call hlset([{'name': 'hlg10', 'linksto': 'Search'}]) + VAR id10 = hlID('hlg10') + call assert_equal([{'id': id10, 'name': 'hlg10', 'ctermfg': '8'}], + \ hlget('hlg10')) + call hlset([{'name': 'hlg10', 'linksto': 'Search', 'force': v:true}]) + call assert_equal([{'id': id10, 'name': 'hlg10', 'ctermfg': '8', + \ 'linksto': 'Search'}], hlget('hlg10')) + highlight clear hlg10 + END + call CheckLegacyAndVim9Success(lines) endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -3297,6 +3297,7 @@ def Test_sign_placelist() CheckDefAndScriptFailure2(['sign_placelist("x")'], 'E1013: Argument 1: type mismatch, expected list but got string', 'E1211: List required for argument 1') CheckDefAndScriptFailure2(['sign_placelist({"a": 10})'], 'E1013: Argument 1: type mismatch, expected list but got dict', 'E1211: List required for argument 1') CheckDefExecAndScriptFailure(['sign_placelist([{"name": "MySign", "buffer": bufnr(), "lnum": ""}])'], 'E1209: Invalid value for a line number: ""') + assert_fails('sign_placelist([{name: "MySign", buffer: "", lnum: 1}])', 'E155:') enddef def Test_sign_undefine() diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -1570,8 +1570,8 @@ def Test_no_space_after_command() CheckDefExecAndScriptFailure(lines, 'E486:', 1) enddef -" Test for the 'popuppreview' option -def Test_popuppreview() +" Test for the 'previewpopup' option +def Test_previewpopup() set previewpopup=height:10,width:60 pedit Xfile var id = popup_findpreview()