mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
fix(api): get virtual text with multiple hl properly (#25307)
This commit is contained in:
@@ -113,6 +113,36 @@ static Object hl_group_name(int hl_id, bool hl_name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array virt_text_to_array(VirtText vt, bool hl_name)
|
||||||
|
{
|
||||||
|
Array chunks = ARRAY_DICT_INIT;
|
||||||
|
Array hl_array = ARRAY_DICT_INIT;
|
||||||
|
for (size_t i = 0; i < kv_size(vt); i++) {
|
||||||
|
char *text = kv_A(vt, i).text;
|
||||||
|
int hl_id = kv_A(vt, i).hl_id;
|
||||||
|
if (text == NULL) {
|
||||||
|
if (hl_id > 0) {
|
||||||
|
ADD(hl_array, hl_group_name(hl_id, hl_name));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Array chunk = ARRAY_DICT_INIT;
|
||||||
|
ADD(chunk, CSTR_TO_OBJ(text));
|
||||||
|
if (hl_array.size > 0) {
|
||||||
|
if (hl_id > 0) {
|
||||||
|
ADD(hl_array, hl_group_name(hl_id, hl_name));
|
||||||
|
}
|
||||||
|
ADD(chunk, ARRAY_OBJ(hl_array));
|
||||||
|
hl_array = (Array)ARRAY_DICT_INIT;
|
||||||
|
} else if (hl_id > 0) {
|
||||||
|
ADD(chunk, hl_group_name(hl_id, hl_name));
|
||||||
|
}
|
||||||
|
ADD(chunks, ARRAY_OBJ(chunk));
|
||||||
|
}
|
||||||
|
assert(hl_array.size == 0);
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict, bool hl_name)
|
static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict, bool hl_name)
|
||||||
{
|
{
|
||||||
Array rv = ARRAY_DICT_INIT;
|
Array rv = ARRAY_DICT_INIT;
|
||||||
@@ -145,16 +175,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kv_size(decor->virt_text)) {
|
if (kv_size(decor->virt_text)) {
|
||||||
Array chunks = ARRAY_DICT_INIT;
|
Array chunks = virt_text_to_array(decor->virt_text, hl_name);
|
||||||
for (size_t i = 0; i < decor->virt_text.size; i++) {
|
|
||||||
Array chunk = ARRAY_DICT_INIT;
|
|
||||||
VirtTextChunk *vtc = &decor->virt_text.items[i];
|
|
||||||
ADD(chunk, CSTR_TO_OBJ(vtc->text));
|
|
||||||
if (vtc->hl_id > 0) {
|
|
||||||
ADD(chunk, hl_group_name(vtc->hl_id, hl_name));
|
|
||||||
}
|
|
||||||
ADD(chunks, ARRAY_OBJ(chunk));
|
|
||||||
}
|
|
||||||
PUT(dict, "virt_text", ARRAY_OBJ(chunks));
|
PUT(dict, "virt_text", ARRAY_OBJ(chunks));
|
||||||
PUT(dict, "virt_text_hide", BOOLEAN_OBJ(decor->virt_text_hide));
|
PUT(dict, "virt_text_hide", BOOLEAN_OBJ(decor->virt_text_hide));
|
||||||
if (decor->virt_text_pos == kVTWinCol) {
|
if (decor->virt_text_pos == kVTWinCol) {
|
||||||
@@ -171,19 +192,9 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
|
|||||||
if (kv_size(decor->virt_lines)) {
|
if (kv_size(decor->virt_lines)) {
|
||||||
Array all_chunks = ARRAY_DICT_INIT;
|
Array all_chunks = ARRAY_DICT_INIT;
|
||||||
bool virt_lines_leftcol = false;
|
bool virt_lines_leftcol = false;
|
||||||
for (size_t i = 0; i < decor->virt_lines.size; i++) {
|
for (size_t i = 0; i < kv_size(decor->virt_lines); i++) {
|
||||||
Array chunks = ARRAY_DICT_INIT;
|
virt_lines_leftcol = kv_A(decor->virt_lines, i).left_col;
|
||||||
VirtText *vt = &decor->virt_lines.items[i].line;
|
Array chunks = virt_text_to_array(kv_A(decor->virt_lines, i).line, hl_name);
|
||||||
virt_lines_leftcol = decor->virt_lines.items[i].left_col;
|
|
||||||
for (size_t j = 0; j < vt->size; j++) {
|
|
||||||
Array chunk = ARRAY_DICT_INIT;
|
|
||||||
VirtTextChunk *vtc = &vt->items[j];
|
|
||||||
ADD(chunk, CSTR_TO_OBJ(vtc->text));
|
|
||||||
if (vtc->hl_id > 0) {
|
|
||||||
ADD(chunk, hl_group_name(vtc->hl_id, hl_name));
|
|
||||||
}
|
|
||||||
ADD(chunks, ARRAY_OBJ(chunk));
|
|
||||||
}
|
|
||||||
ADD(all_chunks, ARRAY_OBJ(chunks));
|
ADD(all_chunks, ARRAY_OBJ(chunks));
|
||||||
}
|
}
|
||||||
PUT(dict, "virt_lines", ARRAY_OBJ(all_chunks));
|
PUT(dict, "virt_lines", ARRAY_OBJ(all_chunks));
|
||||||
|
@@ -259,34 +259,28 @@ void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err)
|
|||||||
Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig,
|
Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig,
|
||||||
BorderTextType bordertext_type)
|
BorderTextType bordertext_type)
|
||||||
{
|
{
|
||||||
VirtText chunks;
|
VirtText vt;
|
||||||
AlignTextPos align;
|
AlignTextPos align;
|
||||||
char *field_name;
|
char *field_name;
|
||||||
char *field_pos_name;
|
char *field_pos_name;
|
||||||
switch (bordertext_type) {
|
switch (bordertext_type) {
|
||||||
case kBorderTextTitle:
|
case kBorderTextTitle:
|
||||||
chunks = fconfig->title_chunks;
|
vt = fconfig->title_chunks;
|
||||||
align = fconfig->title_pos;
|
align = fconfig->title_pos;
|
||||||
field_name = "title";
|
field_name = "title";
|
||||||
field_pos_name = "title_pos";
|
field_pos_name = "title_pos";
|
||||||
break;
|
break;
|
||||||
case kBorderTextFooter:
|
case kBorderTextFooter:
|
||||||
chunks = fconfig->footer_chunks;
|
vt = fconfig->footer_chunks;
|
||||||
align = fconfig->footer_pos;
|
align = fconfig->footer_pos;
|
||||||
field_name = "footer";
|
field_name = "footer";
|
||||||
field_pos_name = "footer_pos";
|
field_pos_name = "footer_pos";
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
Array bordertext = ARRAY_DICT_INIT;
|
Array bordertext = virt_text_to_array(vt, true);
|
||||||
for (size_t i = 0; i < chunks.size; i++) {
|
|
||||||
Array tuple = ARRAY_DICT_INIT;
|
|
||||||
ADD(tuple, CSTR_TO_OBJ(chunks.items[i].text));
|
|
||||||
if (chunks.items[i].hl_id > 0) {
|
|
||||||
ADD(tuple, CSTR_TO_OBJ(syn_id2name(chunks.items[i].hl_id)));
|
|
||||||
}
|
|
||||||
ADD(bordertext, ARRAY_OBJ(tuple));
|
|
||||||
}
|
|
||||||
PUT(config, field_name, ARRAY_OBJ(bordertext));
|
PUT(config, field_name, ARRAY_OBJ(bordertext));
|
||||||
|
|
||||||
char *pos;
|
char *pos;
|
||||||
|
@@ -1524,16 +1524,19 @@ describe('API/extmarks', function()
|
|||||||
sign_hl_group = "Statement",
|
sign_hl_group = "Statement",
|
||||||
sign_text = ">>",
|
sign_text = ">>",
|
||||||
spell = true,
|
spell = true,
|
||||||
virt_lines = { { { "lines", "Statement" } }},
|
virt_lines = {
|
||||||
|
{ { "lines", "Macro" }, { "???" } },
|
||||||
|
{ { "stack", { "Type", "Search" } }, { "!!!" } },
|
||||||
|
},
|
||||||
virt_lines_above = true,
|
virt_lines_above = true,
|
||||||
virt_lines_leftcol = true,
|
virt_lines_leftcol = true,
|
||||||
virt_text = { { "text", "Statement" } },
|
virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
|
||||||
virt_text_hide = true,
|
virt_text_hide = true,
|
||||||
virt_text_pos = "right_align",
|
virt_text_pos = "right_align",
|
||||||
})
|
})
|
||||||
set_extmark(ns, marks[2], 0, 0, {
|
set_extmark(ns, marks[2], 0, 0, {
|
||||||
priority = 0,
|
priority = 0,
|
||||||
virt_text = { { "text", "Statement" } },
|
virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
|
||||||
virt_text_win_col = 1,
|
virt_text_win_col = 1,
|
||||||
})
|
})
|
||||||
eq({0, 0, {
|
eq({0, 0, {
|
||||||
@@ -1553,10 +1556,13 @@ describe('API/extmarks', function()
|
|||||||
sign_hl_group = "Statement",
|
sign_hl_group = "Statement",
|
||||||
sign_text = ">>",
|
sign_text = ">>",
|
||||||
spell = true,
|
spell = true,
|
||||||
virt_lines = { { { "lines", "Statement" } }},
|
virt_lines = {
|
||||||
|
{ { "lines", "Macro" }, { "???" } },
|
||||||
|
{ { "stack", { "Type", "Search" } }, { "!!!" } },
|
||||||
|
},
|
||||||
virt_lines_above = true,
|
virt_lines_above = true,
|
||||||
virt_lines_leftcol = true,
|
virt_lines_leftcol = true,
|
||||||
virt_text = { { "text", "Statement" } },
|
virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
|
||||||
virt_text_hide = true,
|
virt_text_hide = true,
|
||||||
virt_text_pos = "right_align",
|
virt_text_pos = "right_align",
|
||||||
} }, get_extmark_by_id(ns, marks[1], { details = true }))
|
} }, get_extmark_by_id(ns, marks[1], { details = true }))
|
||||||
@@ -1564,7 +1570,7 @@ describe('API/extmarks', function()
|
|||||||
ns_id = 1,
|
ns_id = 1,
|
||||||
right_gravity = true,
|
right_gravity = true,
|
||||||
priority = 0,
|
priority = 0,
|
||||||
virt_text = { { "text", "Statement" } },
|
virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
|
||||||
virt_text_hide = false,
|
virt_text_hide = false,
|
||||||
virt_text_pos = "win_col",
|
virt_text_pos = "win_col",
|
||||||
virt_text_win_col = 1,
|
virt_text_win_col = 1,
|
||||||
|
@@ -895,13 +895,14 @@ describe('API/win', function()
|
|||||||
it('includes border', function()
|
it('includes border', function()
|
||||||
local b = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' }
|
local b = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' }
|
||||||
local win = meths.open_win(0, true, {
|
local win = meths.open_win(0, true, {
|
||||||
relative='win', row=3, col=3, width=12, height=3,
|
relative='win', row=3, col=3, width=12, height=3,
|
||||||
border = b,
|
border = b,
|
||||||
})
|
})
|
||||||
|
|
||||||
local cfg = meths.win_get_config(win)
|
local cfg = meths.win_get_config(win)
|
||||||
eq(b, cfg.border)
|
eq(b, cfg.border)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('includes border with highlight group', function()
|
it('includes border with highlight group', function()
|
||||||
local b = {
|
local b = {
|
||||||
{'a', 'Normal'},
|
{'a', 'Normal'},
|
||||||
@@ -914,12 +915,25 @@ describe('API/win', function()
|
|||||||
{'h', 'PreProc'},
|
{'h', 'PreProc'},
|
||||||
}
|
}
|
||||||
local win = meths.open_win(0, true, {
|
local win = meths.open_win(0, true, {
|
||||||
relative='win', row=3, col=3, width=12, height=3,
|
relative='win', row=3, col=3, width=12, height=3,
|
||||||
border = b,
|
border = b,
|
||||||
})
|
})
|
||||||
|
|
||||||
local cfg = meths.win_get_config(win)
|
local cfg = meths.win_get_config(win)
|
||||||
eq(b, cfg.border)
|
eq(b, cfg.border)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('includes title and footer', function()
|
||||||
|
local title = { {'A', {'StatusLine', 'TabLine'}}, {'B'}, {'C', 'WinBar'} }
|
||||||
|
local footer = { {'A', 'WinBar'}, {'B'}, {'C', {'StatusLine', 'TabLine'}} }
|
||||||
|
local win = meths.open_win(0, true, {
|
||||||
|
relative='win', row=3, col=3, width=12, height=3,
|
||||||
|
border = 'single', title = title, footer = footer,
|
||||||
|
})
|
||||||
|
|
||||||
|
local cfg = meths.win_get_config(win)
|
||||||
|
eq(title, cfg.title)
|
||||||
|
eq(footer, cfg.footer)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@@ -1464,7 +1464,7 @@ describe('extmark decorations', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('can have virtual text which combines foreground and background groups', function()
|
it('can have virtual text which combines foreground and background groups', function()
|
||||||
screen:try_resize(20, 3)
|
screen:try_resize(20, 5)
|
||||||
|
|
||||||
screen:set_default_attr_ids {
|
screen:set_default_attr_ids {
|
||||||
[1] = {bold=true, foreground=Screen.colors.Blue};
|
[1] = {bold=true, foreground=Screen.colors.Blue};
|
||||||
@@ -1494,8 +1494,11 @@ describe('extmark decorations', function()
|
|||||||
meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'eol' })
|
meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'eol' })
|
||||||
meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'right_align' })
|
meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'right_align' })
|
||||||
meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'inline' })
|
meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'inline' })
|
||||||
|
meths.buf_set_extmark(0, ns, 0, 0, { virt_lines = { vt, vt } })
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
{2:a}{3:b}{4:c}{5:d}{6:X}#^# {2:a}{3:b}{4:c}{5:d}{6:X} {2:a}{3:b}{4:c}{5:d}{6:X}|
|
{2:a}{3:b}{4:c}{5:d}{6:X}#^# {2:a}{3:b}{4:c}{5:d}{6:X} {2:a}{3:b}{4:c}{5:d}{6:X}|
|
||||||
|
{2:a}{3:b}{4:c}{5:d}{6:X} |
|
||||||
|
{2:a}{3:b}{4:c}{5:d}{6:X} |
|
||||||
{1:~ }|
|
{1:~ }|
|
||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
|
Reference in New Issue
Block a user