fix(ui): wrong cursor position with left gravity inline virt text at eol

This commit is contained in:
zeertzjq 2023-08-24 07:27:18 +08:00
parent abb8c2c453
commit 128091a256
4 changed files with 112 additions and 59 deletions

View File

@ -862,15 +862,6 @@ void curs_columns(win_T *wp, int may_scroll)
n = (wp->w_wcol - wp->w_width_inner) / width2 + 1;
wp->w_wcol -= n * width2;
wp->w_wrow += n;
// When cursor wraps to first char of next line in Insert
// mode, the 'showbreak' string isn't shown, backup to first
// column
char *const sbr = get_showbreak_value(wp);
if (*sbr && *get_cursor_pos_ptr() == NUL
&& wp->w_wcol == (wp->w_width_inner - width2) + vim_strsize(sbr)) {
wp->w_wcol = 0;
}
}
} else if (may_scroll
&& !wp->w_cline_folded) {

View File

@ -359,7 +359,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
if (width <= 0) {
width = 1;
}
// divide "size - prev_width" by "width", rounding up
// Divide "size - prev_rem" by "width", rounding up.
int cnt = (size - prev_rem + width - 1) / width;
added += cnt * head_mid;
@ -371,7 +371,11 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
} else if (max_head_vcol < 0) {
int off = virt_text_cursor_off(cts, c == NUL);
if (off >= prev_rem) {
head += (1 + (off - prev_rem) / width) * head_mid;
if (size > off) {
head += (1 + (off - prev_rem) / width) * head_mid;
} else {
head += (off - prev_rem + width - 1) / width * head_mid;
}
}
}
}

View File

