Problem: Manipulating highlighting is complicated.
Solution: Add the hlget() and hlset() functions. (Yegappan Lakshmanan,
closes #9039)
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}
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
: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
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
< 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: >
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,
# 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
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 : */
source screendump.vim
source check.vim
source script_util.vim
+source vim9.vim
func Test_highlight()
" basic test if ":highlight" doesn't crash
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
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')