1
0
forked from aniani/vim

patch 8.2.3578: manipulating highlighting is complicated

Problem:    Manipulating highlighting is complicated.
Solution:   Add the hlget() and hlset() functions. (Yegappan Lakshmanan,
            closes #9039)
This commit is contained in:
Yegappan Lakshmanan 2021-11-03 21:56:45 +00:00 committed by Bram Moolenaar
parent 0f0044125c
commit d1a8d658e1
9 changed files with 724 additions and 0 deletions

View File

@ -2718,6 +2718,8 @@ histget({history} [, {index}]) String get the item {index} from a history
histnr({history}) Number highest index of a history
hlID({name}) Number syntax ID of highlight group {name}
hlexists({name}) Number |TRUE| if highlight group {name} exists
hlget([{name} [, {resolve}]]) List get highlight group attributes
hlset({list}) Number set highlight group attributes
hostname() String name of the machine Vim is running on
iconv({expr}, {from}, {to}) String convert encoding of {expr}
indent({lnum}) Number indent of line {lnum}
@ -6716,6 +6718,93 @@ hlexists({name}) *hlexists()*
Can also be used as a |method|: >
GetName()->hlexists()
<
hlget([{name} [, {resolve}]]) *hlget()*
Returns a List of all the highlight group attributes. If the
optional {name} is specified, then returns a List with only
the attributes of the specified highlight group. Returns an
empty List if the highlight group {name} is not present.
If the optional {resolve} argument is set to v:true and the
highlight group {name} is linked to another group, then the
link is resolved recursively and the attributes of the
resolved highlight group are returned.
Each entry in the returned List is a Dictionary with the
following items:
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|.
ctermbg cterm background color.
See |highlight-ctermbg|.
ctermfg cterm foreground color.
See |highlight-ctermfg|.
ctermul cterm underline color. See |highlight-ctermul|.
font highlight group font. See |highlight-font|.
gui gui attributes. See |highlight-gui|.
guibg gui background color. See |highlight-guibg|.
guifg gui foreground color. See |highlight-guifg|.
guisp gui special color. See |highlight-guisp|.
id highlight group ID.
linksto linked highlight group name.
See |:highlight-link|.
name highlight group name. See |group-name|.
start start terminal keycode. See |highlight-start|.
stop stop terminal keycode. See |highlight-stop|.
term term attributes. See |highlight-term|.
The 'term', 'cterm' and 'gui' items in the above Dictionary
have a dictionary value with the following optional boolean
items: 'bold', 'standout', 'underline', 'undercurl', 'italic',
'reverse', 'inverse' and 'strikethrough'.
Example(s): >
:echo hlget()
:echo hlget('ModeMsg')
:echo hlget('Number', v:true)
<
Can also be used as a |method|: >
GetName()->hlget()
<
hlset({list}) *hlset()*
Creates or modifies the attributes of a List of highlight
groups. Each item in {list} is a dictionary containing the
attributes of a highlight group. See |hlget()| for the list of
supported items in this dictionary.
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.
Otherwise the attributes of an existing highlight group are
modified.
If an empty dictionary value is used for the 'term' or 'cterm'
or 'gui' entries, then the corresponding attributes are
cleared. If the 'cleared' item is set to v:true, then all the
attributes of the highlight group are cleared.
The 'linksto' item can be used to link a highlight group to
another highlight group. See |:highlight-link|.
Returns zero for success, -1 for failure.
Example(s): >
" add bold attribute to the Visual highlight group
:call hlset([#{name: 'Visual',
\ term: #{reverse: 1 , bold: 1}}])
:call hlset([#{name: 'Type', guifg: 'DarkGreen'}])
:let l = hlget()
:call hlset(l)
" clear the Search highlight group
:call hlset([#{name: 'Search', cleared: v:true}])
" clear the 'term' attributes for a highlight group
:call hlset([#{name: 'Title', term: {}}])
" create the MyHlg group linking it to DiffAdd
:call hlset([#{name: 'MyHlg', linksto: 'DiffAdd'}])
<
Can also be used as a |method|: >
GetAttrList()->hlset()
<
*hlID()*
hlID({name}) The result is a Number, which is the ID of the highlight group

View File

@ -4849,6 +4849,7 @@ in their own color.
:hi[ghlight] {group-name}
List one highlight group.
*highlight-clear*
:hi[ghlight] clear Reset all highlighting to the defaults. Removes all
highlighting for groups added by the user!
Uses the current value of 'background' to decide which

View File

@ -925,6 +925,8 @@ Syntax and highlighting: *syntax-functions* *highlighting-functions*
getmatches() get all matches defined by |matchadd()| and
the |:match| commands
hlexists() check if a highlight group exists
hlget() get highlight group attributes
hlset() set highlight group attributes
hlID() get ID of a highlight group
synID() get syntax ID at a specific position
synIDattr() get a specific attribute of a syntax ID

View File

@ -1358,6 +1358,7 @@ directory Displays directory contents. Can be used by a file explorer
< The buffer name is the name of the directory and is adjusted
when using the |:cd| command.
*scratch-buffer*
scratch Contains text that can be discarded at any time. It is kept
when closing the window, it must be deleted explicitly.
Settings: >

View File

@ -1527,6 +1527,10 @@ static funcentry_T global_functions[] =
ret_number, f_hlID},
{"hlexists", 1, 1, FEARG_1, arg1_string,
ret_number_bool, f_hlexists},
{"hlget", 0, 2, FEARG_1, arg2_string_bool,
ret_list_dict_any, f_hlget},
{"hlset", 1, 1, FEARG_1, arg1_list_any,
ret_number_bool, f_hlset},
{"hostname", 0, 0, 0, NULL,
ret_string, f_hostname},
{"iconv", 3, 3, FEARG_1, arg3_string,

View File

@ -4081,3 +4081,457 @@ free_highlight_fonts(void)
# endif
}
#endif
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Convert each of the highlight attribute bits (bold, standout, underline,
* etc.) set in 'hlattr' into a separate boolean item in a Dictionary with
* the attribute name as the key.
*/
static dict_T *
highlight_get_attr_dict(int hlattr)
{
dict_T *dict;
int i;
dict = dict_alloc();
if (dict == NULL)
return NULL;
for (i = 0; hl_attr_table[i] != 0; ++i)
{
if (hlattr & hl_attr_table[i])
{
dict_add_bool(dict, hl_name_table[i], VVAL_TRUE);
hlattr &= ~hl_attr_table[i]; // don't want "inverse"
}
}
return dict;
}
/*
* Return the attributes of the highlight group at index 'hl_idx' as a
* Dictionary. If 'resolve_link' is TRUE, then resolves the highlight group
* links recursively.
*/
static dict_T *
highlight_get_info(int hl_idx, int resolve_link)
{
dict_T *dict;
hl_group_T *sgp;
dict_T *attr_dict;
int hlgid;
dict = dict_alloc();
if (dict == NULL)
return dict;
sgp = &HL_TABLE()[hl_idx];
// highlight group id is 1-based
hlgid = hl_idx + 1;
if (dict_add_string(dict, "name", sgp->sg_name) == FAIL)
goto error;
if (dict_add_number(dict, "id", hlgid) == FAIL)
goto error;
if (sgp->sg_link && resolve_link)
{
// resolve the highlight group link recursively
while (sgp->sg_link)
{
hlgid = sgp->sg_link;
sgp = &HL_TABLE()[sgp->sg_link - 1];
}
}
if (sgp->sg_term != 0)
{
attr_dict = highlight_get_attr_dict(sgp->sg_term);
if (attr_dict != NULL)
if (dict_add_dict(dict, "term", attr_dict) == FAIL)
goto error;
}
if (sgp->sg_start != NULL)
if (dict_add_string(dict, "start", sgp->sg_start) == FAIL)
goto error;
if (sgp->sg_stop != NULL)
if (dict_add_string(dict, "stop", sgp->sg_stop) == FAIL)
goto error;
if (sgp->sg_cterm != 0)
{
attr_dict = highlight_get_attr_dict(sgp->sg_cterm);
if (attr_dict != NULL)
if (dict_add_dict(dict, "cterm", attr_dict) == FAIL)
goto error;
}
if (sgp->sg_cterm_fg != 0)
if (dict_add_string(dict, "ctermfg",
highlight_color(hlgid, (char_u *)"fg", 'c')) == FAIL)
goto error;
if (sgp->sg_cterm_bg != 0)
if (dict_add_string(dict, "ctermbg",
highlight_color(hlgid, (char_u *)"bg", 'c')) == FAIL)
goto error;
if (sgp->sg_cterm_ul != 0)
if (dict_add_string(dict, "ctermul",
highlight_color(hlgid, (char_u *)"ul", 'c')) == FAIL)
goto error;
if (sgp->sg_gui != 0)
{
attr_dict = highlight_get_attr_dict(sgp->sg_gui);
if (attr_dict != NULL)
if (dict_add_dict(dict, "gui", attr_dict) == FAIL)
goto error;
}
if (sgp->sg_gui_fg_name != NULL)
if (dict_add_string(dict, "guifg",
highlight_color(hlgid, (char_u *)"fg", 'g')) == FAIL)
goto error;
if (sgp->sg_gui_bg_name != NULL)
if (dict_add_string(dict, "guibg",
highlight_color(hlgid, (char_u *)"bg", 'g')) == FAIL)
goto error;
if (sgp->sg_gui_sp_name != NULL)
if (dict_add_string(dict, "guisp",
highlight_color(hlgid, (char_u *)"sp", 'g')) == FAIL)
goto error;
# ifdef FEAT_GUI
if (sgp->sg_font_name != NULL)
if (dict_add_string(dict, "font", sgp->sg_font_name) == FAIL)
goto error;
# endif
if (sgp->sg_link)
{
char_u *link;
link = HL_TABLE()[sgp->sg_link - 1].sg_name;
if (link != NULL && dict_add_string(dict, "linksto", link) == FAIL)
goto error;
}
if (dict_len(dict) == 2)
// If only 'name' is present, then the highlight group is cleared.
dict_add_bool(dict, "cleared", VVAL_TRUE);
return dict;
error:
vim_free(dict);
return NULL;
}
/*
* "hlget([name])" function
* Return the attributes of a specific highlight group (if specified) or all
* the highlight groups.
*/
void
f_hlget(typval_T *argvars, typval_T *rettv)
{
list_T *list;
dict_T *dict;
int i;
char_u *hlarg = NULL;
int resolve_link = FALSE;
if (rettv_list_alloc(rettv) == FAIL)
return;
if (check_for_opt_string_arg(argvars, 0) == FAIL
|| (argvars[0].v_type != VAR_UNKNOWN
&& check_for_opt_bool_arg(argvars, 1) == FAIL))
return;
if (argvars[0].v_type != VAR_UNKNOWN)
{
// highlight group name supplied
hlarg = tv_get_string_chk(&argvars[0]);
if (hlarg == NULL)
return;
if (argvars[1].v_type != VAR_UNKNOWN)
{
int error = FALSE;
resolve_link = tv_get_bool_chk(&argvars[1], &error);
if (error)
return;
}
}
list = rettv->vval.v_list;
for (i = 0; i < highlight_ga.ga_len && !got_int; ++i)
{
if (hlarg == NULL || STRICMP(hlarg, HL_TABLE()[i].sg_name) == 0)
{
dict = highlight_get_info(i, resolve_link);
if (dict != NULL)
list_append_dict(list, dict);
}
}
}
/*
* Returns the string value at 'dict[key]'. Returns NULL, if 'key' is not in
* 'dict' or the value is not a string type. If the value is not a string type
* or is NULL, then 'error' is set to TRUE.
*/
static char_u *
hldict_get_string(dict_T *dict, char_u *key, int *error)
{
dictitem_T *di;
*error = FALSE;
di = dict_find(dict, key, -1);
if (di == NULL)
return NULL;
if (di->di_tv.v_type != VAR_STRING || di->di_tv.vval.v_string == NULL)
{
emsg(_(e_stringreq));
*error = TRUE;
return NULL;
}
return di->di_tv.vval.v_string;
}
/*
* Convert the highlight attribute Dictionary at 'dict[key]' into a string
* value in 'attr_str' of length 'len'. Returns FALSE if 'dict[key]' is not a
* Dictionary or is NULL.
*/
static int
hldict_attr_to_str(
dict_T *dict,
char_u *key,
char_u *attr_str,
int len)
{
dictitem_T *di;
dict_T *attrdict;
int i;
attr_str[0] = NUL;
di = dict_find(dict, key, -1);
if (di == NULL)
return TRUE;
if (di->di_tv.v_type != VAR_DICT || di->di_tv.vval.v_dict == NULL)
{
emsg(_(e_dictreq));
return FALSE;
}
attrdict = di->di_tv.vval.v_dict;
// If the attribute dict is empty, then return NONE to clear the attributes
if (dict_len(attrdict) == 0)
{
vim_strcat(attr_str, (char_u *)"NONE", len);
return TRUE;
}
for (i = 0; i < (int)ARRAY_LENGTH(hl_name_table); i++)
{
if (dict_get_bool(attrdict, (char_u *)hl_name_table[i],
VVAL_FALSE) == VVAL_TRUE)
{
if (attr_str[0] != NUL)
vim_strcat(attr_str, (char_u *)",", len);
vim_strcat(attr_str, (char_u *)hl_name_table[i], len);
}
}
return TRUE;
}
/*
* Add or update a highlight group using 'dict' items. Returns TRUE if
* successfully updated the highlight group.
*/
static int
hlg_add_or_update(dict_T *dict)
{
char_u *name;
int error;
char_u term_attr[80];
char_u cterm_attr[80];
char_u gui_attr[80];
char_u *start;
char_u *stop;
char_u *ctermfg;
char_u *ctermbg;
char_u *ctermul;
char_u *guifg;
char_u *guibg;
char_u *guisp;
# ifdef FEAT_GUI
char_u *font;
# endif
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_find(dict, (char_u *)"cleared", -1) != NULL)
{
varnumber_T cleared;
// clear a highlight group
cleared = dict_get_bool(dict, (char_u *)"cleared", FALSE);
if (cleared == TRUE)
{
vim_snprintf((char *)IObuff, IOSIZE, "clear %s", name);
do_highlight(IObuff, FALSE, FALSE);
}
return TRUE;
}
start = hldict_get_string(dict, (char_u *)"start", &error);
if (error)
return FALSE;
stop = hldict_get_string(dict, (char_u *)"stop", &error);
if (error)
return FALSE;
if (!hldict_attr_to_str(dict, (char_u *)"term", term_attr,
sizeof(term_attr)))
return FALSE;
if (!hldict_attr_to_str(dict, (char_u *)"cterm", cterm_attr,
sizeof(cterm_attr)))
return FALSE;
ctermfg = hldict_get_string(dict, (char_u *)"ctermfg", &error);
if (error)
return FALSE;
ctermbg = hldict_get_string(dict, (char_u *)"ctermbg", &error);
if (error)
return FALSE;
ctermul = hldict_get_string(dict, (char_u *)"ctermul", &error);
if (error)
return FALSE;
if (!hldict_attr_to_str(dict, (char_u *)"gui", gui_attr,
sizeof(gui_attr)))
return FALSE;
guifg = hldict_get_string(dict, (char_u *)"guifg", &error);
if (error)
return FALSE;
guibg = hldict_get_string(dict, (char_u *)"guibg", &error);
if (error)
return FALSE;
guisp = hldict_get_string(dict, (char_u *)"guisp", &error);
if (error)
return FALSE;
# ifdef FEAT_GUI
font = hldict_get_string(dict, (char_u *)"font", &error);
if (error)
return FALSE;
# endif
// If none of the attributes are specified, then do nothing.
if (term_attr[0] == NUL && start == NULL && stop == NULL
&& cterm_attr[0] == NUL && ctermfg == NULL && ctermbg == NULL
&& ctermul == NULL && gui_attr[0] == NUL
# ifdef FEAT_GUI
&& font == NULL
# endif
&& guifg == NULL && guibg == NULL && guisp == NULL
)
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",
name,
term_attr[0] != NUL ? "term=" : "",
term_attr[0] != NUL ? term_attr : (char_u *)"",
start != NULL ? "start=" : "",
start != NULL ? start : (char_u *)"",
stop != NULL ? "stop=" : "",
stop != NULL ? stop : (char_u *)"",
cterm_attr[0] != NUL ? "cterm=" : "",
cterm_attr[0] != NUL ? cterm_attr : (char_u *)"",
ctermfg != NULL ? "ctermfg=" : "",
ctermfg != NULL ? ctermfg : (char_u *)"",
ctermbg != NULL ? "ctermbg=" : "",
ctermbg != NULL ? ctermbg : (char_u *)"",
ctermul != NULL ? "ctermul=" : "",
ctermul != NULL ? ctermul : (char_u *)"",
gui_attr[0] != NUL ? "gui=" : "",
gui_attr[0] != NUL ? gui_attr : (char_u *)"",
# ifdef FEAT_GUI
font != NULL ? "font=" : "",
font != NULL ? font : (char_u *)"",
# else
"", "",
# endif
guifg != NULL ? "guifg=" : "",
guifg != NULL ? guifg : (char_u *)"",
guibg != NULL ? "guibg=" : "",
guibg != NULL ? guibg : (char_u *)"",
guisp != NULL ? "guisp=" : "",
guisp != NULL ? guisp : (char_u *)""
);
do_highlight(IObuff, FALSE, FALSE);
return TRUE;
}
/*
* "hlset([{highlight_attr}])" function
* Add or modify highlight groups
*/
void
f_hlset(typval_T *argvars, typval_T *rettv)
{
listitem_T *li;
dict_T *dict;
rettv->vval.v_number = -1;
if (check_for_list_arg(argvars, 0) == FAIL)
return;
FOR_ALL_LIST_ITEMS(argvars->vval.v_list, li)
{
if (li->li_tv.v_type != VAR_DICT)
{
emsg(_(e_dictreq));
return;
}
dict = li->li_tv.vval.v_dict;
if (!hlg_add_or_update(dict))
return;
}
rettv->vval.v_number = 0;
}
#endif

View File

@ -49,4 +49,6 @@ void set_context_in_highlight_cmd(expand_T *xp, char_u *arg);
char_u *get_highlight_name(expand_T *xp, int idx);
char_u *get_highlight_name_ext(expand_T *xp, int idx, int skip_cleared);
void free_highlight_fonts(void);
void f_hlget(typval_T *argvars, typval_T *rettv);
void f_hlset(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */

View File

@ -4,6 +4,7 @@ source view_util.vim
source screendump.vim
source check.vim
source script_util.vim
source vim9.vim
func Test_highlight()
" basic test if ":highlight" doesn't crash
@ -970,4 +971,164 @@ func Test_colornames_assignment_and_unassignment()
call assert_fails("echo v:colornames['x1']")
endfunc
" Test for the hlget() function
func Test_hlget()
let lines =<< trim END
call assert_notequal([], filter(hlget(), 'v:val.name == "Visual"'))
call assert_equal([], hlget('SomeHLGroup'))
highlight MyHLGroup term=standout cterm=reverse ctermfg=10 ctermbg=Black
call assert_equal([{'id': hlID('MyHLGroup'), 'ctermfg': '10', 'name': 'MyHLGroup', 'term': {'standout': v:true}, 'ctermbg': '0', 'cterm': {'reverse': v:true}}], hlget('MyHLGroup'))
highlight clear MyHLGroup
call assert_equal(v:true, hlget('MyHLGroup')[0].cleared)
highlight link MyHLGroup IncSearch
call assert_equal('IncSearch', hlget('MyHLGroup')[0].linksto)
highlight clear MyHLGroup
call assert_equal([], hlget(test_null_string()))
call assert_equal([], hlget(""))
END
call CheckLegacyAndVim9Success(lines)
" Test for resolving highlight group links
let lines =<< trim END
highlight hlgA term=bold
VAR hlgAid = hlID('hlgA')
highlight link hlgB hlgA
VAR hlgBid = hlID('hlgB')
highlight link hlgC hlgB
VAR hlgCid = hlID('hlgC')
call assert_equal('hlgA', hlget('hlgB')[0].linksto)
call assert_equal('hlgB', hlget('hlgC')[0].linksto)
call assert_equal([{'id': hlgAid, 'name': 'hlgA',
\ 'term': {'bold': v:true}}], hlget('hlgA'))
call assert_equal([{'id': hlgBid, 'name': 'hlgB',
\ 'linksto': 'hlgA'}], hlget('hlgB'))
call assert_equal([{'id': hlgCid, 'name': 'hlgC',
\ 'linksto': 'hlgB'}], hlget('hlgC'))
call assert_equal([{'id': hlgAid, 'name': 'hlgA',
\ 'term': {'bold': v:true}}], hlget('hlgA', v:false))
call assert_equal([{'id': hlgBid, 'name': 'hlgB',
\ 'linksto': 'hlgA'}], hlget('hlgB', 0))
call assert_equal([{'id': hlgCid, 'name': 'hlgC',
\ 'linksto': 'hlgB'}], hlget('hlgC', v:false))
call assert_equal([{'id': hlgAid, 'name': 'hlgA',
\ 'term': {'bold': v:true}}], hlget('hlgA', v:true))
call assert_equal([{'id': hlgBid, 'name': 'hlgB',
\ 'term': {'bold': v:true}}], hlget('hlgB', 1))
call assert_equal([{'id': hlgCid, 'name': 'hlgC',
\ 'term': {'bold': v:true}}], hlget('hlgC', v:true))
END
call CheckLegacyAndVim9Success(lines)
call assert_fails('call hlget([])', 'E1174:')
call assert_fails('call hlget("abc", "xyz")', 'E1212:')
endfunc
" Test for the hlset() function
func Test_hlset()
let lines =<< trim END
call assert_equal(0, hlset(test_null_list()))
call assert_equal(0, hlset([]))
call assert_fails('call hlset(["Search"])', 'E715:')
call hlset(hlget())
call hlset([{'name': 'NewHLGroup', 'cterm': {'reverse': v:true}, 'ctermfg': '10'}])
call assert_equal({'reverse': v:true}, hlget('NewHLGroup')[0].cterm)
call hlset([{'name': 'NewHLGroup', 'cterm': {'bold': v:true}}])
call assert_equal({'bold': v:true}, hlget('NewHLGroup')[0].cterm)
call hlset([{'name': 'NewHLGroup', 'cleared': v:true}])
call assert_equal(v:true, hlget('NewHLGroup')[0].cleared)
call hlset([{'name': 'NewHLGroup', 'linksto': 'Search'}])
call assert_false(has_key(hlget('NewHLGroup')[0], 'cleared'))
call assert_equal('Search', hlget('NewHLGroup')[0].linksto)
call assert_fails("call hlset([{'name': [], 'ctermfg': '10'}])", 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'cleared': []}])",
\ 'E745:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'cterm': 'Blue'}])",
\ 'E715:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'ctermbg': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'ctermfg': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'ctermul': []}])",
\ 'E928:')
if has('gui')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'font': []}])",
\ 'E928:')
endif
call assert_fails("call hlset([{'name': 'NewHLGroup', 'gui': 'Cyan'}])",
\ 'E715:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'guibg': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'guifg': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'guisp': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'linksto': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'start': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'stop': []}])",
\ 'E928:')
call assert_fails("call hlset([{'name': 'NewHLGroup', 'term': 'Cyan'}])",
\ 'E715:')
call assert_equal('Search', hlget('NewHLGroup')[0].linksto)
highlight clear NewHLGroup
END
call CheckLegacyAndVim9Success(lines)
" Test for clearing the 'term', 'cterm' and 'gui' attributes of a highlight
" group.
let lines =<< trim END
highlight myhlg1 term=bold cterm=italic gui=standout
VAR id = hlID('myhlg1')
call hlset([{'name': 'myhlg1', 'term': {}}])
call assert_equal([{'id': id, 'name': 'myhlg1',
\ 'cterm': {'italic': v:true}, 'gui': {'standout': v:true}}],
\ hlget('myhlg1'))
call hlset([{'name': 'myhlg1', 'cterm': {}}])
call assert_equal([{'id': id, 'name': 'myhlg1',
\ 'gui': {'standout': v:true}}], hlget('myhlg1'))
call hlset([{'name': 'myhlg1', 'gui': {}}])
call assert_equal([{'id': id, 'name': 'myhlg1', 'cleared': v:true}],
\ hlget('myhlg1'))
highlight clear myhlg1
END
call CheckLegacyAndVim9Success(lines)
" Test for setting all the 'term', 'cterm' and 'gui' attributes of a
" highlight group
let lines =<< trim END
VAR attr = {'bold': v:true, 'underline': v:true, 'undercurl': v:true,
\ 'strikethrough': v:true, 'reverse': v:true, 'italic': v:true,
\ '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"))
call assert_equal([{'id': id2, 'name': 'myhlg2', 'gui': attr,
\ 'term': attr, 'cterm': attr}], hlget('myhlg2'))
END
call CheckLegacyAndVim9Success(lines)
" Test for clearing some of the 'term', 'cterm' and 'gui' attributes of a
" highlight group
let lines =<< trim END
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"))
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)
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1721,6 +1721,16 @@ def Test_hlexists()
hlexists('')->assert_equal(0)
enddef
def Test_hlget()
CheckDefAndScriptFailure2(['hlget([])'], 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 'E1174: String required for argument 1')
hlget('')->assert_equal([])
enddef
def Test_hlset()
CheckDefAndScriptFailure2(['hlset("id")'], 'E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1')
hlset([])->assert_equal(0)
enddef
def Test_iconv()
CheckDefAndScriptFailure2(['iconv(1, "from", "to")'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1')
CheckDefAndScriptFailure2(['iconv("abc", 10, "to")'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2')