0
0
mirror of https://github.com/vim/vim.git synced 2025-10-04 05:25:06 -04:00

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)
This commit is contained in:
Yegappan Lakshmanan
2021-11-16 17:19:30 +00:00
committed by Bram Moolenaar
parent c143fa0778
commit 2a16dc6613
5 changed files with 143 additions and 36 deletions

View File

@@ -6750,7 +6750,7 @@ hlget([{name} [, {resolve}]]) *hlget()*
Each entry in the returned List is a Dictionary with the Each entry in the returned List is a Dictionary with the
following items: 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 group attributes are cleared or not yet
specified. See |highlight-clear|. specified. See |highlight-clear|.
cterm cterm attributes. See |highlight-cterm|. cterm cterm attributes. See |highlight-cterm|.
@@ -6759,6 +6759,9 @@ hlget([{name} [, {resolve}]]) *hlget()*
ctermfg cterm foreground color. ctermfg cterm foreground color.
See |highlight-ctermfg|. See |highlight-ctermfg|.
ctermul cterm underline color. See |highlight-ctermul|. 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|. font highlight group font. See |highlight-font|.
gui gui attributes. See |highlight-gui|. gui gui attributes. See |highlight-gui|.
guibg gui background color. See |highlight-guibg|. 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 attributes of a highlight group. See |hlget()| for the list of
supported items in this dictionary. 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 highlight group is identified using the 'name' item and
the 'id' item (if supplied) is ignored. If a highlight group the 'id' item (if supplied) is ignored. If a highlight group
with a specified name doesn't exist, then it is created. with a specified name doesn't exist, then it is created.
@@ -6820,6 +6830,11 @@ hlset({list}) *hlset()*
:call hlset([#{name: 'Title', term: {}}]) :call hlset([#{name: 'Title', term: {}}])
" create the MyHlg group linking it to DiffAdd " create the MyHlg group linking it to DiffAdd
:call hlset([#{name: 'MyHlg', linksto: '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|: > Can also be used as a |method|: >
GetAttrList()->hlset() GetAttrList()->hlset()

View File

@@ -4176,6 +4176,9 @@ highlight_get_info(int hl_idx, int resolve_link)
link = HL_TABLE()[sgp->sg_link - 1].sg_name; link = HL_TABLE()[sgp->sg_link - 1].sg_name;
if (link != NULL && dict_add_string(dict, "linksto", link) == FAIL) if (link != NULL && dict_add_string(dict, "linksto", link) == FAIL)
goto error; goto error;
if (sgp->sg_deflink)
dict_add_bool(dict, "default", VVAL_TRUE);
} }
if (dict_len(dict) == 2) if (dict_len(dict) == 2)
// If only 'name' is present, then the highlight group is cleared. // 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 # ifdef FEAT_GUI
char_u *font; char_u *font;
# endif # endif
int forceit = FALSE;
int dodefault = FALSE;
int done = FALSE;
name = hldict_get_string(dict, (char_u *)"name", &error); name = hldict_get_string(dict, (char_u *)"name", &error);
if (name == NULL || error) if (name == NULL || error)
return FALSE; return FALSE;
if (dict_find(dict, (char_u *)"linksto", -1) != NULL) if (dict_get_bool(dict, (char_u *)"force", VVAL_FALSE) == VVAL_TRUE)
{ forceit = TRUE;
char_u *linksto;
// link highlight groups if (dict_get_bool(dict, (char_u *)"default", VVAL_FALSE) == VVAL_TRUE)
linksto = hldict_get_string(dict, (char_u *)"linksto", &error); dodefault = TRUE;
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_find(dict, (char_u *)"cleared", -1) != NULL) if (dict_find(dict, (char_u *)"cleared", -1) != NULL)
{ {
@@ -4366,12 +4363,32 @@ hlg_add_or_update(dict_T *dict)
if (cleared == TRUE) if (cleared == TRUE)
{ {
vim_snprintf((char *)IObuff, IOSIZE, "clear %s", name); vim_snprintf((char *)IObuff, IOSIZE, "clear %s", name);
do_highlight(IObuff, FALSE, FALSE); do_highlight(IObuff, forceit, FALSE);
done = TRUE;
}
} }
return 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); start = hldict_get_string(dict, (char_u *)"start", &error);
if (error) if (error)
return FALSE; return FALSE;
@@ -4434,7 +4451,8 @@ hlg_add_or_update(dict_T *dict)
return TRUE; return TRUE;
vim_snprintf((char *)IObuff, IOSIZE, 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, name,
term_attr[0] != NUL ? "term=" : "", term_attr[0] != NUL ? "term=" : "",
term_attr[0] != NUL ? term_attr : (char_u *)"", term_attr[0] != NUL ? term_attr : (char_u *)"",
@@ -4466,7 +4484,7 @@ hlg_add_or_update(dict_T *dict)
guisp != NULL ? guisp : (char_u *)"" guisp != NULL ? guisp : (char_u *)""
); );
do_highlight(IObuff, FALSE, FALSE); do_highlight(IObuff, forceit, FALSE);
return TRUE; return TRUE;
} }

