aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/lua/vim/_meta/api_keysets.lua1
-rw-r--r--src/nvim/api/extmark.c20
-rw-r--r--src/nvim/api/keysets_defs.h2
-rw-r--r--src/nvim/decoration.c19
-rw-r--r--src/nvim/decoration.h2
-rw-r--r--test/functional/api/extmark_spec.lua30
-rw-r--r--test/functional/ui/decorations_spec.lua43
7 files changed, 106 insertions, 11 deletions
diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua
index 00d3ff5bb4..c9ef4e9b4f 100644
--- a/runtime/lua/vim/_meta/api_keysets.lua
+++ b/runtime/lua/vim/_meta/api_keysets.lua
@@ -274,6 +274,7 @@ error('Cannot require a meta file')
--- @field ui_watched? boolean
--- @field undo_restore? boolean
--- @field url? string
+--- @field _subpriority? integer
--- @class vim.api.keyset.user_command
--- @field addr? any
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 27a4b7854f..4e84b41a02 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -748,20 +748,32 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = c;
}
+ DecorPriority subpriority = DECOR_PRIORITY_BASE;
+ if (HAS_KEY(opts, set_extmark, _subpriority)) {
+ VALIDATE_RANGE((opts->_subpriority >= 0 && opts->_subpriority <= UINT16_MAX),
+ "_subpriority", {
+ goto error;
+ });
+ subpriority = (DecorPriority)opts->_subpriority;
+ }
+
if (kv_size(virt_text.data.virt_text)) {
- decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true,
+ subpriority);
}
if (kv_size(virt_lines.data.virt_lines)) {
- decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true,
+ subpriority);
}
if (url != NULL) {
DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
sh.url = url;
- decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0);
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0, subpriority);
}
if (has_hl) {
DecorSignHighlight sh = decor_sh_from_inline(hl);
- decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id);
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id,
+ subpriority);
}
} else {
if (opts->ephemeral) {
diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h
index 811f60f4d6..85896c1fa7 100644
--- a/src/nvim/api/keysets_defs.h
+++ b/src/nvim/api/keysets_defs.h
@@ -55,6 +55,8 @@ typedef struct {
Boolean ui_watched;
Boolean undo_restore;
String url;
+
+ Integer _subpriority;
} Dict(set_extmark);
typedef struct {
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 755655856d..5358241644 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -449,18 +449,21 @@ static void decor_range_add_from_inline(DecorState *state, int start_row, int st
if (decor.ext) {
DecorVirtText *vt = decor.data.ext.vt;
while (vt) {
- decor_range_add_virt(state, start_row, start_col, end_row, end_col, vt, owned);
+ decor_range_add_virt(state, start_row, start_col, end_row, end_col, vt, owned,
+ DECOR_PRIORITY_BASE);
vt = vt->next;
}
uint32_t idx = decor.data.ext.sh_idx;
while (idx != DECOR_ID_INVALID) {
DecorSignHighlight *sh = &kv_A(decor_items, idx);
- decor_range_add_sh(state, start_row, start_col, end_row, end_col, sh, owned, ns, mark_id);
+ decor_range_add_sh(state, start_row, start_col, end_row, end_col, sh, owned, ns, mark_id,
+ DECOR_PRIORITY_BASE);
idx = sh->next;
}
} else {
DecorSignHighlight sh = decor_sh_from_inline(decor.data.hl);
- decor_range_add_sh(state, start_row, start_col, end_row, end_col, &sh, owned, ns, mark_id);
+ decor_range_add_sh(state, start_row, start_col, end_row, end_col, &sh, owned, ns, mark_id,
+ DECOR_PRIORITY_BASE);
}
}
@@ -470,7 +473,8 @@ static void decor_range_insert(DecorState *state, DecorRange range)
size_t index;
for (index = kv_size(state->active) - 1; index > 0; index--) {
DecorRange item = kv_A(state->active, index - 1);
- if (item.priority <= range.priority) {
+ if ((item.priority < range.priority)
+ || ((item.priority == range.priority) && (item.subpriority <= range.subpriority))) {
break;
}
kv_A(state->active, index) = kv_A(state->active, index - 1);
@@ -479,7 +483,7 @@ static void decor_range_insert(DecorState *state, DecorRange range)
}
void decor_range_add_virt(DecorState *state, int start_row, int start_col, int end_row, int end_col,
- DecorVirtText *vt, bool owned)
+ DecorVirtText *vt, bool owned, DecorPriority subpriority)
{
bool is_lines = vt->flags & kVTIsLines;
DecorRange range = {
@@ -489,13 +493,15 @@ void decor_range_add_virt(DecorState *state, int start_row, int start_col, int e
.attr_id = 0,
.owned = owned,
.priority = vt->priority,
+ .subpriority = subpriority,
.draw_col = -10,
};
decor_range_insert(state, range);
}
void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end_row, int end_col,
- DecorSignHighlight *sh, bool owned, uint32_t ns, uint32_t mark_id)
+ DecorSignHighlight *sh, bool owned, uint32_t ns, uint32_t mark_id,
+ DecorPriority subpriority)
{
if (sh->flags & kSHIsSign) {
return;
@@ -508,6 +514,7 @@ void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end
.attr_id = 0,
.owned = owned,
.priority = sh->priority,
+ .subpriority = subpriority,
.draw_col = -10,
};
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index b3ff737123..e70c588806 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -48,6 +48,8 @@ typedef struct {
int attr_id; ///< cached lookup of inl.hl_id if it was a highlight
bool owned; ///< ephemeral decoration, free memory immediately
DecorPriority priority;
+ DecorPriority subpriority; ///< Secondary priority value used for ordering (#27131).
+ ///< Reflects the order of patterns/captures in the query file.
DecorRangeKind kind;
/// Screen column to draw the virtual text.
/// When -1, the virtual text may be drawn after deciding where.
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index 0a286965f2..2acfbfc949 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -1798,6 +1798,36 @@ describe('API/extmarks', function()
eq(1, #extmarks)
eq('https://example.com', extmarks[1][4].url)
end)
+
+ it('respects priority', function()
+ screen = Screen.new(15, 10)
+ screen:attach()
+
+ set_extmark(ns, marks[1], 0, 0, {
+ hl_group = 'Comment',
+ end_col = 2,
+ priority = 20,
+ })
+
+ -- Extmark defined after first extmark but has lower priority, first extmark "wins"
+ set_extmark(ns, marks[2], 0, 0, {
+ hl_group = 'String',
+ end_col = 2,
+ priority = 10,
+ })
+
+ screen:expect {
+ grid = [[
+ {1:12}34^5 |
+ {2:~ }|*8
+ |
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Blue1, bold = true },
+ },
+ }
+ end)
end)
describe('Extmarks buffer api with many marks', function()
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 7b3533454c..cb804f056d 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -687,7 +687,7 @@ describe('decorations providers', function()
]]}
end)
- it('can add new providers during redraw #26652', function()
+ it('can add new providers during redraw #26652', function()
setup_provider [[
local ns = api.nvim_create_namespace('test_no_add')
function on_do(...)
@@ -697,6 +697,47 @@ describe('decorations providers', function()
helpers.assert_alive()
end)
+
+ it('supports subpriorities (order of definitions in a query file #27131)', function()
+ insert(mulholland)
+ setup_provider [[
+ local test_ns = api.nvim_create_namespace('mulholland')
+ function on_do(event, ...)
+ if event == "line" then
+ local win, buf, line = ...
+ api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
+ end_row = line + 1,
+ hl_eol = true,
+ hl_group = 'Comment',
+ ephemeral = true,
+ priority = 100,
+ _subpriority = 20,
+ })
+
+ -- This extmark is set last but has a lower subpriority, so the first extmark "wins"
+ api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
+ end_row = line + 1,
+ hl_eol = true,
+ hl_group = 'String',
+ ephemeral = true,
+ priority = 100,
+ _subpriority = 10,
+ })
+ end
+ end
+ ]]
+
+ screen:expect{grid=[[
+ {4:// just to see if there was an accident }|
+ {4:// on Mulholland Drive }|
+ {4:try_start(); }|
+ {4:bufref_T save_buf; }|
+ {4:switch_buffer(&save_buf, buf); }|
+ {4:posp = getmark(mark, false); }|
+ {4:restore_buffer(&save_buf);^ }|
+ |
+ ]]}
+ end)
end)
local example_text = [[