mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:9.0.1783: Display issues with virt text smoothscroll and showbreak
Problem: Wrong display with wrapping virtual text or unprintable chars,
'showbreak' and 'smoothscroll'.
Solution: Don't skip cells taken by 'showbreak' in screen lines before
"w_skipcol". Combined "n_skip" and "skip_cells".
closes: vim/vim#12597
b557f48982
This commit is contained in:
parent
3e80b39a8e
commit
a1d71ad55e
@ -991,6 +991,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
|
||||
chartabsize_T cts;
|
||||
bool on_NUL = false;
|
||||
init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
|
||||
cts.cts_max_head_vcol = -1;
|
||||
|
||||
// This function is used very often, do some speed optimizations.
|
||||
// When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
|
||||
|
@ -132,9 +132,12 @@ typedef struct {
|
||||
|
||||
bool reset_extra_attr;
|
||||
|
||||
int skip_cells; // nr of cells to skip for virtual text
|
||||
int skipped_cells; // nr of skipped virtual text cells
|
||||
bool more_virt_inline_chunks; // indicates if there is more inline virtual text after n_extra
|
||||
int skip_cells; ///< nr of cells to skip for w_leftcol
|
||||
///< or w_skipcol or concealing
|
||||
int skipped_cells; ///< nr of skipped cells for virtual text
|
||||
///< to be added to wlv.vcol later
|
||||
bool more_virt_inline_chunks; ///< indicates if there is more inline virtual text
|
||||
///< after n_extra
|
||||
} winlinevars_T;
|
||||
|
||||
/// for line_putchar. Contains the state that needs to be remembered from
|
||||
@ -1090,9 +1093,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
int n_attr3 = 0; // chars with overruling special attr
|
||||
int saved_attr3 = 0; // char_attr saved for n_attr3
|
||||
|
||||
int n_skip = 0; // nr of chars to skip for 'nowrap' or
|
||||
// concealing
|
||||
|
||||
int fromcol_prev = -2; // start of inverting after cursor
|
||||
bool noinvcur = false; // don't invert the cursor
|
||||
bool lnum_in_visual_area = false;
|
||||
@ -1500,10 +1500,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
char *prev_ptr = ptr;
|
||||
chartabsize_T cts;
|
||||
int charsize = 0;
|
||||
int head = 0;
|
||||
|
||||
init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, ptr);
|
||||
cts.cts_max_head_vcol = (int)v;
|
||||
while (cts.cts_vcol < v && *cts.cts_ptr != NUL) {
|
||||
charsize = win_lbr_chartabsize(&cts, NULL);
|
||||
head = 0;
|
||||
charsize = win_lbr_chartabsize(&cts, &head);
|
||||
cts.cts_vcol += charsize;
|
||||
prev_ptr = cts.cts_ptr;
|
||||
MB_PTR_ADV(cts.cts_ptr);
|
||||
@ -1530,17 +1533,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
if (wlv.vcol > v) {
|
||||
wlv.vcol -= charsize;
|
||||
ptr = prev_ptr;
|
||||
// If the character fits on the screen, don't need to skip it.
|
||||
// Except for a TAB.
|
||||
if (utf_ptr2cells(ptr) >= charsize || *ptr == TAB) {
|
||||
n_skip = (int)(v - wlv.vcol);
|
||||
}
|
||||
}
|
||||
|
||||
// If there the text doesn't reach to the desired column, need to skip
|
||||
// "skip_cells" cells when virtual text follows.
|
||||
if ((!wp->w_p_wrap || (lnum == wp->w_topline && wp->w_skipcol > 0)) && v > wlv.vcol) {
|
||||
wlv.skip_cells = (int)(v - wlv.vcol);
|
||||
if (v > wlv.vcol) {
|
||||
wlv.skip_cells = (int)v - wlv.vcol - head;
|
||||
}
|
||||
|
||||
// Adjust for when the inverted text is before the screen,
|
||||
@ -1808,9 +1804,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
decor_attr = 0;
|
||||
search_attr_from_match = false;
|
||||
}
|
||||
if (wlv.n_extra > 0) {
|
||||
n_skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2027,6 +2020,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
// Get a character from the line itself.
|
||||
c0 = c = (uint8_t)(*ptr);
|
||||
mb_c = c;
|
||||
|
||||
if (c == NUL) {
|
||||
// no more cells to skip
|
||||
wlv.skip_cells = 0;
|
||||
}
|
||||
|
||||
// If the UTF-8 character is more than one byte: Decode it
|
||||
// into "mb_c".
|
||||
mb_l = utfc_ptr2len(ptr);
|
||||
@ -2118,7 +2117,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
|
||||
// If a double-width char doesn't fit at the left side display a '<' in
|
||||
// the first column. Don't do this for unprintable characters.
|
||||
if (n_skip > 0 && mb_l > 1 && wlv.n_extra == 0) {
|
||||
if (wlv.skip_cells > 0 && mb_l > 1 && wlv.n_extra == 0) {
|
||||
wlv.n_extra = 1;
|
||||
wlv.c_extra = MB_FILLER_CHAR;
|
||||
wlv.c_final = NUL;
|
||||
@ -2619,9 +2618,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
}
|
||||
wlv.n_extra = 0;
|
||||
wlv.n_attr = 0;
|
||||
} else if (n_skip == 0) {
|
||||
} else if (wlv.skip_cells == 0) {
|
||||
is_concealing = true;
|
||||
n_skip = 1;
|
||||
wlv.skip_cells = 1;
|
||||
}
|
||||
mb_c = c;
|
||||
mb_utf8 = check_mb_utf8(&c, u8cc);
|
||||
@ -2630,7 +2629,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
is_concealing = false;
|
||||
}
|
||||
|
||||
if (n_skip > 0 && did_decrement_ptr) {
|
||||
if (wlv.skip_cells > 0 && did_decrement_ptr) {
|
||||
// not showing the '>', put pointer back to avoid getting stuck
|
||||
ptr++;
|
||||
}
|
||||
@ -2641,7 +2640,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
if (!did_wcol && wlv.draw_state == WL_LINE
|
||||
&& wp == curwin && lnum == wp->w_cursor.lnum
|
||||
&& conceal_cursor_line(wp)
|
||||
&& (int)wp->w_virtcol <= wlv.vcol + n_skip) {
|
||||
&& (int)wp->w_virtcol <= wlv.vcol + wlv.skip_cells) {
|
||||
if (wp->w_p_rl) {
|
||||
wp->w_wcol = grid->cols - wlv.col + wlv.boguscols - 1;
|
||||
} else {
|
||||
@ -2946,7 +2945,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
|
||||
// Store character to be displayed.
|
||||
// Skip characters that are left of the screen for 'nowrap'.
|
||||
if (wlv.draw_state < WL_LINE || n_skip <= 0) {
|
||||
if (wlv.draw_state < WL_LINE || wlv.skip_cells <= 0) {
|
||||
// Store the character.
|
||||
if (wp->w_p_rl && utf_char2cells(mb_c) > 1) {
|
||||
// A double-wide character is: put first half in left cell.
|
||||
@ -2999,7 +2998,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
wlv.col++;
|
||||
}
|
||||
} else if (wp->w_p_cole > 0 && is_concealing) {
|
||||
n_skip--;
|
||||
wlv.skip_cells--;
|
||||
wlv.vcol_off++;
|
||||
if (wlv.n_extra > 0) {
|
||||
wlv.vcol_off += wlv.n_extra;
|
||||
@ -3055,7 +3054,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
}
|
||||
}
|
||||
} else {
|
||||
n_skip--;
|
||||
wlv.skip_cells--;
|
||||
}
|
||||
|
||||
// The skipped cells need to be accounted for in vcol.
|
||||
|
@ -232,7 +232,8 @@ static void insert_enter(InsertState *s)
|
||||
may_trigger_modechanged();
|
||||
stop_insert_mode = false;
|
||||
|
||||
// need to position cursor again when on a TAB
|
||||
// need to position cursor again when on a TAB and
|
||||
// when on a char with inline virtual text
|
||||
if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
|
||||
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
|
||||
}
|
||||
@ -3471,7 +3472,8 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
|
||||
|
||||
State = MODE_NORMAL;
|
||||
may_trigger_modechanged();
|
||||
// need to position cursor again when on a TAB
|
||||
// need to position cursor again when on a TAB and
|
||||
// when on a char with inline virtual text
|
||||
if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
|
||||
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
|
||||
}
|
||||
|
@ -369,16 +369,19 @@ int lbr_chartabsize_adv(chartabsize_T *cts)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// Get the number of characters taken up on the screen indicated by "cts".
|
||||
/// "cts->cts_cur_text_width_left" and "cts->cts_cur_text_width_right" are set
|
||||
/// to the extra size for inline virtual text.
|
||||
/// This function is used very often, keep it fast!!!!
|
||||
///
|
||||
/// If "headp" not NULL, set *headp to the size of what we for 'showbreak'
|
||||
/// string at start of line. Warning: *headp is only set if it's a non-zero
|
||||
/// value, init to 0 before calling.
|
||||
/// If "headp" not NULL, set "*headp" to the size of 'showbreak'/'breakindent'
|
||||
/// included in the return value.
|
||||
/// When "cts->cts_max_head_vcol" is positive, only count in "*headp" the size
|
||||
/// of 'showbreak'/'breakindent' before "cts->cts_max_head_vcol".
|
||||
/// When "cts->cts_max_head_vcol" is negative, only count in "*headp" the size
|
||||
/// of 'showbreak'/'breakindent' before where cursor should be placed.
|
||||
///
|
||||
/// @param cts
|
||||
/// @param headp
|
||||
///
|
||||
/// @return The number of characters taken up on the screen.
|
||||
/// Warning: "*headp" may not be set if it's 0, init to 0 before calling.
|
||||
int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
||||
{
|
||||
win_T *wp = cts->cts_win;
|
||||
@ -388,7 +391,6 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
||||
|
||||
colnr_T col_adj = 0; // vcol + screen size of tab
|
||||
int mb_added = 0;
|
||||
int numberextra;
|
||||
|
||||
cts->cts_cur_text_width_left = 0;
|
||||
cts->cts_cur_text_width_right = 0;
|
||||
@ -449,7 +451,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
||||
&& (wp->w_width_inner != 0)) {
|
||||
// Count all characters from first non-blank after a blank up to next
|
||||
// non-blank after a blank.
|
||||
numberextra = win_col_off(wp);
|
||||
int numberextra = win_col_off(wp);
|
||||
colnr_T col2 = vcol;
|
||||
colnr_T colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
|
||||
|
||||
@ -490,72 +492,92 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
|
||||
|
||||
// May have to add something for 'breakindent' and/or 'showbreak'
|
||||
// string at start of line.
|
||||
// Set *headp to the size of what we add.
|
||||
// Do not use 'showbreak' at the NUL after the text.
|
||||
int added = 0;
|
||||
int head = mb_added;
|
||||
char *const sbr = c == NUL ? empty_option : get_showbreak_value(wp);
|
||||
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) {
|
||||
colnr_T sbrlen = 0;
|
||||
int numberwidth = win_col_off(wp);
|
||||
|
||||
numberextra = numberwidth;
|
||||
vcol += numberextra + mb_added;
|
||||
|
||||
if (vcol >= (colnr_T)wp->w_width_inner) {
|
||||
vcol -= wp->w_width_inner;
|
||||
numberextra = wp->w_width_inner - (numberextra - win_col_off2(wp));
|
||||
if (vcol >= numberextra && numberextra > 0) {
|
||||
vcol %= numberextra;
|
||||
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap) {
|
||||
int col_off_prev = win_col_off(wp);
|
||||
int width2 = wp->w_width_inner - col_off_prev + win_col_off2(wp);
|
||||
colnr_T wcol = vcol + col_off_prev;
|
||||
// cells taken by 'showbreak'/'breakindent' before current char
|
||||
int head_prev = 0;
|
||||
if (wcol >= wp->w_width_inner) {
|
||||
wcol -= wp->w_width_inner;
|
||||
col_off_prev = wp->w_width_inner - width2;
|
||||
if (wcol >= width2 && width2 > 0) {
|
||||
wcol %= width2;
|
||||
}
|
||||
if (*sbr != NUL) {
|
||||
sbrlen = (colnr_T)mb_charlen(sbr);
|
||||
if (vcol >= sbrlen) {
|
||||
vcol -= sbrlen;
|
||||
head_prev += vim_strsize(sbr);
|
||||
}
|
||||
if (wp->w_p_bri) {
|
||||
head_prev += get_breakindent_win(wp, line);
|
||||
}
|
||||
if (vcol >= numberextra && numberextra > 0) {
|
||||
vcol %= numberextra;
|
||||
} else if (vcol > 0 && numberextra > 0) {
|
||||
vcol += numberwidth - win_col_off2(wp);
|
||||
if (wcol < head_prev) {
|
||||
wcol = head_prev;
|
||||
}
|
||||
wcol += col_off_prev;
|
||||
}
|
||||
|
||||
numberwidth -= win_col_off2(wp);
|
||||
if ((vcol > 0 && wcol == col_off_prev + head_prev)
|
||||
|| wcol + size > wp->w_width_inner) {
|
||||
int added = 0;
|
||||
colnr_T max_head_vcol = cts->cts_max_head_vcol;
|
||||
|
||||
if (vcol > 0 && wcol == col_off_prev + head_prev) {
|
||||
added += head_prev;
|
||||
if (max_head_vcol <= 0 || vcol < max_head_vcol) {
|
||||
head += head_prev;
|
||||
}
|
||||
}
|
||||
|
||||
if (vcol == 0 || (vcol + size + sbrlen > (colnr_T)wp->w_width_inner)) {
|
||||
// cells taken by 'showbreak'/'breakindent' halfway current char
|
||||
int head_mid = 0;
|
||||
if (*sbr != NUL) {
|
||||
if (size + sbrlen + numberwidth > (colnr_T)wp->w_width_inner) {
|
||||
head_mid += vim_strsize(sbr);
|
||||
}
|
||||
if (wp->w_p_bri) {
|
||||
head_mid += get_breakindent_win(wp, line);
|
||||
}
|
||||
if (head_mid > 0) {
|
||||
if (wcol + size > wp->w_width_inner) {
|
||||
// Calculate effective window width.
|
||||
int width = (colnr_T)wp->w_width_inner - sbrlen - numberwidth;
|
||||
int prev_width = vcol ? ((colnr_T)wp->w_width_inner - (sbrlen + vcol))
|
||||
: 0;
|
||||
int prev_rem = wp->w_width_inner - wcol;
|
||||
int width = width2 - head_mid;
|
||||
|
||||
if (width <= 0) {
|
||||
width = 1;
|
||||
}
|
||||
added += ((size - prev_width) / width) * vim_strsize(sbr);
|
||||
if ((size - prev_width) % width) {
|
||||
// Wrapped, add another length of 'sbr'.
|
||||
added += vim_strsize(sbr);
|
||||
}
|
||||
} else {
|
||||
added += vim_strsize(sbr);
|
||||
}
|
||||
}
|
||||
// divide "size - prev_width" by "width", rounding up
|
||||
int cnt = (size - prev_rem + width - 1) / width;
|
||||
added += cnt * head_mid;
|
||||
|
||||
if (wp->w_p_bri) {
|
||||
added += get_breakindent_win(wp, line);
|
||||
if (max_head_vcol == 0 || vcol + size + added < max_head_vcol) {
|
||||
head += cnt * head_mid;
|
||||
} else if (max_head_vcol > vcol + head_prev + prev_rem) {
|
||||
head += (max_head_vcol - (vcol + head_prev + prev_rem)
|
||||
+ width2 - 1) / width2 * head_mid;
|
||||
} else if (max_head_vcol < 0) {
|
||||
int off = 0;
|
||||
if (c != NUL || !(State & MODE_NORMAL)) {
|
||||
off += cts->cts_cur_text_width_left;
|
||||
}
|
||||
if (c != NUL && (State & MODE_NORMAL)) {
|
||||
off += cts->cts_cur_text_width_right;
|
||||
}
|
||||
if (off >= prev_rem) {
|
||||
head += (1 + (off - prev_rem) / width) * head_mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size += added;
|
||||
if (vcol != 0) {
|
||||
added = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (headp != NULL) {
|
||||
*headp = added + mb_added;
|
||||
*headp = head;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ typedef struct {
|
||||
MarkTreeIter cts_iter[1];
|
||||
|
||||
int cts_vcol; ///< virtual column at current position
|
||||
int cts_max_head_vcol; ///< see win_lbr_chartabsize()
|
||||
} chartabsize_T;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
|
@ -2021,7 +2021,7 @@ bbbbbbb]])
|
||||
]]}
|
||||
end)
|
||||
|
||||
it('cursor position is correct with virtual text attached to hard tabs', function()
|
||||
it('cursor position is correct with virtual text attached to hard TABs', function()
|
||||
command('set noexpandtab')
|
||||
feed('i')
|
||||
feed('<TAB>')
|
||||
@ -2692,7 +2692,7 @@ bbbbbbb]])
|
||||
]]}
|
||||
end)
|
||||
|
||||
it('correctly draws when overflowing virtual text is followed by tab with no wrap', function()
|
||||
it('correctly draws when overflowing virtual text is followed by TAB with no wrap', function()
|
||||
command('set nowrap')
|
||||
feed('i<TAB>test<ESC>')
|
||||
meths.buf_set_extmark(
|
||||
@ -2984,6 +2984,328 @@ bbbbbbb]])
|
||||
{8:-- VISUAL BLOCK --} |
|
||||
]]}
|
||||
end)
|
||||
|
||||
local function test_virt_inline_showbreak_smoothscroll()
|
||||
screen:try_resize(30, 6)
|
||||
exec([[
|
||||
highlight! link LineNr Normal
|
||||
call setline(1, repeat('a', 28))
|
||||
setlocal number showbreak=+ breakindent breakindentopt=shift:2
|
||||
setlocal scrolloff=0 smoothscroll
|
||||
normal! $
|
||||
]])
|
||||
meths.buf_set_extmark(0, ns, 0, 27, { virt_text = { { ('123'):rep(23) } }, virt_text_pos = 'inline' })
|
||||
feed(':<CR>') -- Have a screen line that doesn't start with spaces
|
||||
screen:expect{grid=[[
|
||||
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||
{1:+}a1231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}12312312312312312312312|
|
||||
{1:+}3^a |
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}a1231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}12312312312312312312312|
|
||||
{1:+}3^a |
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}12312312312312312312312|
|
||||
{1:+}3^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}12312312312312312312312|
|
||||
{1:+}3^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}3^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('zbi')
|
||||
screen:expect{grid=[[
|
||||
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||
{1:+}a^1231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}12312312312312312312312|
|
||||
{1:+}3a |
|
||||
{8:-- INSERT --} |
|
||||
]]}
|
||||
feed('<BS>')
|
||||
screen:expect{grid=[[
|
||||
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||
{1:+}^12312312312312312312312|
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}a |
|
||||
{8:-- INSERT --} |
|
||||
]]}
|
||||
feed('<Esc>l')
|
||||
feed(':<CR>') -- Have a screen line that doesn't start with spaces
|
||||
screen:expect{grid=[[
|
||||
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
|
||||
{1:+}12312312312312312312312|
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}^a |
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}12312312312312312312312|
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('023x$')
|
||||
screen:expect{grid=[[
|
||||
1 aaa12312312312312312312312|
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
: |
|
||||
]]}
|
||||
feed('zbi')
|
||||
screen:expect{grid=[[
|
||||
1 aaa^12312312312312312312312|
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123123|
|
||||
{1:+}a |
|
||||
{1:~ }|
|
||||
{8:-- INSERT --} |
|
||||
]]}
|
||||
feed('<C-U>')
|
||||
screen:expect{grid=[[
|
||||
1 ^12312312312312312312312312|
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{8:-- INSERT --} |
|
||||
]]}
|
||||
feed('<Esc>')
|
||||
screen:expect{grid=[[
|
||||
1 12312312312312312312312312|
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}31231231231231231231231|
|
||||
{1:+}23123123123123123123^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:+}23123123123123123123^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
end
|
||||
|
||||
describe('with showbreak, smoothscroll', function()
|
||||
it('and cpoptions-=n', function()
|
||||
test_virt_inline_showbreak_smoothscroll()
|
||||
end)
|
||||
|
||||
it('and cpoptions+=n', function()
|
||||
command('set cpoptions+=n')
|
||||
-- because of 'breakindent' the screen states are the same
|
||||
test_virt_inline_showbreak_smoothscroll()
|
||||
end)
|
||||
end)
|
||||
|
||||
it('before TABs with smoothscroll', function()
|
||||
screen:try_resize(30, 6)
|
||||
exec([[
|
||||
call setline(1, repeat("\t", 4) .. 'a')
|
||||
setlocal list listchars=tab:<-> scrolloff=0 smoothscroll
|
||||
normal! $
|
||||
]])
|
||||
meths.buf_set_extmark(0, ns, 0, 3, { virt_text = { { ('12'):rep(32) } }, virt_text_pos = 'inline' })
|
||||
screen:expect{grid=[[
|
||||
{1:<------><------><------>}121212|
|
||||
121212121212121212121212121212|
|
||||
1212121212121212121212121212{1:<-}|
|
||||
{1:----->}^a |
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:<<<}212121212121212121212121212|
|
||||
1212121212121212121212121212{1:<-}|
|
||||
{1:----->}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:<<<}2121212121212121212121212{1:<-}|
|
||||
{1:----->}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:<<<-->}^a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('zbh')
|
||||
screen:expect{grid=[[
|
||||
{1:<------><------><------>}121212|
|
||||
121212121212121212121212121212|
|
||||
1212121212121212121212121212{1:^<-}|
|
||||
{1:----->}a |
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('i')
|
||||
screen:expect{grid=[[
|
||||
{1:<------><------><------>}^121212|
|
||||
121212121212121212121212121212|
|
||||
1212121212121212121212121212{1:<-}|
|
||||
{1:----->}a |
|
||||
{1:~ }|
|
||||
{8:-- INSERT --} |
|
||||
]]}
|
||||
feed('<C-O>:setlocal nolist<CR>')
|
||||
screen:expect{grid=[[
|
||||
^121212|
|
||||
121212121212121212121212121212|
|
||||
1212121212121212121212121212 |
|
||||
a |
|
||||
{1:~ }|
|
||||
{8:-- INSERT --} |
|
||||
]]}
|
||||
feed('<Esc>l')
|
||||
screen:expect{grid=[[
|
||||
121212|
|
||||
121212121212121212121212121212|
|
||||
1212121212121212121212121212 |
|
||||
^ a |
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:<<<}212121212121212121212121212|
|
||||
1212121212121212121212121212 |
|
||||
^ a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:<<<}2121212121212121212121212 |
|
||||
^ a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
feed('<C-E>')
|
||||
screen:expect{grid=[[
|
||||
{1:<<<} ^ a |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('decorations: virtual lines', function()
|
||||
@ -3643,7 +3965,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
||||
end)
|
||||
|
||||
|
||||
it('works with hard tabs', function()
|
||||
it('works with hard TABs', function()
|
||||
insert(example_text2)
|
||||
feed 'gg'
|
||||
meths.buf_set_extmark(0, ns, 1, 0, {
|
||||
|
@ -14,7 +14,7 @@ function s:screen_lines(lnum, width) abort
|
||||
endfunction
|
||||
|
||||
func s:compare_lines(expect, actual)
|
||||
call assert_equal(join(a:expect, "\n"), join(a:actual, "\n"))
|
||||
call assert_equal(a:expect, a:actual)
|
||||
endfunc
|
||||
|
||||
function s:test_windows(...)
|
||||
@ -330,4 +330,47 @@ func Test_list_with_tab_and_skipping_first_chars()
|
||||
\ ]
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
endfu
|
||||
endfunc
|
||||
|
||||
func Test_ctrl_char_on_wrap_column()
|
||||
call s:test_windows("setl nolbr wrap sbr=")
|
||||
call setline(1, 'aaa' .. repeat("\<C-A>", 150) .. 'bbb')
|
||||
call cursor(1,1)
|
||||
norm! $
|
||||
redraw!
|
||||
let expect=[
|
||||
\ '<<<^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^A^A^A^A^A^A^A^A^A^',
|
||||
\ 'A^Abbb ']
|
||||
let lines = s:screen_lines([1, 10], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
call assert_equal(len(expect), winline())
|
||||
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
|
||||
setl sbr=!!
|
||||
redraw!
|
||||
let expect=[
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^A^A^A^',
|
||||
\ '!!A^A^A^A^A^A^Abbb ']
|
||||
let lines = s:screen_lines([1, 10], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
call assert_equal(len(expect), winline())
|
||||
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
|
||||
call s:close_windows()
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -249,7 +249,6 @@ endfunc
|
||||
|
||||
func Test_chinese_char_on_wrap_column()
|
||||
call s:test_windows("setl nolbr wrap sbr=")
|
||||
syntax off
|
||||
call setline(1, [
|
||||
\ 'aaaaaaaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaaaaa中'.
|
||||
@ -278,5 +277,85 @@ func Test_chinese_char_on_wrap_column()
|
||||
\ '中hello ']
|
||||
let lines = s:screen_lines([1, 10], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
call assert_equal(len(expect), winline())
|
||||
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
|
||||
call s:close_windows()
|
||||
endfu
|
||||
endfunc
|
||||
|
||||
func Test_chinese_char_on_wrap_column_sbr()
|
||||
call s:test_windows("setl nolbr wrap sbr=!!!")
|
||||
call setline(1, [
|
||||
\ 'aaaaaaaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'aaaaaaaaaaaaaa中'.
|
||||
\ 'hello'])
|
||||
call cursor(1,1)
|
||||
norm! $
|
||||
redraw!
|
||||
let expect=[
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中aaaaaaaaaaaaaa>',
|
||||
\ '!!!中hello ']
|
||||
let lines = s:screen_lines([1, 10], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
call assert_equal(len(expect), winline())
|
||||
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
|
||||
call s:close_windows()
|
||||
endfunc
|
||||
|
||||
func Test_unprintable_char_on_wrap_column()
|
||||
call s:test_windows("setl nolbr wrap sbr=")
|
||||
call setline(1, 'aaa' .. repeat("\uFEFF", 50) .. 'bbb')
|
||||
call cursor(1,1)
|
||||
norm! $
|
||||
redraw!
|
||||
let expect=[
|
||||
\ '<<<<feff><feff><feff',
|
||||
\ '><feff><feff><feff><',
|
||||
\ 'feff><feff><feff><fe',
|
||||
\ 'ff><feff><feff><feff',
|
||||
\ '><feff><feff><feff><',
|
||||
\ 'feff><feff><feff><fe',
|
||||
\ 'ff><feff><feff><feff',
|
||||
\ '><feff><feff><feff><',
|
||||
\ 'feff><feff><feff><fe',
|
||||
\ 'ff>bbb ']
|
||||
let lines = s:screen_lines([1, 10], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
call assert_equal(len(expect), winline())
|
||||
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
|
||||
setl sbr=!!
|
||||
redraw!
|
||||
let expect=[
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff><feff',
|
||||
\ '!!><feff><feff>bbb ']
|
||||
let lines = s:screen_lines([1, 10], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
call assert_equal(len(expect), winline())
|
||||
call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol())
|
||||
call s:close_windows()
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
Loading…
Reference in New Issue
Block a user