mirror of
https://github.com/neovim/neovim
synced 2025-07-16 01:01:49 +00:00
feat(extmark): stack multiple highlight groups in hl_group
This has been possible in the "backend" for a while but API was missing. Followup: we will need a `details2=true` mode for `nvim_get_hl_id_by_name` to return information in a way forward compatible with even further enhancements.
This commit is contained in:
@ -2660,6 +2660,8 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
|
|||||||
and below highlight groups can be supplied either as a
|
and below highlight groups can be supplied either as a
|
||||||
string or as an integer, the latter of which can be
|
string or as an integer, the latter of which can be
|
||||||
obtained using |nvim_get_hl_id_by_name()|.
|
obtained using |nvim_get_hl_id_by_name()|.
|
||||||
|
Multiple highlight groups can be stacked by passing an
|
||||||
|
array (highest priority last).
|
||||||
• hl_eol : when true, for a multiline highlight covering the
|
• hl_eol : when true, for a multiline highlight covering the
|
||||||
EOL of a line, continue the highlight for the rest of the
|
EOL of a line, continue the highlight for the rest of the
|
||||||
screen line (just like for diff and cursorline highlight).
|
screen line (just like for diff and cursorline highlight).
|
||||||
|
@ -188,6 +188,7 @@ API
|
|||||||
• |nvim_echo()| `err` field to print error messages and `chunks` accepts
|
• |nvim_echo()| `err` field to print error messages and `chunks` accepts
|
||||||
highlight group IDs.
|
highlight group IDs.
|
||||||
• |nvim_open_win()| `relative` field can be set to "laststatus" and "tabline".
|
• |nvim_open_win()| `relative` field can be set to "laststatus" and "tabline".
|
||||||
|
• |nvim_buf_set_extmark()| `hl_group` field can be an array of layered groups
|
||||||
|
|
||||||
DEFAULTS
|
DEFAULTS
|
||||||
|
|
||||||
|
3
runtime/lua/vim/_meta/api.lua
generated
3
runtime/lua/vim/_meta/api.lua
generated
@ -595,6 +595,9 @@ function vim.api.nvim_buf_line_count(buffer) end
|
|||||||
--- - hl_group : highlight group used for the text range. This and below
|
--- - hl_group : highlight group used for the text range. This and below
|
||||||
--- highlight groups can be supplied either as a string or as an integer,
|
--- highlight groups can be supplied either as a string or as an integer,
|
||||||
--- the latter of which can be obtained using `nvim_get_hl_id_by_name()`.
|
--- the latter of which can be obtained using `nvim_get_hl_id_by_name()`.
|
||||||
|
---
|
||||||
|
--- Multiple highlight groups can be stacked by passing an array (highest
|
||||||
|
--- priority last).
|
||||||
--- - hl_eol : when true, for a multiline highlight covering the
|
--- - hl_eol : when true, for a multiline highlight covering the
|
||||||
--- EOL of a line, continue the highlight for the rest
|
--- EOL of a line, continue the highlight for the rest
|
||||||
--- of the screen line (just like for diff and
|
--- of the screen line (just like for diff and
|
||||||
|
2
runtime/lua/vim/_meta/api_keysets.lua
generated
2
runtime/lua/vim/_meta/api_keysets.lua
generated
@ -241,7 +241,7 @@ error('Cannot require a meta file')
|
|||||||
--- @field end_line? integer
|
--- @field end_line? integer
|
||||||
--- @field end_row? integer
|
--- @field end_row? integer
|
||||||
--- @field end_col? integer
|
--- @field end_col? integer
|
||||||
--- @field hl_group? integer|string
|
--- @field hl_group? any
|
||||||
--- @field virt_text? any[]
|
--- @field virt_text? any[]
|
||||||
--- @field virt_text_pos? string
|
--- @field virt_text_pos? string
|
||||||
--- @field virt_text_win_col? integer
|
--- @field virt_text_win_col? integer
|
||||||
|
@ -385,6 +385,9 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
|
|||||||
/// - hl_group : highlight group used for the text range. This and below
|
/// - hl_group : highlight group used for the text range. This and below
|
||||||
/// highlight groups can be supplied either as a string or as an integer,
|
/// highlight groups can be supplied either as a string or as an integer,
|
||||||
/// the latter of which can be obtained using |nvim_get_hl_id_by_name()|.
|
/// the latter of which can be obtained using |nvim_get_hl_id_by_name()|.
|
||||||
|
///
|
||||||
|
/// Multiple highlight groups can be stacked by passing an array (highest
|
||||||
|
/// priority last).
|
||||||
/// - hl_eol : when true, for a multiline highlight covering the
|
/// - hl_eol : when true, for a multiline highlight covering the
|
||||||
/// EOL of a line, continue the highlight for the rest
|
/// EOL of a line, continue the highlight for the rest
|
||||||
/// of the screen line (just like for diff and
|
/// of the screen line (just like for diff and
|
||||||
@ -499,6 +502,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
|||||||
DecorVirtText virt_lines = DECOR_VIRT_LINES_INIT;
|
DecorVirtText virt_lines = DECOR_VIRT_LINES_INIT;
|
||||||
char *url = NULL;
|
char *url = NULL;
|
||||||
bool has_hl = false;
|
bool has_hl = false;
|
||||||
|
bool has_hl_multiple = false;
|
||||||
|
|
||||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
@ -551,8 +555,33 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
|||||||
col2 = (int)val;
|
col2 = (int)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
hl.hl_id = (int)opts->hl_group;
|
if (HAS_KEY(opts, set_extmark, hl_group)) {
|
||||||
has_hl = hl.hl_id > 0;
|
if (opts->hl_group.type == kObjectTypeArray) {
|
||||||
|
Array arr = opts->hl_group.data.array;
|
||||||
|
if (arr.size >= 1) {
|
||||||
|
hl.hl_id = object_to_hl_id(arr.items[0], "hl_group item", err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 1; i < arr.size; i++) {
|
||||||
|
int hl_id = object_to_hl_id(arr.items[i], "hl_group item", err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (hl_id) {
|
||||||
|
has_hl_multiple = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hl.hl_id = object_to_hl_id(opts->hl_group, "hl_group", err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
has_hl = hl.hl_id > 0;
|
||||||
|
}
|
||||||
|
|
||||||
sign.hl_id = (int)opts->sign_hl_group;
|
sign.hl_id = (int)opts->sign_hl_group;
|
||||||
sign.cursorline_hl_id = (int)opts->cursorline_hl_group;
|
sign.cursorline_hl_id = (int)opts->cursorline_hl_group;
|
||||||
sign.number_hl_id = (int)opts->number_hl_group;
|
sign.number_hl_id = (int)opts->number_hl_group;
|
||||||
@ -794,6 +823,21 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_hl_multiple) {
|
||||||
|
Array arr = opts->hl_group.data.array;
|
||||||
|
for (size_t i = arr.size - 1; i > 0; i--) { // skip hl_group[0], handled as hl.hl_id below
|
||||||
|
int hl_id = object_to_hl_id(arr.items[i], "hl_group item", err);
|
||||||
|
if (hl_id > 0) {
|
||||||
|
DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
|
||||||
|
sh.hl_id = hl_id;
|
||||||
|
sh.flags = opts->hl_eol ? kSHHlEol : 0;
|
||||||
|
sh.next = decor_indexed;
|
||||||
|
decor_indexed = decor_put_sh(sh);
|
||||||
|
decor_flags |= MT_FLAG_DECOR_HL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DecorInline decor = DECOR_INLINE_INIT;
|
DecorInline decor = DECOR_INLINE_INIT;
|
||||||
if (decor_alloc || decor_indexed != DECOR_ID_INVALID || url != NULL
|
if (decor_alloc || decor_indexed != DECOR_ID_INVALID || url != NULL
|
||||||
|| schar_high(hl.conceal_char)) {
|
|| schar_high(hl.conceal_char)) {
|
||||||
|
@ -29,7 +29,7 @@ typedef struct {
|
|||||||
Integer end_line;
|
Integer end_line;
|
||||||
Integer end_row;
|
Integer end_row;
|
||||||
Integer end_col;
|
Integer end_col;
|
||||||
HLGroupID hl_group;
|
Object hl_group;
|
||||||
Array virt_text;
|
Array virt_text;
|
||||||
String virt_text_pos;
|
String virt_text_pos;
|
||||||
Integer virt_text_win_col;
|
Integer virt_text_win_col;
|
||||||
|
@ -834,6 +834,9 @@ describe('extmark decorations', function()
|
|||||||
[42] = {undercurl = true, special = Screen.colors.Red};
|
[42] = {undercurl = true, special = Screen.colors.Red};
|
||||||
[43] = {background = Screen.colors.Yellow, undercurl = true, special = Screen.colors.Red};
|
[43] = {background = Screen.colors.Yellow, undercurl = true, special = Screen.colors.Red};
|
||||||
[44] = {background = Screen.colors.LightMagenta};
|
[44] = {background = Screen.colors.LightMagenta};
|
||||||
|
[45] = { background = Screen.colors.Red, special = Screen.colors.Red, foreground = Screen.colors.Red };
|
||||||
|
[46] = { background = Screen.colors.Blue, foreground = Screen.colors.Blue, special = Screen.colors.Red };
|
||||||
|
[47] = { background = Screen.colors.Green, foreground = Screen.colors.Blue, special = Screen.colors.Red };
|
||||||
}
|
}
|
||||||
|
|
||||||
ns = api.nvim_create_namespace 'test'
|
ns = api.nvim_create_namespace 'test'
|
||||||
@ -1924,6 +1927,46 @@ describe('extmark decorations', function()
|
|||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('highlight can combine multiple groups', function()
|
||||||
|
screen:try_resize(50, 3)
|
||||||
|
command('hi Group1 guibg=Red guifg=Red guisp=Red')
|
||||||
|
command('hi Group2 guibg=Blue guifg=Blue')
|
||||||
|
command('hi Group3 guibg=Green')
|
||||||
|
insert([[example text]])
|
||||||
|
api.nvim_buf_set_extmark(0, ns, 0, 0, { end_row=1, hl_group = {} })
|
||||||
|
screen:expect([[
|
||||||
|
example tex^t |
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
||||||
|
api.nvim_buf_set_extmark(0, ns, 0, 0, { end_row=1, hl_group = {'Group1'} })
|
||||||
|
screen:expect([[
|
||||||
|
{45:example tex^t} |
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
||||||
|
api.nvim_buf_set_extmark(0, ns, 0, 0, { end_row = 1, hl_group = {'Group1', 'Group2'} })
|
||||||
|
screen:expect([[
|
||||||
|
{46:example tex^t} |
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
||||||
|
api.nvim_buf_set_extmark(0, ns, 0, 0, { end_row = 1, hl_group = {'Group1', 'Group2', 'Group3'}, hl_eol=true })
|
||||||
|
screen:expect([[
|
||||||
|
{47:example tex^t }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
eq('Invalid hl_group: hl_group item',
|
||||||
|
pcall_err(api.nvim_buf_set_extmark, 0, ns, 0, 0, { end_row = 1, hl_group = {'Group1', 'Group2', {'fail'}}, hl_eol=true }))
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
it('highlight works after TAB with sidescroll #14201', function()
|
it('highlight works after TAB with sidescroll #14201', function()
|
||||||
screen:try_resize(50, 3)
|
screen:try_resize(50, 3)
|
||||||
command('set nowrap')
|
command('set nowrap')
|
||||||
|
Reference in New Issue
Block a user