feat(decorations): allow more than one stacked highlight in a virt_text
This commit is contained in:
parent
98c4b2cf62
commit
1495d36d63
|
@ -1433,8 +1433,14 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
|
||||||
/// - hl_group : name of the highlight group used to highlight
|
/// - hl_group : name of the highlight group used to highlight
|
||||||
/// this mark.
|
/// this mark.
|
||||||
/// - virt_text : virtual text to link to this mark.
|
/// - virt_text : virtual text to link to this mark.
|
||||||
/// - virt_text_pos : positioning of virtual text. Possible
|
/// A list of [text, highlight] tuples, each representing a
|
||||||
/// values:
|
/// text chunk with specified highlight. `highlight` element
|
||||||
|
/// can either be a a single highlight group, or an array of
|
||||||
|
/// multiple highlight groups that will be stacked
|
||||||
|
/// (highest priority last). A highlight group can be supplied
|
||||||
|
/// either as a string or as an integer, the latter which
|
||||||
|
/// can be obtained using |nvim_get_hl_id_by_name|.
|
||||||
|
/// - virt_text_pos : position of virtual text. Possible values:
|
||||||
/// - "eol": right after eol character (default)
|
/// - "eol": right after eol character (default)
|
||||||
/// - "overlay": display over the specified column, without
|
/// - "overlay": display over the specified column, without
|
||||||
/// shifting the underlying text.
|
/// shifting the underlying text.
|
||||||
|
|
|
@ -1603,22 +1603,38 @@ VirtText parse_virt_text(Array chunks, Error *err)
|
||||||
Array chunk = chunks.items[i].data.array;
|
Array chunk = chunks.items[i].data.array;
|
||||||
if (chunk.size == 0 || chunk.size > 2
|
if (chunk.size == 0 || chunk.size > 2
|
||||||
|| chunk.items[0].type != kObjectTypeString
|
|| chunk.items[0].type != kObjectTypeString
|
||||||
|| (chunk.size == 2 && chunk.items[1].type != kObjectTypeString)) {
|
|| chunk.size > 2) {
|
||||||
api_set_error(err, kErrorTypeValidation,
|
api_set_error(err, kErrorTypeValidation,
|
||||||
"Chunk is not an array with one or two strings");
|
"Chunk is not an array with one or two strings");
|
||||||
goto free_exit;
|
goto free_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
String str = chunk.items[0].data.string;
|
String str = chunk.items[0].data.string;
|
||||||
char *text = transstr(str.size > 0 ? str.data : ""); // allocates
|
|
||||||
|
|
||||||
int hl_id = 0;
|
int hl_id = 0;
|
||||||
if (chunk.size == 2) {
|
if (chunk.size == 2) {
|
||||||
String hl = chunk.items[1].data.string;
|
Object hl = chunk.items[1];
|
||||||
if (hl.size > 0) {
|
if (hl.type == kObjectTypeArray) {
|
||||||
hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
|
Array arr = hl.data.array;
|
||||||
|
for (size_t j = 0; j < arr.size; j++) {
|
||||||
|
hl_id = object_to_hl_id(arr.items[j], "virt_text highlight", err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
goto free_exit;
|
||||||
|
}
|
||||||
|
if (j < arr.size-1) {
|
||||||
|
kv_push(virt_text, ((VirtTextChunk){ .text = NULL,
|
||||||
|
.hl_id = hl_id }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hl_id = object_to_hl_id(hl, "virt_text highlight", err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
goto free_exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *text = transstr(str.size > 0 ? str.data : ""); // allocates
|
||||||
kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
|
kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1656,7 +1672,7 @@ int object_to_hl_id(Object obj, const char *what, Error *err)
|
||||||
String str = obj.data.string;
|
String str = obj.data.string;
|
||||||
return str.size ? syn_check_group((char_u *)str.data, (int)str.size) : 0;
|
return str.size ? syn_check_group((char_u *)str.data, (int)str.size) : 0;
|
||||||
} else if (obj.type == kObjectTypeInteger) {
|
} else if (obj.type == kObjectTypeInteger) {
|
||||||
return (int)obj.data.integer;
|
return MAX((int)obj.data.integer, 0);
|
||||||
} else {
|
} else {
|
||||||
api_set_error(err, kErrorTypeValidation,
|
api_set_error(err, kErrorTypeValidation,
|
||||||
"%s is not a valid highlight", what);
|
"%s is not a valid highlight", what);
|
||||||
|
|
|
@ -4021,6 +4021,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||||
|
|
||||||
while (wp->w_p_rl ? col >= 0 : col < grid->Columns) {
|
while (wp->w_p_rl ? col >= 0 : col < grid->Columns) {
|
||||||
int cells = -1;
|
int cells = -1;
|
||||||
|
// TODO: integrate this whith the other virt_text impl already
|
||||||
if (do_virttext && !delay_virttext) {
|
if (do_virttext && !delay_virttext) {
|
||||||
if (*s.p == NUL) {
|
if (*s.p == NUL) {
|
||||||
if (virt_pos < virt_text.size) {
|
if (virt_pos < virt_text.size) {
|
||||||
|
@ -4424,14 +4425,21 @@ void draw_virt_text(buf_T *buf, int col_off, int *end_col, int max_col)
|
||||||
|
|
||||||
while (col < max_col) {
|
while (col < max_col) {
|
||||||
if (!*s.p) {
|
if (!*s.p) {
|
||||||
if (virt_pos == kv_size(vt)) {
|
if (virt_pos >= kv_size(vt)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
virt_attr = 0;
|
||||||
|
do {
|
||||||
|
s.p = kv_A(vt, virt_pos).text;
|
||||||
|
int hl_id = kv_A(vt, virt_pos).hl_id;
|
||||||
|
virt_attr = hl_combine_attr(virt_attr,
|
||||||
|
hl_id > 0 ? syn_id2attr(hl_id) : 0);
|
||||||
|
virt_pos++;
|
||||||
|
} while (!s.p && virt_pos < kv_size(vt));
|
||||||
|
// TODO: y w0t m8
|
||||||
|
if (!s.p) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s.p = kv_A(vt, virt_pos).text;
|
|
||||||
int hl_id = kv_A(vt, virt_pos).hl_id;
|
|
||||||
virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
|
|
||||||
virt_pos++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
int attr;
|
int attr;
|
||||||
bool through = false;
|
bool through = false;
|
||||||
|
|
|
@ -697,6 +697,52 @@ end]]
|
||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('can have virtual text which combines foreground and backround groups', function()
|
||||||
|
screen:set_default_attr_ids {
|
||||||
|
[1] = {bold=true, foreground=Screen.colors.Blue};
|
||||||
|
[2] = {background = tonumber('0x123456'), foreground = tonumber('0xbbbbbb')};
|
||||||
|
[3] = {background = tonumber('0x123456'), foreground = tonumber('0xcccccc')};
|
||||||
|
[4] = {background = tonumber('0x234567'), foreground = tonumber('0xbbbbbb')};
|
||||||
|
[5] = {background = tonumber('0x234567'), foreground = tonumber('0xcccccc')};
|
||||||
|
[6] = {bold = true, foreground = tonumber('0xcccccc'), background = tonumber('0x234567')};
|
||||||
|
}
|
||||||
|
|
||||||
|
exec [[
|
||||||
|
hi BgOne guibg=#123456
|
||||||
|
hi BgTwo guibg=#234567
|
||||||
|
hi FgEin guifg=#bbbbbb
|
||||||
|
hi FgZwei guifg=#cccccc
|
||||||
|
hi VeryBold gui=bold
|
||||||
|
]]
|
||||||
|
|
||||||
|
meths.buf_set_extmark(0, ns, 0, 0, { virt_text={
|
||||||
|
{'a', {'BgOne', 'FgEin'}};
|
||||||
|
{'b', {'BgOne', 'FgZwei'}};
|
||||||
|
{'c', {'BgTwo', 'FgEin'}};
|
||||||
|
{'d', {'BgTwo', 'FgZwei'}};
|
||||||
|
{'X', {'BgTwo', 'FgZwei', 'VeryBold'}};
|
||||||
|
}})
|
||||||
|
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ {2:a}{3:b}{4:c}{5:d}{6:X} |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end)
|
||||||
|
|
||||||
it('does not crash when deleting a cleared buffer #15212', function()
|
it('does not crash when deleting a cleared buffer #15212', function()
|
||||||
exec_lua [[
|
exec_lua [[
|
||||||
ns = vim.api.nvim_create_namespace("myplugin")
|
ns = vim.api.nvim_create_namespace("myplugin")
|
||||||
|
|
Loading…
Reference in New Issue