fix(extmarks): overlay virt_text position after 'showbreak' (#25175)

Also make virt_text_hide work properly.
This commit is contained in:
zeertzjq 2023-09-15 20:30:50 +08:00 committed by GitHub
parent f5a09f1b03
commit 35e50d79c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 19 deletions

View File

@ -268,6 +268,28 @@ static void decor_add(DecorState *state, int start_row, int start_col, int end_r
kv_A(state->active, index) = range;
}
/// Initialize the draw_col of a newly-added non-inline virtual text item.
static void decor_init_draw_col(int win_col, bool hidden, DecorRange *item)
{
if (win_col < 0) {
item->draw_col = win_col;
} else if (item->decor.virt_text_pos == kVTOverlay) {
item->draw_col = (item->decor.virt_text_hide && hidden) ? INT_MIN : win_col;
} else {
item->draw_col = -1;
}
}
void decor_recheck_draw_col(int win_col, bool hidden, DecorState *state)
{
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange *item = &kv_A(state->active, i);
if (item->draw_col == -3) {
decor_init_draw_col(win_col, hidden, item);
}
}
}
int decor_redraw_col(win_T *wp, int col, int win_col, bool hidden, DecorState *state)
{
buf_T *buf = wp->w_buffer;
@ -349,12 +371,9 @@ next_mark:
spell = item.decor.spell;
}
if (item.start_row == state->row && item.start_col <= col
&& decor_virt_pos(&item.decor) && item.draw_col == -1) {
if (item.decor.virt_text_pos == kVTOverlay) {
item.draw_col = (item.decor.virt_text_hide && hidden) ? INT_MIN : win_col;
} else if (win_col < 0 && item.decor.virt_text_pos != kVTInline) {
item.draw_col = win_col;
}
&& decor_virt_pos(&item.decor) && item.draw_col == -1
&& item.decor.virt_text_pos != kVTInline) {
decor_init_draw_col(win_col, hidden, &item);
}
if (keep) {
kv_A(state->active, j++) = item;

View File

@ -84,7 +84,6 @@ typedef struct {
bool virt_text_owned;
/// Screen column to draw the virtual text.
/// When -1, the virtual text may be drawn after deciding where.
/// When -2, the virtual text should be drawn at the start of the screen line.
/// When -3, the virtual text should be drawn on the next screen line.
/// When INT_MIN, the virtual text should no longer be drawn.
int draw_col;

View File

@ -282,10 +282,6 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int
} else if (item->decor.virt_text_pos == kVTWinCol) {
item->draw_col = MAX(item->decor.col + col_off, 0);
}
} else if (item->draw_col == -2) {
item->draw_col = col_off;
} else if (item->draw_col == -3) {
item->draw_col = item->decor.virt_text_pos == kVTOverlay ? -2 : -1;
}
if (item->draw_col < 0) {
continue;
@ -1145,6 +1141,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
bool saved_search_attr_from_match = false;
int win_col_offset = 0; // offset for window columns
bool area_active = false; // whether in Visual selection, for virtual text
bool decor_need_recheck = false; // call decor_recheck_draw_col() at next char
char buf_fold[FOLD_TEXT_LEN]; // Hold value returned by get_foldtext
@ -1786,9 +1784,27 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
if (has_decor && wlv.n_extra == 0) {
bool selected = (area_highlighting
&& ((wlv.vcol >= wlv.fromcol && wlv.vcol < wlv.tocol)
|| (noinvcur && wlv.vcol == wp->w_virtcol)));
// Duplicate the Visual area check after this block,
// but don't check inside p_extra here.
if (wlv.vcol == wlv.fromcol
|| (wlv.vcol + 1 == wlv.fromcol
&& (wlv.n_extra == 0 && utf_ptr2cells(ptr) > 1))
|| (vcol_prev == fromcol_prev
&& vcol_prev < wlv.vcol
&& wlv.vcol < wlv.tocol)) {
area_active = true;
} else if (area_active
&& (wlv.vcol == wlv.tocol
|| (noinvcur && wlv.vcol == wp->w_virtcol))) {
area_active = false;
}
bool selected = (area_active || (area_highlighting && noinvcur
&& wlv.vcol == wp->w_virtcol));
if (decor_need_recheck) {
decor_recheck_draw_col(wlv.off, selected, &decor_state);
decor_need_recheck = false;
}
extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off, selected, &decor_state);
if (!has_fold && wp->w_buffer->b_virt_text_inline > 0) {
@ -1822,10 +1838,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
&& vcol_prev < wlv.vcol // not at margin
&& wlv.vcol < wlv.tocol)) {
*area_attr_p = vi_attr; // start highlighting
area_active = true;
} else if (*area_attr_p != 0
&& (wlv.vcol == wlv.tocol
|| (noinvcur && wlv.vcol == wp->w_virtcol))) {
*area_attr_p = 0; // stop highlighting
area_active = false;
}
if (!has_fold && wlv.n_extra == 0) {
@ -3087,9 +3105,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// At the end of screen line: might need to peek for decorations just after
// this position.
if (!has_fold && wp->w_p_wrap && wlv.n_extra == 0) {
// FIXME: virt_text_hide doesn't work for overlay virt_text at the next char
// as it's not easy to check if the next char is inside Visual selection.
decor_redraw_col(wp, (int)(ptr - line), -3, false, &decor_state);
// Check position/hiding of virtual text again on next screen line.
decor_need_recheck = true;
} else if (has_fold || !wp->w_p_wrap) {
// Without wrapping, we might need to display right_align and win_col
// virt_text for the entire text line.

View File

@ -1280,7 +1280,7 @@ static TriState decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_ln
decor_redraw_line(wp, lnum - 1, &decor_state);
*decor_lnum = lnum;
}
decor_redraw_col(wp, col, col, false, &decor_state);
decor_redraw_col(wp, col, 0, false, &decor_state);
return decor_state.spell;
}

View File

@ -869,7 +869,7 @@ describe('extmark decorations', function()
insert(('ab'):rep(100))
for i = 0, 9 do
meths.buf_set_extmark(0, ns, 0, 42 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay'})
meths.buf_set_extmark(0, ns, 0, 91 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide = true})
meths.buf_set_extmark(0, ns, 0, 91 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
end
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
@ -880,7 +880,58 @@ describe('extmark decorations', function()
|
]]}
command('set number')
command('set showbreak=++')
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
{1:++}{4:89}abababababababababababababababababababa{4:0123456}|
{1:++}{4:789}babababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababa^b |
|
]]}
feed('2gkvg0')
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
{1:++}{4:89}abababababababababababababababababababa{4:0123456}|
{1:++}^a{18:babab}ababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
{24:-- VISUAL --} |
]]}
feed('o')
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
{1:++}{4:89}abababababababababababababababababababa{4:0123456}|
{1:++}{18:ababa}^bababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
{24:-- VISUAL --} |
]]}
feed('gk')
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
{1:++}{4:89}aba^b{18:ababababababababababababababababababababab}|
{1:++}{18:a}{4:89}babababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
{24:-- VISUAL --} |
]]}
feed('o')
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
{1:++}{4:89}aba{18:bababababababababababababababababababababab}|
{1:++}^a{4:89}babababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
{24:-- VISUAL --} |
]]}
feed('<Esc>$')
command('set number showbreak=')
screen:expect{grid=[[
{2: 1 }ababababababababababababababababababababab{4:0123}|
{2: }{4:456789}abababababababababababababababababababa{4:0}|