View File

@@ -1046,9 +1046,6 @@ endfunc
" Test for the hlset() function " Test for the hlset() function
func Test_hlset() func Test_hlset()
let save_columns = &columns
let &columns = 80
let lines =<< trim END let lines =<< trim END
call assert_equal(0, hlset(test_null_list())) call assert_equal(0, hlset(test_null_list()))
call assert_equal(0, hlset([])) call assert_equal(0, hlset([]))
@@ -1126,12 +1123,10 @@ func Test_hlset()
\ 'standout': v:true, 'nocombine': v:true} \ 'standout': v:true, 'nocombine': v:true}
call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}]) call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}])
VAR id2 = hlID('myhlg2') VAR id2 = hlID('myhlg2')
VAR output =<< trim END 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"
myhlg2 xxx term=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough VAR output = execute('highlight myhlg2')
cterm=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough LET output = output->split("\n")->join()->substitute('\s\+', ' ', 'g')
gui=bold,standout,underline,undercurl,italic,reverse,nocombine,strikethrough call assert_equal(expected, output)
END
call assert_equal(output, execute('highlight myhlg2')->split("\n"))
call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr, call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr,
\ 'term': attr, 'cterm': attr}], hlget('myhlg2')) \ 'term': attr, 'cterm': attr}], hlget('myhlg2'))
END END
@@ -1143,18 +1138,96 @@ func Test_hlset()
VAR attr = {'bold': v:false, 'underline': v:true, 'strikethrough': v:true} VAR attr = {'bold': v:false, 'underline': v:true, 'strikethrough': v:true}
call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}]) call hlset([{'name': 'myhlg2', 'term': attr, 'cterm': attr, 'gui': attr}])
VAR id2 = hlID('myhlg2') VAR id2 = hlID('myhlg2')
VAR output =<< trim END VAR expected = "myhlg2 xxx term=underline,strikethrough cterm=underline,strikethrough gui=underline,strikethrough"
myhlg2 xxx term=underline,strikethrough cterm=underline,strikethrough VAR output = execute('highlight myhlg2')
gui=underline,strikethrough LET output = output->split("\n")->join()->substitute('\s\+', ' ', 'g')
END call assert_equal(expected, output)
call assert_equal(output, execute('highlight myhlg2')->split("\n"))
LET attr = {'underline': v:true, 'strikethrough': v:true} LET attr = {'underline': v:true, 'strikethrough': v:true}
call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr, call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr,
\ 'term': attr, 'cterm': attr}], hlget('myhlg2')) \ 'term': attr, 'cterm': attr}], hlget('myhlg2'))
END END
call CheckLegacyAndVim9Success(lines) 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 endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -3297,6 +3297,7 @@ def Test_sign_placelist()
CheckDefAndScriptFailure2(['sign_placelist("x")'], 'E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1') CheckDefAndScriptFailure2(['sign_placelist("x")'], 'E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1')
CheckDefAndScriptFailure2(['sign_placelist({"a": 10})'], 'E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1') CheckDefAndScriptFailure2(['sign_placelist({"a": 10})'], 'E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1')
CheckDefExecAndScriptFailure(['sign_placelist([{"name": "MySign", "buffer": bufnr(), "lnum": ""}])'], 'E1209: Invalid value for a line number: ""') 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 enddef
def Test_sign_undefine() def Test_sign_undefine()

View File

@@ -1570,8 +1570,8 @@ def Test_no_space_after_command()
CheckDefExecAndScriptFailure(lines, 'E486:', 1) CheckDefExecAndScriptFailure(lines, 'E486:', 1)
enddef enddef
" Test for the 'popuppreview' option " Test for the 'previewpopup' option
def Test_popuppreview() def Test_previewpopup()
set previewpopup=height:10,width:60 set previewpopup=height:10,width:60
pedit Xfile pedit Xfile
var id = popup_findpreview() var id = popup_findpreview()