mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
feat(luahl): add priority mechanism
Base priority is 0x1000, in order to stay kinda backward compatible. Also set tree-sitter default highlight to 100 (middle-ish value)
This commit is contained in:
parent
43ec616414
commit
c0a6989d93
@ -219,7 +219,8 @@ local function on_line_impl(self, buf, line)
|
||||
a.nvim_buf_set_extmark(buf, ns, start_row, start_col,
|
||||
{ end_line = end_row, end_col = end_col,
|
||||
hl_group = hl,
|
||||
ephemeral = true
|
||||
ephemeral = true,
|
||||
priority = 100 -- Low but leaves room below
|
||||
})
|
||||
end
|
||||
if start_row > line then
|
||||
|
@ -1122,6 +1122,8 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict)
|
||||
}
|
||||
PUT(dict, "virt_text", ARRAY_OBJ(chunks));
|
||||
}
|
||||
|
||||
PUT(dict, "priority", INTEGER_OBJ(decor->priority));
|
||||
}
|
||||
|
||||
if (dict.size) {
|
||||
@ -1375,6 +1377,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
|
||||
uint64_t id = 0;
|
||||
int line2 = -1, hl_id = 0;
|
||||
DecorPriority priority = DECOR_PRIORITY_BASE;
|
||||
colnr_T col2 = 0;
|
||||
VirtText virt_text = KV_INITIAL_VALUE;
|
||||
for (size_t i = 0; i < opts.size; i++) {
|
||||
@ -1446,6 +1449,19 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
if (ERROR_SET(err)) {
|
||||
goto error;
|
||||
}
|
||||
} else if (strequal("priority", k.data)) {
|
||||
if (v->type != kObjectTypeInteger) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"priority is not a Number of the correct size");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (v->data.integer < 0 || v->data.integer > UINT16_MAX) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"priority is not a valid value");
|
||||
goto error;
|
||||
}
|
||||
priority = (DecorPriority)v->data.integer;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
|
||||
goto error;
|
||||
@ -1479,7 +1495,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
*vt_allocated = virt_text;
|
||||
}
|
||||
decor_add_ephemeral(attr_id, (int)line, (colnr_T)col,
|
||||
(int)line2, (colnr_T)col2, vt_allocated);
|
||||
(int)line2, (colnr_T)col2, priority, vt_allocated);
|
||||
} else {
|
||||
if (ephemeral) {
|
||||
api_set_error(err, kErrorTypeException, "not yet implemented");
|
||||
@ -1492,6 +1508,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
decor->virt_text = virt_text;
|
||||
} else if (hl_id) {
|
||||
decor = decor_hl(hl_id);
|
||||
decor->priority = priority;
|
||||
}
|
||||
|
||||
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
|
||||
|
@ -43,6 +43,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf,
|
||||
colnr_T hl_end = 0;
|
||||
Decoration *decor = decor_hl(hl_id);
|
||||
|
||||
decor->priority = DECOR_PRIORITY_BASE;
|
||||
// TODO(bfredl): if decoration had blocky mode, we could avoid this loop
|
||||
for (linenr_T lnum = pos_start.lnum; lnum <= pos_end.lnum; lnum ++) {
|
||||
int end_off = 0;
|
||||
@ -84,6 +85,7 @@ Decoration *decor_hl(int hl_id)
|
||||
Decoration *decor = xcalloc(1, sizeof(*decor));
|
||||
decor->hl_id = hl_id;
|
||||
decor->shared = true;
|
||||
decor->priority = DECOR_PRIORITY_BASE;
|
||||
*dp = decor;
|
||||
return decor;
|
||||
}
|
||||
@ -191,12 +193,12 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
|
||||
HlRange range;
|
||||
if (mark.id&MARKTREE_END_FLAG) {
|
||||
range = (HlRange){ altpos.row, altpos.col, mark.row, mark.col,
|
||||
attr_id, vt, false };
|
||||
attr_id, decor->priority, vt, false };
|
||||
} else {
|
||||
range = (HlRange){ mark.row, mark.col, altpos.row,
|
||||
altpos.col, attr_id, vt, false };
|
||||
altpos.col, attr_id, decor->priority, vt, false };
|
||||
}
|
||||
kv_push(state->active, range);
|
||||
hlrange_activate(range, state);
|
||||
|
||||
next_mark:
|
||||
if (marktree_itr_node_done(state->itr)) {
|
||||
@ -218,6 +220,34 @@ bool decor_redraw_line(buf_T *buf, int row, DecorState *state)
|
||||
return true; // TODO(bfredl): be more precise
|
||||
}
|
||||
|
||||
static void hlrange_activate(HlRange range, DecorState *state)
|
||||
{
|
||||
// Get size before preparing the push, to have the number of elements
|
||||
size_t s = kv_size(state->active);
|
||||
|
||||
kv_pushp(state->active);
|
||||
|
||||
size_t dest_index = 0;
|
||||
|
||||
// Determine insertion dest_index
|
||||
while (dest_index < s) {
|
||||
HlRange item = kv_A(state->active, dest_index);
|
||||
if (item.priority > range.priority) {
|
||||
break;
|
||||
}
|
||||
|
||||
dest_index++;
|
||||
}
|
||||
|
||||
// Splice
|
||||
for (size_t index = s; index > dest_index; index--) {
|
||||
kv_A(state->active, index) = kv_A(state->active, index-1);
|
||||
}
|
||||
|
||||
// Insert
|
||||
kv_A(state->active, dest_index) = range;
|
||||
}
|
||||
|
||||
int decor_redraw_col(buf_T *buf, int col, DecorState *state)
|
||||
{
|
||||
if (col <= state->col_until) {
|
||||
@ -257,9 +287,10 @@ int decor_redraw_col(buf_T *buf, int col, DecorState *state)
|
||||
|
||||
int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
|
||||
VirtText *vt = kv_size(decor->virt_text) ? &decor->virt_text : NULL;
|
||||
kv_push(state->active, ((HlRange){ mark.row, mark.col,
|
||||
hlrange_activate((HlRange){ mark.row, mark.col,
|
||||
endpos.row, endpos.col,
|
||||
attr_id, vt, false }));
|
||||
attr_id, decor->priority,
|
||||
vt, false }, state);
|
||||
|
||||
next_mark:
|
||||
marktree_itr_next(buf->b_marktree, state->itr);
|
||||
@ -321,10 +352,10 @@ VirtText *decor_redraw_virt_text(buf_T *buf, DecorState *state)
|
||||
}
|
||||
|
||||
void decor_add_ephemeral(int attr_id, int start_row, int start_col,
|
||||
int end_row, int end_col, VirtText *virt_text)
|
||||
int end_row, int end_col, DecorPriority priority,
|
||||
VirtText *virt_text)
|
||||
{
|
||||
kv_push(decor_state.active,
|
||||
((HlRange){ start_row, start_col,
|
||||
end_row, end_col,
|
||||
attr_id, virt_text, virt_text != NULL }));
|
||||
hlrange_activate(((HlRange){ start_row, start_col, end_row, end_col, attr_id,
|
||||
priority, virt_text, virt_text != NULL }),
|
||||
&decor_state);
|
||||
}
|
||||
|
@ -15,11 +15,15 @@ typedef struct {
|
||||
typedef kvec_t(VirtTextChunk) VirtText;
|
||||
#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE)
|
||||
|
||||
typedef uint16_t DecorPriority;
|
||||
#define DECOR_PRIORITY_BASE 0x1000
|
||||
|
||||
struct Decoration
|
||||
{
|
||||
int hl_id; // highlight group
|
||||
VirtText virt_text;
|
||||
// TODO(bfredl): style, signs, etc
|
||||
DecorPriority priority;
|
||||
bool shared; // shared decoration, don't free
|
||||
};
|
||||
|
||||
@ -29,6 +33,7 @@ typedef struct {
|
||||
int end_row;
|
||||
int end_col;
|
||||
int attr_id;
|
||||
DecorPriority priority;
|
||||
VirtText *virt_text;
|
||||
bool virt_text_owned;
|
||||
} HlRange;
|
||||
|
@ -534,6 +534,62 @@ describe('Buffer highlighting', function()
|
||||
]]}
|
||||
end)
|
||||
|
||||
it('respects priority', function()
|
||||
local set_extmark = curbufmeths.set_extmark
|
||||
local id = meths.create_namespace('')
|
||||
insert [[foobar]]
|
||||
|
||||
set_extmark(id, 0, 0, {
|
||||
end_line = 0,
|
||||
end_col = 5,
|
||||
hl_group = "Statement",
|
||||
priority = 100
|
||||
})
|
||||
set_extmark(id, 0, 0, {
|
||||
end_line = 0,
|
||||
end_col = 6,
|
||||
hl_group = "String",
|
||||
priority = 1
|
||||
})
|
||||
|
||||
screen:expect [[
|
||||
{3:fooba}{2:^r} |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]
|
||||
|
||||
clear_namespace(id, 0, -1)
|
||||
|
||||
set_extmark(id, 0, 0, {
|
||||
end_line = 0,
|
||||
end_col = 6,
|
||||
hl_group = "String",
|
||||
priority = 1
|
||||
})
|
||||
set_extmark(id, 0, 0, {
|
||||
end_line = 0,
|
||||
end_col = 5,
|
||||
hl_group = "Statement",
|
||||
priority = 100
|
||||
})
|
||||
|
||||
screen:expect [[
|
||||
{3:fooba}{2:^r} |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]
|
||||
end)
|
||||
|
||||
it('works with multibyte text', function()
|
||||
insert([[
|
||||
Ta båten över sjön!]])
|
||||
@ -699,12 +755,12 @@ describe('Buffer highlighting', function()
|
||||
-- TODO: only a virtual text from the same ns curretly overrides
|
||||
-- an existing virtual text. We might add a prioritation system.
|
||||
set_virtual_text(id1, 0, s1, {})
|
||||
eq({{1, 0, 0, {virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
|
||||
eq({{1, 0, 0, { priority = 0, virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
|
||||
|
||||
-- TODO: is this really valid? shouldn't the max be line_count()-1?
|
||||
local lastline = line_count()
|
||||
set_virtual_text(id1, line_count(), s2, {})
|
||||
eq({{3, lastline, 0, {virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
|
||||
eq({{3, lastline, 0, { priority = 0, virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
|
||||
|
||||
eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {}))
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user