fix(api): expose fg_indexed/bg_indexed in nvim_get_hl (#39240)

Problem: fg_indexed/bg_indexed were dropped from nvim_get_hl output due
to a wrong short_keys guard. HL_FG_INDEXED also wasn't cleared in
hl_blend_attrs, and HLATTRS_DICT_SIZE was too small.

Solution: Remove the short_keys guard, clear HL_FG_INDEXED in
hl_blend_attrs, bump HLATTRS_DICT_SIZE to 24, and clarify docs that
these flags mean rgb is an approximation of the cterm palette index.

(cherry picked from commit 01861c2f95)

Co-authored-by: glepnir <glephunter@gmail.com>
This commit is contained in:
Justin M. Keyes
2026-04-20 05:46:55 -04:00
committed by GitHub
parent 5153006747
commit eaa8cff0bd
7 changed files with 50 additions and 24 deletions
+5 -4
View File
@@ -1555,8 +1555,9 @@ nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()*
accepts the following keys:
• altfont: boolean
• bg: color name or "#RRGGBB", see note.
• bg_indexed: boolean (default false) If true, bg is a
terminal palette index (0-255).
• bg_indexed: boolean. If true, `bg` is an RGB approximation
of `ctermbg` (a palette index). UIs rendering cterm
natively may prefer `ctermbg`.
• blend: integer between 0 and 100
• blink: boolean
• bold: boolean
@@ -1571,8 +1572,8 @@ nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()*
|:hi-default|
• dim: boolean
• fg: Color name or "#RRGGBB", see note.
• fg_indexed: boolean (default false) If true, fg is a
terminal palette index (0-255).
• fg_indexed: boolean. Same as `bg_indexed`, for `fg` and
`ctermfg`.
• force: boolean (default false) Update the highlight group
even if it already exists.
• italic: boolean
+3 -2
View File
@@ -2225,7 +2225,8 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end
--- @param val vim.api.keyset.highlight Highlight definition map, accepts the following keys:
--- - altfont: boolean
--- - bg: color name or "#RRGGBB", see note.
--- - bg_indexed: boolean (default false) If true, bg is a terminal palette index (0-255).
--- - bg_indexed: boolean. If true, `bg` is an RGB approximation of `ctermbg`
--- (a palette index). UIs rendering cterm natively may prefer `ctermbg`.
--- - blend: integer between 0 and 100
--- - blink: boolean
--- - bold: boolean
@@ -2237,7 +2238,7 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end
--- - default: boolean Don't override existing definition `:hi-default`
--- - dim: boolean
--- - fg: Color name or "#RRGGBB", see note.
--- - fg_indexed: boolean (default false) If true, fg is a terminal palette index (0-255).
--- - fg_indexed: boolean. Same as `bg_indexed`, for `fg` and `ctermfg`.
--- - force: boolean (default false) Update the highlight group even if it already exists.
--- - italic: boolean
--- - link: Name of highlight group to link to. `:hi-link`
+7 -5
View File
@@ -152,13 +152,15 @@ error('Cannot require a meta file')
--- @field background? integer
--- @class vim.api.keyset.get_hl_info : vim.api.keyset.hl_info.base
--- @field fg? integer
--- @field bg? integer
--- @field sp? integer
--- @field default? true
--- @field link? string
--- @field blend? integer
--- @field bg? integer
--- @field bg_indexed? boolean
--- @field cterm? vim.api.keyset.hl_info.cterm
--- @field default? true
--- @field fg? integer
--- @field fg_indexed? boolean
--- @field link? string
--- @field sp? integer
--- @class vim.api.keyset.set_hl_info : vim.api.keyset.hl_info.base
--- @field fg? integer|string
+3 -2
View File
@@ -139,7 +139,8 @@ DictAs(get_hl_info) nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena
/// @param val Highlight definition map, accepts the following keys:
/// - altfont: boolean
/// - bg: color name or "#RRGGBB", see note.
/// - bg_indexed: boolean (default false) If true, bg is a terminal palette index (0-255).
/// - bg_indexed: boolean. If true, `bg` is an RGB approximation of `ctermbg`
/// (a palette index). UIs rendering cterm natively may prefer `ctermbg`.
/// - blend: integer between 0 and 100
/// - blink: boolean
/// - bold: boolean
@@ -151,7 +152,7 @@ DictAs(get_hl_info) nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena
/// - default: boolean Don't override existing definition |:hi-default|
/// - dim: boolean
/// - fg: Color name or "#RRGGBB", see note.
/// - fg_indexed: boolean (default false) If true, fg is a terminal palette index (0-255).
/// - fg_indexed: boolean. Same as `bg_indexed`, for `fg` and `ctermfg`.
/// - force: boolean (default false) Update the highlight group even if it already exists.
/// - italic: boolean
/// - link: Name of highlight group to link to. |:hi-link|
+8 -10
View File
@@ -757,7 +757,7 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
cattrs.rgb_sp_color = -1;
}
cattrs.rgb_ae_attr &= ~HL_BG_INDEXED;
cattrs.rgb_ae_attr &= ~(HL_FG_INDEXED | HL_BG_INDEXED);
}
// Check if we should preserve background transparency
@@ -916,8 +916,8 @@ Dict hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error *err)
void hlattrs2dict(Dict *hl, Dict *hl_attrs, HlAttrs ae, bool use_rgb, bool short_keys)
{
hl_attrs = hl_attrs ? hl_attrs : hl;
assert(hl->capacity >= HLATTRS_DICT_SIZE); // at most 16 items
assert(hl_attrs->capacity >= HLATTRS_DICT_SIZE); // at most 16 items
assert(hl->capacity >= HLATTRS_DICT_SIZE); // at most 24 items
assert(hl_attrs->capacity >= HLATTRS_DICT_SIZE); // at most 24 items
int mask = use_rgb ? ae.rgb_ae_attr : ae.cterm_ae_attr;
if (mask & HL_INVERSE) {
@@ -999,14 +999,12 @@ void hlattrs2dict(Dict *hl, Dict *hl_attrs, HlAttrs ae, bool use_rgb, bool short
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_FG_INDEXED) {
PUT_C(*hl, "fg_indexed", BOOLEAN_OBJ(true));
}
if (mask & HL_BG_INDEXED) {
PUT_C(*hl, "bg_indexed", BOOLEAN_OBJ(true));
}
if (mask & HL_BG_INDEXED) {
PUT_C(*hl, "bg_indexed", BOOLEAN_OBJ(true));
}
} else {
if (ae.cterm_fg_color != 0) {
+1 -1
View File
@@ -179,4 +179,4 @@ typedef struct {
#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1, \
.is_default = false, .link_global = false }
enum { HLATTRS_DICT_SIZE = 20, };
enum { HLATTRS_DICT_SIZE = 24, };
+23
View File
@@ -679,6 +679,29 @@ describe('API: get highlight', function()
api.nvim_set_hl(0, 'Bar', { link = 'Foo', default = true, force = true })
eq({ link = 'Foo', default = true }, api.nvim_get_hl(0, { name = 'Bar' }))
end)
it('round-trips fg_indexed/bg_indexed through nvim_get_hl', function()
api.nvim_set_hl(0, 'Test_idx', {
fg = '#cc0000',
bg = '#0000cc',
ctermfg = 1,
ctermbg = 4,
fg_indexed = true,
bg_indexed = true,
})
local hl = api.nvim_get_hl(0, { name = 'Test_idx' })
eq(true, hl.fg_indexed)
eq(true, hl.bg_indexed)
eq(tonumber('0xcc0000'), hl.fg)
eq(tonumber('0x0000cc'), hl.bg)
eq(1, hl.ctermfg)
eq(4, hl.ctermbg)
api.nvim_set_hl(0, 'Test_idx', { fg_indexed = false, update = true })
eq(nil, api.nvim_get_hl(0, { name = 'Test_idx' }).fg_indexed)
eq(true, api.nvim_get_hl(0, { name = 'Test_idx' }).bg_indexed)
eq(tonumber('0xcc0000'), api.nvim_get_hl(0, { name = 'Test_idx' }).fg)
end)
end)
describe('API: set/get highlight namespace', function()