mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 19:38:20 +00:00
fix(extmarks): inline virt_text support multiple hl groups (#25303)
This commit is contained in:
@@ -324,6 +324,24 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the next chunk of a virtual text item.
|
||||||
|
///
|
||||||
|
/// @param[in] vt The virtual text item
|
||||||
|
/// @param[in,out] pos Position in the virtual text item
|
||||||
|
/// @param[in,out] attr Highlight attribute
|
||||||
|
///
|
||||||
|
/// @return The text of the chunk, or NULL if there are no more chunks
|
||||||
|
static char *next_virt_text_chunk(VirtText vt, size_t *pos, int *attr)
|
||||||
|
{
|
||||||
|
char *text = NULL;
|
||||||
|
for (; text == NULL && *pos < kv_size(vt); (*pos)++) {
|
||||||
|
text = kv_A(vt, *pos).text;
|
||||||
|
int hl_id = kv_A(vt, *pos).hl_id;
|
||||||
|
*attr = hl_combine_attr(*attr, hl_id > 0 ? syn_id2attr(hl_id) : 0);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, int max_col,
|
static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, int max_col,
|
||||||
int vcol, bool rl)
|
int vcol, bool rl)
|
||||||
{
|
{
|
||||||
@@ -332,23 +350,17 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
|
|||||||
size_t virt_pos = 0;
|
size_t virt_pos = 0;
|
||||||
|
|
||||||
while (rl ? col > max_col : col < max_col) {
|
while (rl ? col > max_col : col < max_col) {
|
||||||
if (!*s.p) {
|
if (*s.p == NUL) {
|
||||||
if (virt_pos >= kv_size(vt)) {
|
if (virt_pos >= kv_size(vt)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
virt_attr = 0;
|
virt_attr = 0;
|
||||||
do {
|
s.p = next_virt_text_chunk(vt, &virt_pos, &virt_attr);
|
||||||
s.p = kv_A(vt, virt_pos).text;
|
if (s.p == NULL) {
|
||||||
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));
|
|
||||||
if (!s.p) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!*s.p) {
|
if (*s.p == NUL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int attr;
|
int attr;
|
||||||
@@ -950,17 +962,20 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// already inside existing inline virtual text with multiple chunks
|
// already inside existing inline virtual text with multiple chunks
|
||||||
VirtTextChunk vtc = kv_A(wlv->virt_inline, wlv->virt_inline_i);
|
int attr = 0;
|
||||||
wlv->virt_inline_i++;
|
char *text = next_virt_text_chunk(wlv->virt_inline, &wlv->virt_inline_i, &attr);
|
||||||
wlv->p_extra = vtc.text;
|
if (text == NULL) {
|
||||||
wlv->n_extra = (int)strlen(vtc.text);
|
continue;
|
||||||
|
}
|
||||||
|
wlv->p_extra = text;
|
||||||
|
wlv->n_extra = (int)strlen(text);
|
||||||
if (wlv->n_extra == 0) {
|
if (wlv->n_extra == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
wlv->c_extra = NUL;
|
wlv->c_extra = NUL;
|
||||||
wlv->c_final = NUL;
|
wlv->c_final = NUL;
|
||||||
wlv->extra_attr = vtc.hl_id ? syn_id2attr(vtc.hl_id) : 0;
|
wlv->extra_attr = attr;
|
||||||
wlv->n_attr = mb_charlen(vtc.text);
|
wlv->n_attr = mb_charlen(text);
|
||||||
// If the text didn't reach until the first window
|
// If the text didn't reach until the first window
|
||||||
// column we need to skip cells.
|
// column we need to skip cells.
|
||||||
if (wlv->skip_cells > 0) {
|
if (wlv->skip_cells > 0) {
|
||||||
|
@@ -1464,6 +1464,8 @@ 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:set_default_attr_ids {
|
screen:set_default_attr_ids {
|
||||||
[1] = {bold=true, foreground=Screen.colors.Blue};
|
[1] = {bold=true, foreground=Screen.colors.Blue};
|
||||||
[2] = {background = tonumber('0x123456'), foreground = tonumber('0xbbbbbb')};
|
[2] = {background = tonumber('0x123456'), foreground = tonumber('0xbbbbbb')};
|
||||||
@@ -1481,30 +1483,21 @@ describe('extmark decorations', function()
|
|||||||
hi VeryBold gui=bold
|
hi VeryBold gui=bold
|
||||||
]]
|
]]
|
||||||
|
|
||||||
meths.buf_set_extmark(0, ns, 0, 0, { virt_text={
|
insert('##')
|
||||||
|
local vt = {
|
||||||
{'a', {'BgOne', 'FgEin'}};
|
{'a', {'BgOne', 'FgEin'}};
|
||||||
{'b', {'BgOne', 'FgZwei'}};
|
{'b', {'BgOne', 'FgZwei'}};
|
||||||
{'c', {'BgTwo', 'FgEin'}};
|
{'c', {'BgTwo', 'FgEin'}};
|
||||||
{'d', {'BgTwo', 'FgZwei'}};
|
{'d', {'BgTwo', 'FgZwei'}};
|
||||||
{'X', {'BgTwo', 'FgZwei', 'VeryBold'}};
|
{'X', {'BgTwo', 'FgZwei', 'VeryBold'}};
|
||||||
}})
|
}
|
||||||
|
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 = 'inline' })
|
||||||
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}|
|
||||||
{1:~ }|
|
{1:~ }|
|
||||||
{1:~ }|
|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
{1:~ }|
|
|
||||||
|
|
|
||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user