mirror of
https://github.com/neovim/neovim
synced 2025-07-17 17:51:48 +00:00
fix(ui): fix visual and search highlighting interfering with virtual text
vim-patch:9.0.0193: search and match highlgith interfere with virtual text Problem: Search and match highlgith interfere with virtual text highlight. (Ben Jackson) Solution: Check for match highlight after text properties. Reset and restore search highlight when showing virtual text. (closes vim/vim#10892)e38fc86180
vim-patch:9.0.0452: Visual highlighting extends into virtual text prop Problem: Visual highlighting extends into virtual text prop. Solution: Do not highlight what isn't actually selected. Fix ordering of stored text props.6eda17d881
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@ -978,7 +978,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
bool area_highlighting = false; // Visual or incsearch highlighting in this line
|
bool area_highlighting = false; // Visual or incsearch highlighting in this line
|
||||||
int vi_attr = 0; // attributes for Visual and incsearch highlighting
|
int vi_attr = 0; // attributes for Visual and incsearch highlighting
|
||||||
int area_attr = 0; // attributes desired by highlighting
|
int area_attr = 0; // attributes desired by highlighting
|
||||||
|
int saved_area_attr = 0; // idem for area_attr
|
||||||
int search_attr = 0; // attributes desired by 'hlsearch'
|
int search_attr = 0; // attributes desired by 'hlsearch'
|
||||||
|
int saved_search_attr = 0; // search_attr to be used when n_extra
|
||||||
|
// goes to zero
|
||||||
int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
|
int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
|
||||||
int syntax_attr = 0; // attributes desired by syntax
|
int syntax_attr = 0; // attributes desired by syntax
|
||||||
bool has_syntax = false; // this buffer has syntax highl.
|
bool has_syntax = false; // this buffer has syntax highl.
|
||||||
@ -1729,6 +1732,50 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
area_active = false;
|
area_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_decor && v >= 0) {
|
||||||
|
bool selected = (area_active || (area_highlighting && noinvcur
|
||||||
|
&& wlv.vcol == wp->w_virtcol));
|
||||||
|
extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off,
|
||||||
|
selected, &decor_state);
|
||||||
|
|
||||||
|
// we could already be inside an existing virt_line with multiple chunks
|
||||||
|
if (!(virt_inline_i < kv_size(virt_inline))) {
|
||||||
|
DecorState *state = &decor_state;
|
||||||
|
for (size_t i = 0; i < kv_size(state->active); i++) {
|
||||||
|
DecorRange *item = &kv_A(state->active, i);
|
||||||
|
if (!(item->start_row == state->row
|
||||||
|
&& kv_size(item->decor.virt_text)
|
||||||
|
&& item->decor.virt_text_pos == kVTInline)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (item->win_col >= -1 && item->start_col <= v) {
|
||||||
|
virt_inline = item->decor.virt_text;
|
||||||
|
virt_inline_i = 0;
|
||||||
|
item->win_col = -2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlv.n_extra <= 0 && virt_inline_i < kv_size(virt_inline)) {
|
||||||
|
VirtTextChunk vtc = kv_A(virt_inline, virt_inline_i);
|
||||||
|
wlv.p_extra = vtc.text;
|
||||||
|
wlv.n_extra = (int)strlen(wlv.p_extra);
|
||||||
|
wlv.c_extra = NUL;
|
||||||
|
wlv.c_final = NUL;
|
||||||
|
wlv.extra_attr = vtc.hl_id ? syn_id2attr(vtc.hl_id) : 0;
|
||||||
|
n_attr = mb_charlen(vtc.text);
|
||||||
|
// restore search_attr and area_attr when n_extra
|
||||||
|
// is down to zero
|
||||||
|
saved_search_attr = search_attr;
|
||||||
|
saved_area_attr = area_attr;
|
||||||
|
search_attr = 0;
|
||||||
|
area_attr = 0;
|
||||||
|
extmark_attr = 0;
|
||||||
|
virt_inline_i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!wlv.n_extra) {
|
if (!wlv.n_extra) {
|
||||||
// Check for start/end of 'hlsearch' and other matches.
|
// Check for start/end of 'hlsearch' and other matches.
|
||||||
// After end, check for start/end of next match.
|
// After end, check for start/end of next match.
|
||||||
@ -1792,43 +1839,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
wlv.char_attr = 0;
|
wlv.char_attr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_decor && v >= 0) {
|
|
||||||
bool selected = (area_active || (area_highlighting && noinvcur
|
|
||||||
&& wlv.vcol == wp->w_virtcol));
|
|
||||||
extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off, selected, &decor_state);
|
|
||||||
|
|
||||||
// we could already be inside an existing virt_line with multiple chunks
|
|
||||||
if (!(virt_inline_i < kv_size(virt_inline))) {
|
|
||||||
DecorState *state = &decor_state;
|
|
||||||
for (size_t i = 0; i < kv_size(state->active); i++) {
|
|
||||||
DecorRange *item = &kv_A(state->active, i);
|
|
||||||
if (!(item->start_row == state->row
|
|
||||||
&& kv_size(item->decor.virt_text)
|
|
||||||
&& item->decor.virt_text_pos == kVTInline)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (item->win_col >= -1 && item->start_col <= v) {
|
|
||||||
virt_inline = item->decor.virt_text;
|
|
||||||
virt_inline_i = 0;
|
|
||||||
item->win_col = -2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wlv.n_extra <= 0 && virt_inline_i < kv_size(virt_inline)) {
|
|
||||||
VirtTextChunk vtc = kv_A(virt_inline, virt_inline_i);
|
|
||||||
wlv.p_extra = vtc.text;
|
|
||||||
wlv.n_extra = (int)strlen(wlv.p_extra);
|
|
||||||
wlv.c_extra = NUL;
|
|
||||||
wlv.c_final = NUL;
|
|
||||||
wlv.extra_attr = vtc.hl_id ? syn_id2attr(vtc.hl_id) : 0;
|
|
||||||
n_attr = mb_charlen(vtc.text);
|
|
||||||
extmark_attr = 0;
|
|
||||||
virt_inline_i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the next character to put on the screen.
|
// Get the next character to put on the screen.
|
||||||
@ -1890,6 +1900,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
|||||||
wlv.p_extra++;
|
wlv.p_extra++;
|
||||||
}
|
}
|
||||||
wlv.n_extra--;
|
wlv.n_extra--;
|
||||||
|
if (wlv.n_extra <= 0) {
|
||||||
|
if (search_attr == 0) {
|
||||||
|
search_attr = saved_search_attr;
|
||||||
|
}
|
||||||
|
if (area_attr == 0 && *ptr != NUL) {
|
||||||
|
area_attr = saved_area_attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (foldinfo.fi_lines > 0) {
|
} else if (foldinfo.fi_lines > 0) {
|
||||||
// skip writing the buffer line itself
|
// skip writing the buffer line itself
|
||||||
c = NUL;
|
c = NUL;
|
||||||
|
@ -646,6 +646,8 @@ describe('extmark decorations', function()
|
|||||||
[26] = {background=Screen.colors.DarkGrey, foreground=Screen.colors.LightGrey};
|
[26] = {background=Screen.colors.DarkGrey, foreground=Screen.colors.LightGrey};
|
||||||
[27] = {background = Screen.colors.Plum1};
|
[27] = {background = Screen.colors.Plum1};
|
||||||
[28] = {foreground = Screen.colors.SlateBlue};
|
[28] = {foreground = Screen.colors.SlateBlue};
|
||||||
|
[29] = {background = Screen.colors.Yellow1};
|
||||||
|
[30] = {reverse = true};
|
||||||
}
|
}
|
||||||
|
|
||||||
ns = meths.create_namespace 'test'
|
ns = meths.create_namespace 'test'
|
||||||
@ -1582,7 +1584,7 @@ bbbbbbb]])
|
|||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('has correct cursor position with virtual text on an empty line', function()
|
it('cursor position is correct with virtual text on an empty line', function()
|
||||||
command('set linebreak')
|
command('set linebreak')
|
||||||
insert('one twoword')
|
insert('one twoword')
|
||||||
feed('0')
|
feed('0')
|
||||||
@ -1606,6 +1608,94 @@ bbbbbbb]])
|
|||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('search highlight is correct with virtual text attatched to', function()
|
||||||
|
insert('foo foo foo foo')
|
||||||
|
feed('0')
|
||||||
|
meths.buf_set_extmark(0, ns, 0, 8,
|
||||||
|
{ virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
|
||||||
|
screen:expect { grid = [[
|
||||||
|
^foo foo {28:virtual text}foo foo |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
|
||||||
|
feed('/foo')
|
||||||
|
screen:expect { grid = [[
|
||||||
|
{29:foo} {30:foo} {28:virtual text}{29:foo} {29:foo} |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
/foo^ |
|
||||||
|
]]}
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('visual select highlight is correct with virtual text attatched to', function()
|
||||||
|
insert('foo foo foo foo')
|
||||||
|
feed('0')
|
||||||
|
meths.buf_set_extmark(0, ns, 0, 8,
|
||||||
|
{ virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
|
||||||
|
feed('8l')
|
||||||
|
screen:expect { grid = [[
|
||||||
|
foo foo {28:virtual text}^foo foo |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
|
||||||
|
feed('v')
|
||||||
|
feed('2h')
|
||||||
|
screen:expect { grid = [[
|
||||||
|
foo fo^o{18: }{28:virtual text}{18:f}oo foo |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{24:-- VISUAL --} |
|
||||||
|
]]}
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('decorations: virtual lines', function()
|
describe('decorations: virtual lines', function()
|
||||||
|
Reference in New Issue
Block a user