diff options
author | Null Chilly <56817415+nullchilly@users.noreply.github.com> | 2023-03-23 16:31:39 +0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-23 10:31:39 +0100 |
commit | c0fe6c040e19ef9102a8507ffcbd88b83186326a (patch) | |
tree | abaecffb9bfd97ae0f00502c7560eb001100c135 | |
parent | ea0b66d208dbcd5d5c0a17810596d769c7a0b6dd (diff) | |
download | rneovim-c0fe6c040e19ef9102a8507ffcbd88b83186326a.tar.gz rneovim-c0fe6c040e19ef9102a8507ffcbd88b83186326a.tar.bz2 rneovim-c0fe6c040e19ef9102a8507ffcbd88b83186326a.zip |
feat(api): add nvim_get_hl (#22693)
Problem: no way of getting all highlight group definitions in a namespace.
Solution: add `nvim_get_hl()`, deprecate `nvim_get_hl_by_name()` and `nvim_get_hl_by_id()`.
-rw-r--r-- | runtime/doc/api.txt | 34 | ||||
-rw-r--r-- | runtime/doc/deprecated.txt | 2 | ||||
-rw-r--r-- | runtime/doc/news.txt | 4 | ||||
-rw-r--r-- | src/nvim/api/deprecated.c | 46 | ||||
-rw-r--r-- | src/nvim/api/keysets.lua | 5 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 8 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 56 | ||||
-rw-r--r-- | src/nvim/highlight.c | 34 | ||||
-rw-r--r-- | src/nvim/highlight_group.c | 68 | ||||
-rw-r--r-- | test/functional/api/highlight_spec.lua | 219 |
10 files changed, 385 insertions, 91 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 289788f036..197edf2e81 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -923,31 +923,23 @@ nvim_get_current_win() *nvim_get_current_win()* Return: ~ Window handle -nvim_get_hl_by_id({hl_id}, {rgb}) *nvim_get_hl_by_id()* - Gets a highlight definition by id. |hlID()| +nvim_get_hl({ns_id}, {*opts}) *nvim_get_hl()* + Gets all or specific highlight groups in a namespace. Parameters: ~ - • {hl_id} Highlight id as returned by |hlID()| - • {rgb} Export RGB colors - - Return: ~ - Highlight definition map - - See also: ~ - • nvim_get_hl_by_name - -nvim_get_hl_by_name({name}, {rgb}) *nvim_get_hl_by_name()* - Gets a highlight definition by name. - - Parameters: ~ - • {name} Highlight group name - • {rgb} Export RGB colors + • {ns_id} Get highlight groups for namespace ns_id + |nvim_get_namespaces()|. Use 0 to get global highlight groups + |:highlight|. + • {opts} Options dict: + • name: (string) Get a highlight definition by name. + • id: (integer) Get a highlight definition by id. + • link: (boolean, default true) Show linked group name + instead of effective definition |:hi-link|. Return: ~ - Highlight definition map - - See also: ~ - • nvim_get_hl_by_id + Highlight groups as a map from group name to a highlight definition + map as in |nvim_set_hl()|, or only a single highlight definition map + if requested by name or id. nvim_get_hl_id_by_name({name}) *nvim_get_hl_id_by_name()* Gets a highlight group by name diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 74c50f00a2..50f5b95ab5 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -17,6 +17,8 @@ API - *nvim_buf_set_virtual_text()* Use |nvim_buf_set_extmark()| instead. - *nvim_command_output()* Use |nvim_exec()| instead. - *nvim_execute_lua()* Use |nvim_exec_lua()| instead. +- *nvim_get_hl_by_name()* Use |nvim_get_hl()| instead. +- *nvim_get_hl_by_id()* Use |nvim_get_hl()| instead. COMMANDS - *:rv* *:rviminfo* Deprecated alias to |:rshada| command. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 1499b9d742..a03bd705a9 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -217,6 +217,8 @@ The following new APIs or features were added. • |vim.filetype.get_option()| to get the default option value for a specific filetype. This is a wrapper around |nvim_get_option_value()| with caching. + +• Added |nvim_get_hl()| for getting highlight group definitions in a format compatible with |nvim_set_hl()|. ============================================================================== CHANGED FEATURES *news-changes* @@ -278,4 +280,6 @@ release. • |vim.treesitter.get_node_at_pos()| and |vim.treesitter.get_node_at_cursor()| are both deprecated in favor of |vim.treesitter.get_node()|. +• `vim.api.nvim_get_hl_by_name()`, `vim.api.nvim_get_hl_by_id()` were deprecated, use |nvim_get_hl()| instead. + vim:tw=78:ts=8:sw=2:et:ft=help:norl: diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index 332e2b5fc3..b1e2e6811e 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -10,11 +10,14 @@ #include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/api/vimscript.h" #include "nvim/buffer_defs.h" #include "nvim/decoration.h" #include "nvim/extmark.h" #include "nvim/globals.h" +#include "nvim/highlight.h" +#include "nvim/highlight_group.h" #include "nvim/lua/executor.h" #include "nvim/memory.h" #include "nvim/pos.h" @@ -159,6 +162,49 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A return src_id; } +/// Gets a highlight definition by id. |hlID()| +/// +/// @deprecated use |nvim_get_hl()| instead +/// +/// @param hl_id Highlight id as returned by |hlID()| +/// @param rgb Export RGB colors +/// @param[out] err Error details, if any +/// @return Highlight definition map +/// @see nvim_get_hl_by_name +Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *err) + FUNC_API_SINCE(3) + FUNC_API_DEPRECATED_SINCE(9) +{ + Dictionary dic = ARRAY_DICT_INIT; + VALIDATE_INT((syn_get_final_id((int)hl_id) != 0), "highlight id", hl_id, { + return dic; + }); + int attrcode = syn_id2attr((int)hl_id); + return hl_get_attr_by_id(attrcode, rgb, arena, err); +} + +/// Gets a highlight definition by name. +/// +/// @deprecated use |nvim_get_hl()| instead +/// +/// @param name Highlight group name +/// @param rgb Export RGB colors +/// @param[out] err Error details, if any +/// @return Highlight definition map +/// @see nvim_get_hl_by_id +Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *err) + FUNC_API_SINCE(3) + FUNC_API_DEPRECATED_SINCE(9) +{ + Dictionary result = ARRAY_DICT_INIT; + int id = syn_name2id(name.data); + + VALIDATE_S((id != 0), "highlight name", name.data, { + return result; + }); + return nvim_get_hl_by_id(id, rgb, arena, err); +} + /// Inserts a sequence of lines to a buffer at a certain index /// /// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines) diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua index 2c7532bd27..b2b327d73e 100644 --- a/src/nvim/api/keysets.lua +++ b/src/nvim/api/keysets.lua @@ -145,6 +145,11 @@ return { "altfont"; "nocombine"; }}; + { 'get_highlight', { + "id"; + "name"; + "link"; + }}; -- Autocmds { 'clear_autocmds', { "buffer"; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index a8f5d2e070..201989aee5 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -727,8 +727,8 @@ void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cte ADD_C(args, INTEGER_OBJ(id)); MAXSIZE_TEMP_DICT(rgb, HLATTRS_DICT_SIZE); MAXSIZE_TEMP_DICT(cterm, HLATTRS_DICT_SIZE); - hlattrs2dict(&rgb, rgb_attrs, true); - hlattrs2dict(&cterm, rgb_attrs, false); + hlattrs2dict(&rgb, rgb_attrs, true, false); + hlattrs2dict(&cterm, rgb_attrs, false, false); ADD_C(args, DICTIONARY_OBJ(rgb)); ADD_C(args, DICTIONARY_OBJ(cterm)); @@ -751,7 +751,7 @@ void remote_ui_highlight_set(UI *ui, int id) } data->hl_id = id; MAXSIZE_TEMP_DICT(dict, HLATTRS_DICT_SIZE); - hlattrs2dict(&dict, syn_attr2entry(id), ui->rgb); + hlattrs2dict(&dict, syn_attr2entry(id), ui->rgb, false); ADD_C(args, DICTIONARY_OBJ(dict)); push_call(ui, "highlight_set", args); } @@ -950,7 +950,7 @@ static Array translate_contents(UI *ui, Array contents, Arena *arena) int attr = (int)item.items[0].data.integer; if (attr) { Dictionary rgb_attrs = arena_dict(arena, HLATTRS_DICT_SIZE); - hlattrs2dict(&rgb_attrs, syn_attr2entry(attr), ui->rgb); + hlattrs2dict(&rgb_attrs, syn_attr2entry(attr), ui->rgb, false); ADD(new_item, DICTIONARY_OBJ(rgb_attrs)); } else { ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 4689e6b5bf..ca5dd97020 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -74,42 +74,6 @@ # include "api/vim.c.generated.h" #endif -/// Gets a highlight definition by name. -/// -/// @param name Highlight group name -/// @param rgb Export RGB colors -/// @param[out] err Error details, if any -/// @return Highlight definition map -/// @see nvim_get_hl_by_id -Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *err) - FUNC_API_SINCE(3) -{ - Dictionary result = ARRAY_DICT_INIT; - int id = syn_name2id(name.data); - - VALIDATE_S((id != 0), "highlight name", name.data, { - return result; - }); - return nvim_get_hl_by_id(id, rgb, arena, err); -} - -/// Gets a highlight definition by id. |hlID()| -/// @param hl_id Highlight id as returned by |hlID()| -/// @param rgb Export RGB colors -/// @param[out] err Error details, if any -/// @return Highlight definition map -/// @see nvim_get_hl_by_name -Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *err) - FUNC_API_SINCE(3) -{ - Dictionary dic = ARRAY_DICT_INIT; - VALIDATE_INT((syn_get_final_id((int)hl_id) != 0), "highlight id", hl_id, { - return dic; - }); - int attrcode = syn_id2attr((int)hl_id); - return hl_get_attr_by_id(attrcode, rgb, arena, err); -} - /// Gets a highlight group by name /// /// similar to |hlID()|, but allocates a new ID if not present. @@ -119,12 +83,22 @@ Integer nvim_get_hl_id_by_name(String name) return syn_check_group(name.data, name.size); } -Dictionary nvim__get_hl_defs(Integer ns_id, Arena *arena, Error *err) +/// Gets all or specific highlight groups in a namespace. +/// +/// @param ns_id Get highlight groups for namespace ns_id |nvim_get_namespaces()|. +/// Use 0 to get global highlight groups |:highlight|. +/// @param opts Options dict: +/// - name: (string) Get a highlight definition by name. +/// - id: (integer) Get a highlight definition by id. +/// - link: (boolean, default true) Show linked group name instead of effective definition |:hi-link|. +/// +/// @param[out] err Error details, if any. +/// @return Highlight groups as a map from group name to a highlight definition map as in |nvim_set_hl()|, +/// or only a single highlight definition map if requested by name or id. +Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err) + FUNC_API_SINCE(11) { - if (ns_id == 0) { - return get_global_hl_defs(arena); - } - abort(); + return ns_get_hl_defs((NS)ns_id, opts, arena, err); } /// Sets a highlight group. diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 305e84276c..a97f8f4142 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -821,7 +821,7 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error * return dic; } Dictionary retval = arena_dict(arena, HLATTRS_DICT_SIZE); - hlattrs2dict(&retval, syn_attr2entry((int)attr_id), rgb); + hlattrs2dict(&retval, syn_attr2entry((int)attr_id), rgb, false); return retval; } @@ -830,7 +830,9 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error * /// @param[in/out] hl Dictionary with pre-allocated space for HLATTRS_DICT_SIZE elements /// @param[in] aep data to convert /// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*' -void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb) +/// @param short_keys change (foreground, background, special) to (fg, bg, sp) for 'gui*' settings +/// (foreground, background) to (ctermfg, ctermbg) for 'cterm*' settings +void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb, bool short_keys) { assert(dict->capacity >= HLATTRS_DICT_SIZE); // at most 16 items Dictionary hl = *dict; @@ -887,32 +889,34 @@ void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb) } if (use_rgb) { - if (mask & HL_FG_INDEXED) { - PUT_C(hl, "fg_indexed", BOOLEAN_OBJ(true)); - } - - if (mask & HL_BG_INDEXED) { - PUT_C(hl, "bg_indexed", BOOLEAN_OBJ(true)); - } - if (ae.rgb_fg_color != -1) { - PUT_C(hl, "foreground", INTEGER_OBJ(ae.rgb_fg_color)); + PUT_C(hl, short_keys ? "fg" : "foreground", INTEGER_OBJ(ae.rgb_fg_color)); } if (ae.rgb_bg_color != -1) { - PUT_C(hl, "background", INTEGER_OBJ(ae.rgb_bg_color)); + PUT_C(hl, short_keys ? "bg" : "background", INTEGER_OBJ(ae.rgb_bg_color)); } if (ae.rgb_sp_color != -1) { - PUT_C(hl, "special", INTEGER_OBJ(ae.rgb_sp_color)); + PUT_C(hl, short_keys ? "sp" : "special", INTEGER_OBJ(ae.rgb_sp_color)); + } + + if (!short_keys) { + if (mask & HL_FG_INDEXED) { + PUT_C(hl, "fg_indexed", BOOLEAN_OBJ(true)); + } + + if (mask & HL_BG_INDEXED) { + PUT_C(hl, "bg_indexed", BOOLEAN_OBJ(true)); + } } } else { if (ae.cterm_fg_color != 0) { - PUT_C(hl, "foreground", INTEGER_OBJ(ae.cterm_fg_color - 1)); + PUT_C(hl, short_keys ? "ctermfg" : "foreground", INTEGER_OBJ(ae.cterm_fg_color - 1)); } if (ae.cterm_bg_color != 0) { - PUT_C(hl, "background", INTEGER_OBJ(ae.cterm_bg_color - 1)); + PUT_C(hl, short_keys ? "ctermbg" : "background", INTEGER_OBJ(ae.cterm_bg_color - 1)); } } diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 5d8649b429..96b55b5abb 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -12,6 +12,7 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" @@ -1521,24 +1522,71 @@ static void highlight_list_one(const int id) } } -Dictionary get_global_hl_defs(Arena *arena) +static bool hlgroup2dict(Dictionary *hl, NS ns_id, int hl_id, Arena *arena) { + HlGroup *sgp = &hl_table[hl_id - 1]; + int link = ns_id == 0 ? sgp->sg_link : ns_get_hl(&ns_id, hl_id, true, sgp->sg_set); + if (link == -1) { + return false; + } + HlAttrs attr = + syn_attr2entry(ns_id == 0 ? sgp->sg_attr : ns_get_hl(&ns_id, hl_id, false, sgp->sg_set)); + if (link > 0) { + *hl = arena_dict(arena, 1); + PUT_C(*hl, "link", STRING_OBJ(cstr_as_string(hl_table[link - 1].sg_name))); + } else { + *hl = arena_dict(arena, HLATTRS_DICT_SIZE); + hlattrs2dict(hl, attr, true, true); + hlattrs2dict(hl, attr, false, true); + } + return true; +} + +Dictionary ns_get_hl_defs(NS ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err) +{ + Boolean link = api_object_to_bool(opts->link, "link", true, err); + int id = -1; + if (opts->name.type != kObjectTypeNil) { + VALIDATE_T("highlight name", kObjectTypeString, opts->name.type, { + goto cleanup; + }); + String name = opts->name.data.string; + id = syn_check_group(name.data, name.size); + } else if (opts->id.type != kObjectTypeNil) { + VALIDATE_T("highlight id", kObjectTypeInteger, opts->id.type, { + goto cleanup; + }); + id = (int)opts->id.data.integer; + } + + if (id != -1) { + VALIDATE(1 <= id && id <= highlight_ga.ga_len, "%s", "Highlight id out of bounds", { + goto cleanup; + }); + Dictionary attrs = ARRAY_DICT_INIT; + hlgroup2dict(&attrs, ns_id, link ? id : syn_get_final_id(id), arena); + return attrs; + } + if (ERROR_SET(err)) { + goto cleanup; + } + Dictionary rv = arena_dict(arena, (size_t)highlight_ga.ga_len); for (int i = 1; i <= highlight_ga.ga_len; i++) { Dictionary attrs = ARRAY_DICT_INIT; - HlGroup *h = &hl_table[i - 1]; - if (h->sg_attr > 0) { - attrs = arena_dict(arena, HLATTRS_DICT_SIZE); - hlattrs2dict(&attrs, syn_attr2entry(h->sg_attr), true); - } else if (h->sg_link > 0) { - attrs = arena_dict(arena, 1); - char *link = hl_table[h->sg_link - 1].sg_name; - PUT_C(attrs, "link", STRING_OBJ(cstr_as_string(link))); + if (!hlgroup2dict(&attrs, ns_id, i, arena)) { + continue; } - PUT_C(rv, h->sg_name, DICTIONARY_OBJ(attrs)); + PUT_C(rv, hl_table[(link ? i : syn_get_final_id(i)) - 1].sg_name, DICTIONARY_OBJ(attrs)); } return rv; + +cleanup: + api_free_integer(id); + api_free_boolean(link); + Dictionary empty = ARRAY_DICT_INIT; + return empty; } /// Outputs a highlight when doing ":hi MyHighlight" diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua index eb7d0f7b47..de3eb4e798 100644 --- a/test/functional/api/highlight_spec.lua +++ b/test/functional/api/highlight_spec.lua @@ -369,3 +369,222 @@ describe("API: set highlight", function() assert_alive() end) end) + +describe('API: get highlight', function() + local highlight_color = { + fg = tonumber('0xff0000'), + bg = tonumber('0x0032aa'), + ctermfg = 8, + ctermbg = 15, + } + local highlight1 = { + bg = highlight_color.bg, + fg = highlight_color.fg, + bold = true, + italic = true, + } + local highlight2 = { + ctermbg = highlight_color.ctermbg, + ctermfg = highlight_color.ctermfg, + underline = true, + reverse = true, + } + local highlight3_config = { + bg = highlight_color.bg, + fg = highlight_color.fg, + ctermbg = highlight_color.ctermbg, + ctermfg = highlight_color.ctermfg, + bold = true, + italic = true, + reverse = true, + underdashed = true, + strikethrough = true, + altfont = true, + cterm = { + italic = true, + reverse = true, + strikethrough = true, + altfont = true, + nocombine = true, + }, + } + local highlight3_result = { + bg = highlight_color.bg, + fg = highlight_color.fg, + ctermbg = highlight_color.ctermbg, + ctermfg = highlight_color.ctermfg, + bold = true, + italic = true, + nocombine = true, + reverse = true, + underdashed = true, + strikethrough = true, + altfont = true, + } + + local function get_ns() + -- Test namespace filtering behavior + local ns2 = meths.create_namespace('Another_namespace') + meths.set_hl(ns2, 'Test_hl', { ctermfg = 23 }) + meths.set_hl(ns2, 'Test_another_hl', { link = 'Test_hl' }) + meths.set_hl(ns2, 'Test_hl_link', { link = 'Test_another_hl' }) + meths.set_hl(ns2, 'Test_another_hl_link', { link = 'Test_hl_link' }) + + local ns = meths.create_namespace('Test_set_hl') + meths.set_hl_ns(ns) + + return ns + end + + before_each(clear) + + it('validation', function() + eq( + 'Invalid highlight name: expected String, got Integer', + pcall_err(meths.get_hl, 0, { name = 177 }) + ) + eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { name = 'Test set hl' })) + end) + + it('can get all highlights in current namespace', function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', { bg = '#B4BEFE' }) + meths.set_hl(ns, 'Test_hl_link', { link = 'Test_hl' }) + eq({ + Test_hl = { + bg = 11845374 + }, + Test_hl_link = { + link = 'Test_hl' + } + }, meths.get_hl(ns, {})) + end) + + it('can get gui highlight', function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight1) + eq(highlight1, meths.get_hl(ns, { name = 'Test_hl' })) + end) + + it('can get cterm highlight', function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight2) + eq(highlight2, meths.get_hl(ns, { name = 'Test_hl' })) + end) + + it('can get empty cterm attr', function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', { cterm = {} }) + eq({}, meths.get_hl(ns, { name = 'Test_hl' })) + end) + + it('cterm attr defaults to gui attr', function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight1) + eq(highlight1, meths.get_hl(ns, { name = 'Test_hl' })) + end) + + it('can overwrite attr for cterm', function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', highlight3_config) + eq(highlight3_result, meths.get_hl(ns, { name = 'Test_hl' })) + end) + + it('only allows one underline attribute #22371', function() + local ns = get_ns() + meths.set_hl(ns, 'Test_hl', { + underdouble = true, + underdotted = true, + cterm = { + underline = true, + undercurl = true, + }, + }) + eq({ undercurl = true, underdotted = true }, meths.get_hl(ns, { name = 'Test_hl' })) + end) + + it('can get a highlight in the global namespace', function() + meths.set_hl(0, 'Test_hl', highlight2) + eq(highlight2, meths.get_hl(0, { name = 'Test_hl' })) + + meths.set_hl(0, 'Test_hl', { background = highlight_color.bg }) + eq({ + bg = 12970, + }, meths.get_hl(0, { name = 'Test_hl' })) + + meths.set_hl(0, 'Test_hl2', highlight3_config) + eq(highlight3_result, meths.get_hl(0, { name = 'Test_hl2' })) + + -- Colors are stored with the name they are defined, but + -- with canonical casing + meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' }) + eq({ + bg = 16711680, + fg = 255, + }, meths.get_hl(0, { name = 'Test_hl3' })) + end) + + local expected_rgb = { + altfont = true, + bg = 16776960, + bold = true, + ctermbg = 10, + fg = 16711680, + italic = true, + nocombine = true, + reverse = true, + sp = 255, + strikethrough = true, + underline = true, + } + local expected = { + bg = 16776960, + bold = true, + ctermbg = 10, + fg = 16711680, + sp = 255, + underline = true, + } + local expected_undercurl = { + bg = 16776960, + ctermbg = 10, + fg = 16711680, + sp = 255, + undercurl = true, + underline = true, + } + + it('nvim_get_hl by id', function() + local hl_id = meths.get_hl_id_by_name('NewHighlight') + + command( + 'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold' + ) + eq(expected, meths.get_hl(0, { id = hl_id })) + + -- Test 0 argument + eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { id = 0 })) + + eq( + 'Invalid highlight id: expected Integer, got String', + pcall_err(meths.get_hl, 0, { id = 'Test_set_hl' }) + ) + + -- Test all highlight properties. + command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') + eq(expected_rgb, meths.get_hl(0, { id = hl_id })) + + -- Test undercurl + command('hi NewHighlight gui=undercurl') + eq(expected_undercurl, meths.get_hl(0, { id = hl_id })) + end) + + it('can correctly detect links', function() + command('hi String guifg=#a6e3a1') + command('hi link @string string') + command('hi link @string.cpp @string') + eq({ fg = 10937249 }, meths.get_hl(0, { name = 'String' })) + eq({ link = 'String' }, meths.get_hl(0, { name = '@string' })) + eq({ fg = 10937249 }, meths.get_hl(0, { name = '@string.cpp', link = false })) + end) +end) |