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; n = (wp->w_wcol - wp->w_width_inner) / width2 + 1;
wp->w_wcol -= n * width2; wp->w_wcol -= n * width2;
wp->w_wrow += n; 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 } else if (may_scroll
&& !wp->w_cline_folded) { && !wp->w_cline_folded) {

View File

@ -359,7 +359,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
if (width <= 0) { if (width <= 0) {
width = 1; 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; int cnt = (size - prev_rem + width - 1) / width;
added += cnt * head_mid; added += cnt * head_mid;
@ -371,7 +371,11 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
} else if (max_head_vcol < 0) { } else if (max_head_vcol < 0) {
int off = virt_text_cursor_off(cts, c == NUL); int off = virt_text_cursor_off(cts, c == NUL);
if (off >= prev_rem) { if (off >= prev_rem) {
if (size > off) {
head += (1 + (off - prev_rem) / width) * head_mid; 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:$ set listchars=eol:$
let &signcolumn = 'yes' let &signcolumn = 'yes'
let &showbreak = '++' let &showbreak = '++'
let &breakindent = v:true
let &breakindentopt = 'shift:2' let &breakindentopt = 'shift:2'
let leftcol = win_getid()->getwininfo()->get(0, {})->get('textoff') let leftcol = win_getid()->getwininfo()->get(0, {})->get('textoff')
eval repeat('x', &columns - leftcol - 1)->setline(1) 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. -- No line wraps, so changing 'showbreak' should lead to the same screen.
command('setlocal showbreak=+') command('setlocal showbreak=+')
screen:expect_unchanged() 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'. -- The first line now wraps because of "eol" in 'listchars'.
command('setlocal list') command('setlocal list')
screen:expect{grid=[[ screen:expect{grid=[[
@ -49,5 +51,14 @@ describe('breakindent', function()
{0:~ }| {0:~ }|
{2:-- INSERT --} | {2:-- INSERT --} |
]]} ]]}
command('setlocal nobreakindent')
screen:expect{grid=[[
{1: }xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX|
{1: }{0:+^$} |
{1: }second line{0:$} |
{0:~ }|
{0:~ }|
{2:-- INSERT --} |
]]}
end) end)
end) end)

View File

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