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,
|
a.nvim_buf_set_extmark(buf, ns, start_row, start_col,
|
||||||
{ end_line = end_row, end_col = end_col,
|
{ end_line = end_row, end_col = end_col,
|
||||||
hl_group = hl,
|
hl_group = hl,
|
||||||
ephemeral = true
|
ephemeral = true,
|
||||||
|
priority = 100 -- Low but leaves room below
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
if start_row > line then
|
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, "virt_text", ARRAY_OBJ(chunks));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PUT(dict, "priority", INTEGER_OBJ(decor->priority));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict.size) {
|
if (dict.size) {
|
||||||
@ -1375,6 +1377,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
|
|
||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
int line2 = -1, hl_id = 0;
|
int line2 = -1, hl_id = 0;
|
||||||
|
DecorPriority priority = DECOR_PRIORITY_BASE;
|
||||||
colnr_T col2 = 0;
|
colnr_T col2 = 0;
|
||||||
VirtText virt_text = KV_INITIAL_VALUE;
|
VirtText virt_text = KV_INITIAL_VALUE;
|
||||||
for (size_t i = 0; i < opts.size; i++) {
|
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)) {
|
if (ERROR_SET(err)) {
|
||||||
goto error;
|
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 {
|
} else {
|
||||||
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
|
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
|
||||||
goto error;
|
goto error;
|
||||||
@ -1479,7 +1495,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
*vt_allocated = virt_text;
|
*vt_allocated = virt_text;
|
||||||
}
|
}
|
||||||
decor_add_ephemeral(attr_id, (int)line, (colnr_T)col,
|
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 {
|
} else {
|
||||||
if (ephemeral) {
|
if (ephemeral) {
|
||||||
api_set_error(err, kErrorTypeException, "not yet implemented");
|
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;
|
decor->virt_text = virt_text;
|
||||||
} else if (hl_id) {
|
} else if (hl_id) {
|
||||||
decor = decor_hl(hl_id);
|
decor = decor_hl(hl_id);
|
||||||
|
decor->priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
|
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;
|
colnr_T hl_end = 0;
|
||||||
Decoration *decor = decor_hl(hl_id);
|
Decoration *decor = decor_hl(hl_id);
|
||||||
|
|
||||||
|
decor->priority = DECOR_PRIORITY_BASE;
|
||||||
// TODO(bfredl): if decoration had blocky mode, we could avoid this loop
|
// TODO(bfredl): if decoration had blocky mode, we could avoid this loop
|
||||||
for (linenr_T lnum = pos_start.lnum; lnum <= pos_end.lnum; lnum ++) {
|
for (linenr_T lnum = pos_start.lnum; lnum <= pos_end.lnum; lnum ++) {
|
||||||
int end_off = 0;
|
int end_off = 0;
|
||||||
@ -84,6 +85,7 @@ Decoration *decor_hl(int hl_id)
|
|||||||
Decoration *decor = xcalloc(1, sizeof(*decor));
|
Decoration *decor = xcalloc(1, sizeof(*decor));
|
||||||
decor->hl_id = hl_id;
|
decor->hl_id = hl_id;
|
||||||
decor->shared = true;
|
decor->shared = true;
|
||||||
|
decor->priority = DECOR_PRIORITY_BASE;
|
||||||
*dp = decor;
|
*dp = decor;
|
||||||
return decor;
|
return decor;
|
||||||
}
|
}
|
||||||
@ -191,12 +193,12 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
|
|||||||
HlRange range;
|
HlRange range;
|
||||||
if (mark.id&MARKTREE_END_FLAG) {
|
if (mark.id&MARKTREE_END_FLAG) {
|
||||||
range = (HlRange){ altpos.row, altpos.col, mark.row, mark.col,
|
range = (HlRange){ altpos.row, altpos.col, mark.row, mark.col,
|
||||||
attr_id, vt, false };
|
attr_id, decor->priority, vt, false };
|
||||||
} else {
|
} else {
|
||||||
range = (HlRange){ mark.row, mark.col, altpos.row,
|
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:
|
next_mark:
|
||||||
if (marktree_itr_node_done(state->itr)) {
|
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
|
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)
|
int decor_redraw_col(buf_T *buf, int col, DecorState *state)
|
||||||
{
|
{
|
||||||
if (col <= state->col_until) {
|
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;
|
int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
|
||||||
VirtText *vt = kv_size(decor->virt_text) ? &decor->virt_text : NULL;
|
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,
|
endpos.row, endpos.col,
|
||||||
attr_id, vt, false }));
|
attr_id, decor->priority,
|
||||||
|
vt, false }, state);
|
||||||
|
|
||||||
next_mark:
|
next_mark:
|
||||||
marktree_itr_next(buf->b_marktree, state->itr);
|
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,
|
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_activate(((HlRange){ start_row, start_col, end_row, end_col, attr_id,
|
||||||
((HlRange){ start_row, start_col,
|
priority, virt_text, virt_text != NULL }),
|
||||||
end_row, end_col,
|
&decor_state);
|
||||||
attr_id, virt_text, virt_text != NULL }));
|
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,15 @@ typedef struct {
|
|||||||
typedef kvec_t(VirtTextChunk) VirtText;
|
typedef kvec_t(VirtTextChunk) VirtText;
|
||||||
#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE)
|
#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE)
|
||||||
|
|
||||||
|
typedef uint16_t DecorPriority;
|
||||||
|
#define DECOR_PRIORITY_BASE 0x1000
|
||||||
|
|
||||||
struct Decoration
|
struct Decoration
|
||||||
{
|
{
|
||||||
int hl_id; // highlight group
|
int hl_id; // highlight group
|
||||||
VirtText virt_text;
|
VirtText virt_text;
|
||||||
// TODO(bfredl): style, signs, etc
|
// TODO(bfredl): style, signs, etc
|
||||||
|
DecorPriority priority;
|
||||||
bool shared; // shared decoration, don't free
|
bool shared; // shared decoration, don't free
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -29,6 +33,7 @@ typedef struct {
|
|||||||
int end_row;
|
int end_row;
|
||||||
int end_col;
|
int end_col;
|
||||||
int attr_id;
|
int attr_id;
|
||||||
|
DecorPriority priority;
|
||||||
VirtText *virt_text;
|
VirtText *virt_text;
|
||||||
bool virt_text_owned;
|
bool virt_text_owned;
|
||||||
} HlRange;
|
} HlRange;
|
||||||
|
@ -534,6 +534,62 @@ describe('Buffer highlighting', function()
|
|||||||
]]}
|
]]}
|
||||||
end)
|
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()
|
it('works with multibyte text', function()
|
||||||
insert([[
|
insert([[
|
||||||
Ta båten över sjön!]])
|
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
|
-- TODO: only a virtual text from the same ns curretly overrides
|
||||||
-- an existing virtual text. We might add a prioritation system.
|
-- an existing virtual text. We might add a prioritation system.
|
||||||
set_virtual_text(id1, 0, s1, {})
|
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?
|
-- TODO: is this really valid? shouldn't the max be line_count()-1?
|
||||||
local lastline = line_count()
|
local lastline = line_count()
|
||||||
set_virtual_text(id1, line_count(), s2, {})
|
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}, {}))
|
eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {}))
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user