@ -21,7 +21,6 @@ describe('breakindent', function()
set listchars=eol:$
let &signcolumn = 'yes'
let &showbreak = '++'
let &breakindent = v:true
let &breakindentopt = 'shift:2'
let leftcol = win_getid()->getwininfo()->get(0, {})->get('textoff')
eval repeat('x', &columns - leftcol - 1)->setline(1)
@ -39,6 +38,9 @@ describe('breakindent', function()
-- No line wraps, so changing 'showbreak' should lead to the same screen.
command('setlocal showbreak=+')
screen:expect_unchanged()
-- No line wraps, so setting 'breakindent' should lead to the same screen.
command('setlocal breakindent')
screen:expect_unchanged()
-- The first line now wraps because of "eol" in 'listchars'.
command('setlocal list')
screen:expect{grid=[[
@ -49,5 +51,14 @@ describe('breakindent', function()
{0:~ }|
{2:-- INSERT --} |
]]}
command('setlocal nobreakindent')
screen:expect{grid=[[
{1: }xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX|
{1: }{0:+^$} |
{1: }second line{0:$} |
{0:~ }|
{0:~ }|
{2:-- INSERT --} |
]]}
end)
end)

View File

@ -2209,111 +2209,119 @@ bbbbbbb]])
end)
it('cursor position is correct when inserting around a virtual text with left gravity', function()
insert('foo foo foo foo')
meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
feed('0')
feed('8l')
screen:try_resize(27, 4)
insert(('a'):rep(15))
meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { ('>'):rep(43), 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
command('setlocal showbreak=+ breakindent breakindentopt=shift:2')
feed('08l')
screen:expect{grid=[[
foo foo {10:virtual text}^foo foo |
{1:~ }|
|
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}^aaaaaaa |
|
]]}
feed('i')
screen:expect{grid=[[
foo foo {10:virtual text}^foo foo |
{1:~ }|
{8:-- INSERT --} |
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}^aaaaaaa |
{8:-- INSERT --} |
]]}
feed([[<C-\><C-O>]])
screen:expect{grid=[[
foo foo {10:virtual text}^foo foo |
{1:~ }|
{8:-- (insert) --} |
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}^aaaaaaa |
{8:-- (insert) --} |
]]}
feed('D')
screen:expect{grid=[[
foo foo {10:virtual text}^ |
{1:~ }|
{8:-- INSERT --} |
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:^~ }|
{8:-- INSERT --} |
]]}
command('setlocal list listchars=eol:$')
screen:expect{grid=[[
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+^$} |
{8:-- INSERT --} |
]]}
feed('<C-U>')
screen:expect{grid=[[
{10:virtual text}^ |
{1:~ }|
{8:-- INSERT --} |
{10:>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>}{1:^$} |
{1:~ }|
{8:-- INSERT --} |
]]}
feed('a')
screen:expect{grid=[[
{10:virtual text}a^ |
{1:~ }|
{8:-- INSERT --} |
{10:>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>}a{1:^$} |
{1:~ }|
{8:-- INSERT --} |
]]}
feed('<Esc>')
screen:expect{grid=[[
{10:virtual text}^a |
{1:~ }|
|
{10:>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>}^a{1:$} |
{1:~ }|
|
]]}
feed('x')
screen:expect{grid=[[
{10:^virtual text} |
{1:~ }|
|
{10:^>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>>>>>>>}{1:$} |
{1:~ }|
|
]]}
end)
it('cursor position is correct when inserting around virtual texts with both left and right gravity', function()
screen:try_resize(30, 4)
command('setlocal showbreak=+ breakindent breakindentopt=shift:2')
insert('foo foo foo foo')
insert(('a'):rep(15))
meths.buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('>'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = false })
meths.buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('<'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = true })
feed('08l')
screen:expect{grid=[[
foo foo {10:>>>>>>>>>>>>>>>>>>>>>>}|
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>><<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<<<<<<<<<<<<<}^foo foo |
{1:+}{10:<<<<<<<<<<<<<<<}^aaaaaaa |
|
]]}
feed('i')
screen:expect{grid=[[
foo foo {10:>>>>>>>>>>>>>>>>>>>>>>}|
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>^<<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<<<<<<<<<<<<<}foo foo |
{1:+}{10:<<<<<<<<<<<<<<<}aaaaaaa |
{8:-- INSERT --} |
]]}
feed('a')
screen:expect{grid=[[
foo foo {10:>>>>>>>>>>>>>>>>>>>>>>}|
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>}a{10:^<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<<<<<<<<<<<<<<}foo foo |
{1:+}{10:<<<<<<<<<<<<<<<<}aaaaaaa |
{8:-- INSERT --} |
]]}
feed([[<C-\><C-O>]])
screen:expect{grid=[[
foo foo {10:>>>>>>>>>>>>>>>>>>>>>>}|
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>}a{10:<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<<<<<<<<<<<<<<}^foo foo |
{1:+}{10:<<<<<<<<<<<<<<<<}^aaaaaaa |
{8:-- (insert) --} |
]]}
feed('D')
screen:expect{grid=[[
foo foo {10:>>>>>>>>>>>>>>>>>>>>>>}|
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>}a{10:^<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<<<<<<<<<<<<<<} |
{8:-- INSERT --} |
]]}
feed('<BS>')
screen:expect{grid=[[
foo foo {10:>>>>>>>>>>>>>>>>>>>>>>}|
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>>>>>>>>>^<<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<<<<<<<<<<<<<} |
{8:-- INSERT --} |
@ -2346,6 +2354,27 @@ bbbbbbb]])
{1:+}{10:<<<<<<<} |
|
]]}
feed('i')
screen:expect{grid=[[
{10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:>>^<<<<<<<<<<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<<<<<} |
{8:-- INSERT --} |
]]}
screen:try_resize(32, 4)
screen:expect{grid=[[
{10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<}|
{1:+}{10:<<<} |
{8:-- INSERT --} |
]]}
command('setlocal nobreakindent')
screen:expect{grid=[[
{10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
{1:+}{10:^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<}|
{1:+}{10:<} |
{8:-- INSERT --} |
]]}
end)
it('draws correctly with no wrap multiple virtual text, where one is hidden', function()
@ -3002,6 +3031,24 @@ bbbbbbb]])
{1:~ }|
|
]]}
feed('26ia<Esc>a')
screen:expect{grid=[[
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:+}^12312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:~ }|
{8:-- INSERT --} |
]]}
feed([[<C-\><C-O>:setlocal breakindentopt=<CR>]])
screen:expect{grid=[[
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:+}^1231231231231231231231231|
{1:+}2312312312312312312312312|
{1:+}3123123123123123123 |
{1:~ }|
{8:-- INSERT --} |
]]}
end
describe('with showbreak, smoothscroll', function()