fix(ui): handle virtual text with multiple hl in more cases (#25304)

This commit is contained in:
zeertzjq 2023-09-22 15:36:24 +08:00 committed by GitHub
parent 34a786bc49
commit 64e8a3c4d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 69 additions and 53 deletions

View File

@ -1188,8 +1188,7 @@ VirtText parse_virt_text(Array chunks, Error *err, int *width)
goto free_exit; goto free_exit;
} }
if (j < arr.size - 1) { if (j < arr.size - 1) {
kv_push(virt_text, ((VirtTextChunk){ .text = NULL, kv_push(virt_text, ((VirtTextChunk){ .text = NULL, .hl_id = hl_id }));
.hl_id = hl_id }));
} }
} }
} else { } else {

View File

@ -153,6 +153,24 @@ void clear_virttext(VirtText *text)
*text = (VirtText)KV_INITIAL_VALUE; *text = (VirtText)KV_INITIAL_VALUE;
} }
/// 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
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;
}
Decoration *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id) Decoration *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id)
{ {
MarkTreeIter itr[1] = { 0 }; MarkTreeIter itr[1] = { 0 };

View File

@ -324,24 +324,6 @@ 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)
{ {

View File

@ -709,13 +709,15 @@ void end_search_hl(void)
screen_search_hl.rm.regprog = NULL; screen_search_hl.rm.regprog = NULL;
} }
static void win_redr_bordertext(win_T *wp, ScreenGrid *grid, VirtText text_chunks, int row, int col) static void win_redr_bordertext(win_T *wp, ScreenGrid *grid, VirtText vt, int row, int col)
{ {
for (size_t i = 0; i < text_chunks.size; i++) { for (size_t i = 0; i < kv_size(vt);) {
char *text = text_chunks.items[i].text; int attr = 0;
char *text = next_virt_text_chunk(vt, &i, &attr);
if (text == NULL) {
break;
}
int cell = (int)mb_string2cells(text); int cell = (int)mb_string2cells(text);
int hl_id = text_chunks.items[i].hl_id;
int attr = hl_id ? syn_id2attr(hl_id) : 0;
grid_puts(grid, text, row, col, attr); grid_puts(grid, text, row, col, attr);
col += cell; col += cell;
} }

View File

@ -3344,8 +3344,13 @@ void f_foldtextresult(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
} }
if (kv_size(vt) > 0) { if (kv_size(vt) > 0) {
assert(*text == NUL); assert(*text == NUL);
for (size_t i = 0; i < kv_size(vt); i++) { for (size_t i = 0; i < kv_size(vt);) {
char *new_text = concat_str(text, kv_A(vt, i).text); int attr = 0;
char *new_text = next_virt_text_chunk(vt, &i, &attr);
if (new_text == NULL) {
break;
}
new_text = concat_str(text, new_text);
xfree(text); xfree(text);
text = new_text; text = new_text;
} }

View File

@ -821,7 +821,7 @@ describe('float window', function()
[4] = {bold = true, reverse = true}, [4] = {bold = true, reverse = true},
[5] = {reverse = true}, [5] = {reverse = true},
[6] = {background = Screen.colors.LightMagenta, bold = true, reverse = true}, [6] = {background = Screen.colors.LightMagenta, bold = true, reverse = true},
[7] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, [7] = {foreground = Screen.colors.White, background = Screen.colors.Red},
[8] = {bold = true, foreground = Screen.colors.SeaGreen4}, [8] = {bold = true, foreground = Screen.colors.SeaGreen4},
[9] = {background = Screen.colors.LightGrey, underline = true}, [9] = {background = Screen.colors.LightGrey, underline = true},
[10] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta}, [10] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta},
@ -2512,7 +2512,12 @@ describe('float window', function()
]]} ]]}
end end
meths.win_set_config(win, {title= { {"🦄"},{"BB"}},title_pos="right",footer= { {"🦄"},{"BB"}},footer_pos="right"}) command('hi B0 guibg=Red guifg=Black')
command('hi B1 guifg=White')
meths.win_set_config(win, {
title = {{"🦄"}, {"BB", {"B0", "B1"}}}, title_pos = "right",
footer= {{"🦄"}, {"BB", {"B0", "B1"}}}, footer_pos = "right",
})
if multigrid then if multigrid then
screen:expect{grid=[[ screen:expect{grid=[[
## grid 1 ## grid 1
@ -2533,10 +2538,10 @@ describe('float window', function()
## grid 3 ## grid 3
| |
## grid 4 ## grid 4
{5:}🦄BB{5:}| {5:}🦄{7:BB}{5:}|
{5:}{1: halloj! }{5:}| {5:}{1: halloj! }{5:}|
{5:}{1: BORDAA }{5:}| {5:}{1: BORDAA }{5:}|
{5:}🦄BB{5:}| {5:}🦄{7:BB}{5:}|
]], float_pos={ ]], float_pos={
[4] = { { id = 1001 }, "NW", 1, 2, 5, true } [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
}, win_viewport={ }, win_viewport={
@ -2547,10 +2552,10 @@ describe('float window', function()
screen:expect{grid=[[ screen:expect{grid=[[
^ | ^ |
{0:~ }| {0:~ }|
{0:~ }{5:}🦄BB{5:}{0: }| {0:~ }{5:}🦄{7:BB}{5:}{0: }|
{0:~ }{5:}{1: halloj! }{5:}{0: }| {0:~ }{5:}{1: halloj! }{5:}{0: }|
{0:~ }{5:}{1: BORDAA }{5:}{0: }| {0:~ }{5:}{1: BORDAA }{5:}{0: }|
{0:~ }{5:}🦄BB{5:}{0: }| {0:~ }{5:}🦄{7:BB}{5:}{0: }|
| |
]]} ]]}
end end

View File

@ -33,7 +33,7 @@ describe("folded lines", function()
[1] = {bold = true, foreground = Screen.colors.Blue1}, [1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {reverse = true}, [2] = {reverse = true},
[3] = {bold = true, reverse = true}, [3] = {bold = true, reverse = true},
[4] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, [4] = {foreground = Screen.colors.White, background = Screen.colors.Red},
[5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey}, [5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
[6] = {background = Screen.colors.Yellow}, [6] = {background = Screen.colors.Yellow},
[7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray}, [7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
@ -2938,10 +2938,15 @@ describe("folded lines", function()
screen:try_resize(30, 7) screen:try_resize(30, 7)
insert(content1) insert(content1)
command("hi! CursorLine guibg=NONE guifg=Red gui=NONE") command("hi! CursorLine guibg=NONE guifg=Red gui=NONE")
command('hi F0 guibg=Red guifg=Black')
command('hi F1 guifg=White')
meths.set_option_value('cursorline', true, {}) meths.set_option_value('cursorline', true, {})
meths.set_option_value('foldcolumn', '4', {}) meths.set_option_value('foldcolumn', '4', {})
meths.set_option_value('foldtext', meths.set_option_value('foldtext', '['
'[[v:folddashes], ["\t", "Search"], [getline(v:foldstart), "NonText"]]', {}) .. '["▶", ["F0", "F1"]], '
.. '[v:folddashes], '
.. '["\t", "Search"], '
.. '[getline(v:foldstart), "NonText"]]', {})
command('3,4fold') command('3,4fold')
command('5,6fold') command('5,6fold')
@ -2958,7 +2963,7 @@ describe("folded lines", function()
[3:------------------------------]| [3:------------------------------]|
## grid 2 ## grid 2
{7: }This is a | {7: }This is a |
{7:+ }{13:^-}{17: }{18:valid English}{13:·····}| {7:+ }{4:^}{13:-}{17: }{18:valid English}{13:·····}|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
@ -2969,7 +2974,7 @@ describe("folded lines", function()
else else
screen:expect([[ screen:expect([[
{7: }This is a | {7: }This is a |
{7:+ }{13:^-}{17: }{18:valid English}{13:·····}| {7:+ }{4:^}{13:-}{17: }{18:valid English}{13:·····}|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
@ -2977,7 +2982,7 @@ describe("folded lines", function()
| |
]]) ]])
end end
eq('-\tvalid English', funcs.foldtextresult(2)) eq('-\tvalid English', funcs.foldtextresult(2))
feed('zo') feed('zo')
if multigrid then if multigrid then
@ -2993,8 +2998,8 @@ describe("folded lines", function()
## grid 2 ## grid 2
{7: }This is a | {7: }This is a |
{7:- }valid English | {7:- }valid English |
{7:+ }{5:--}{19: }{18:sentence composed }| {7:+ }{4:}{5:--}{19: }{18:sentence composed }|
{7:+ }{13:^--}{17: }{18:in his cave.}{13:······}| {7:+ }{4:^}{13:--}{17: }{18:in his cave.}{13:······}|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
## grid 3 ## grid 3
@ -3004,15 +3009,15 @@ describe("folded lines", function()
screen:expect([[ screen:expect([[
{7: }This is a | {7: }This is a |
{7:- }valid English | {7:- }valid English |
{7:+ }{5:--}{19: }{18:sentence composed }| {7:+ }{4:}{5:--}{19: }{18:sentence composed }|
{7:+ }{13:^--}{17: }{18:in his cave.}{13:······}| {7:+ }{4:^}{13:--}{17: }{18:in his cave.}{13:······}|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| |
]]) ]])
end end
eq('--\tsentence composed by', funcs.foldtextresult(3)) eq('--\tsentence composed by', funcs.foldtextresult(3))
eq('--\tin his cave.', funcs.foldtextresult(5)) eq('--\tin his cave.', funcs.foldtextresult(5))
command('hi! Visual guibg=Red') command('hi! Visual guibg=Red')
feed('V2k') feed('V2k')
@ -3029,8 +3034,8 @@ describe("folded lines", function()
## grid 2 ## grid 2
{7: }This is a | {7: }This is a |
{7:- }^v{14:alid English} | {7:- }^v{14:alid English} |
{7:+ }{15:--}{19: }{20:sentence composed }| {7:+ }{4:}{15:--}{19: }{20:sentence composed }|
{7:+ }{15:--}{19: }{20:in his cave.}{15:······}| {7:+ }{4:}{15:--}{19: }{20:in his cave.}{15:······}|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
## grid 3 ## grid 3
@ -3040,8 +3045,8 @@ describe("folded lines", function()
screen:expect([[ screen:expect([[
{7: }This is a | {7: }This is a |
{7:- }^v{14:alid English} | {7:- }^v{14:alid English} |
{7:+ }{15:--}{19: }{20:sentence composed }| {7:+ }{4:}{15:--}{19: }{20:sentence composed }|
{7:+ }{15:--}{19: }{20:in his cave.}{15:······}| {7:+ }{4:}{15:--}{19: }{20:in his cave.}{15:······}|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{11:-- VISUAL LINE --} | {11:-- VISUAL LINE --} |
@ -3062,8 +3067,8 @@ describe("folded lines", function()
## grid 2 ## grid 2
a si sihT{7: }| a si sihT{7: }|
{14:hsilgnE dila}^v{7: -}| {14:hsilgnE dila}^v{7: -}|
{20: desopmoc ecnetnes}{19: }{15:--}{7: +│}| {20: desopmoc ecnetnes}{19: }{15:--}{4:▶}{7: +│}|
{15:······}{20:.evac sih ni}{19: }{15:--}{7: +│}| {15:······}{20:.evac sih ni}{19: }{15:--}{4:▶}{7: +│}|
{1: ~}| {1: ~}|
{1: ~}| {1: ~}|
## grid 3 ## grid 3
@ -3073,8 +3078,8 @@ describe("folded lines", function()
screen:expect([[ screen:expect([[
a si sihT{7: }| a si sihT{7: }|
{14:hsilgnE dila}^v{7: -}| {14:hsilgnE dila}^v{7: -}|
{20: desopmoc ecnetnes}{19: }{15:--}{7: +│}| {20: desopmoc ecnetnes}{19: }{15:--}{4:▶}{7: +│}|
{15:······}{20:.evac sih ni}{19: }{15:--}{7: +│}| {15:······}{20:.evac sih ni}{19: }{15:--}{4:▶}{7: +│}|
{1: ~}| {1: ~}|
{1: ~}| {1: ~}|
{11:-- VISUAL LINE --} | {11:-- VISUAL LINE --} |