aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2025-01-21 12:32:20 +0100
committerGitHub <noreply@github.com>2025-01-21 12:32:20 +0100
commitd7aba51d39c7409ef388ed7cffe3e31d9fcec163 (patch)
tree0f0dd5c20e65568e013c4d838ea83d5d660b873d
parent05435bf10585e7f850ff44acd63446fbcc56bfe5 (diff)
parent4cced601c8cdfd6253266b035667dd0383a07ebe (diff)
downloadrneovim-d7aba51d39c7409ef388ed7cffe3e31d9fcec163.tar.gz
rneovim-d7aba51d39c7409ef388ed7cffe3e31d9fcec163.tar.bz2
rneovim-d7aba51d39c7409ef388ed7cffe3e31d9fcec163.zip
Merge pull request #32098 from bfredl/multihl_group
feat(extmark): stack multiple highlight groups in `hl_group`
-rw-r--r--runtime/doc/api.txt2
-rw-r--r--runtime/doc/news.txt1
-rw-r--r--runtime/lua/vim/_meta/api.lua3
-rw-r--r--runtime/lua/vim/_meta/api_keysets.lua2
-rw-r--r--src/nvim/api/extmark.c48
-rw-r--r--src/nvim/api/keysets_defs.h2
-rw-r--r--test/functional/ui/decorations_spec.lua43
7 files changed, 97 insertions, 4 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 5163f24ac8..b452db9f3e 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -2593,6 +2593,8 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
and below 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()|.
+ Multiple highlight groups can be stacked by passing an
+ array (highest priority last).
• hl_eol : when true, for a multiline highlight covering the
EOL of a line, continue the highlight for the rest of the
screen line (just like for diff and cursorline highlight).
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 58dab586d9..0d5fa3ca18 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -193,6 +193,7 @@ API
• |nvim_echo()| `err` field to print error messages and `chunks` accepts
highlight group IDs.
• |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
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index 4168d5b857..2f9ab5b846 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -574,6 +574,9 @@ function vim.api.nvim_buf_line_count(buffer) end
--- - 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,
--- 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
--- EOL of a line, continue the highlight for the rest
--- of the screen line (just like for diff and
diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua
index 98e916115e..26c2c963de 100644
--- a/runtime/lua/vim/_meta/api_keysets.lua
+++ b/runtime/lua/vim/_meta/api_keysets.lua
@@ -241,7 +241,7 @@ error('Cannot require a meta file')
--- @field end_line? integer
--- @field end_row? integer
--- @field end_col? integer
---- @field hl_group? integer|string
+--- @field hl_group? any
--- @field virt_text? any[]
--- @field virt_text_pos? string
--- @field virt_text_win_col? integer
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index aa07bf39b3..e66140da5a 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -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
/// 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()|.
+///
+/// Multiple highlight groups can be stacked by passing an array (highest
+/// priority last).
/// - hl_eol : when true, for a multiline highlight covering the
/// EOL of a line, continue the highlight for the rest
/// 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;
char *url = NULL;
bool has_hl = false;
+ bool has_hl_multiple = false;
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@@ -551,8 +555,33 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = (int)val;
}
- hl.hl_id = (int)opts->hl_group;
- has_hl = hl.hl_id > 0;
+ if (HAS_KEY(opts, set_extmark, hl_group)) {
+ 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.cursorline_hl_id = (int)opts->cursorline_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;
if (decor_alloc || decor_indexed != DECOR_ID_INVALID || url != NULL
|| schar_high(hl.conceal_char)) {
diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h
index 664406ab6e..953e467f1e 100644
--- a/src/nvim/api/keysets_defs.h
+++ b/src/nvim/api/keysets_defs.h
@@ -29,7 +29,7 @@ typedef struct {
Integer end_line;
Integer end_row;
Integer end_col;
- HLGroupID hl_group;
+ Object hl_group;
Array virt_text;
String virt_text_pos;
Integer virt_text_win_col;
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index e364c473b7..c2030b9527 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -834,6 +834,9 @@ describe('extmark decorations', function()
[42] = {undercurl = true, special = Screen.colors.Red};
[43] = {background = Screen.colors.Yellow, undercurl = true, special = Screen.colors.Red};
[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'
@@ -1924,6 +1927,46 @@ describe('extmark decorations', function()
]]}
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()
screen:try_resize(50, 3)
command('set nowrap')