vim-patch:9.0.0099: scrollback can be wrong after redrawing the command line (#19562)

Problem:    Scrollback can be wrong after redrawing the command line.
Solution:   Clear unfinished scrollback when redrawing. (closes vim/vim#10807)
46af7bc08d
This commit is contained in:
zeertzjq 2022-07-28 20:07:32 +08:00 committed by GitHub
parent 9cb8b5f8db
commit f254fc67a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 7 deletions

View File

@ -3823,6 +3823,7 @@ void redrawcmd(void)
redrawing_cmdline = true;
sb_text_restart_cmdline();
msg_start();
redrawcmdprompt();

View File

@ -2503,6 +2503,7 @@ static void store_sb_text(char_u **sb_str, char_u *s, int attr, int *sb_col, int
if (do_clear_sb_text == SB_CLEAR_ALL
|| do_clear_sb_text == SB_CLEAR_CMDLINE_DONE) {
clear_sb_text(do_clear_sb_text == SB_CLEAR_ALL);
msg_sb_eol(); // prevent messages from overlapping
do_clear_sb_text = SB_CLEAR_NONE;
}
@ -2537,18 +2538,47 @@ void may_clear_sb_text(void)
do_clear_sb_text = SB_CLEAR_ALL;
}
/// Starting to edit the command line, do not clear messages now.
/// Starting to edit the command line: do not clear messages now.
void sb_text_start_cmdline(void)
{
do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY;
msg_sb_eol();
if (do_clear_sb_text == SB_CLEAR_CMDLINE_BUSY) {
// Invoking command line recursively: the previous-level command line
// doesn't need to be remembered as it will be redrawn when returning
// to that level.
sb_text_restart_cmdline();
} else {
msg_sb_eol();
do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY;
}
}
/// Ending to edit the command line. Clear old lines but the last one later.
/// Redrawing the command line: clear the last unfinished line.
void sb_text_restart_cmdline(void)
{
// Needed when returning from nested command line.
do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY;
if (last_msgchunk == NULL || last_msgchunk->sb_eol) {
// No unfinished line: don't clear anything.
return;
}
msgchunk_T *tofree = msg_sb_start(last_msgchunk);
last_msgchunk = tofree->sb_prev;
if (last_msgchunk != NULL) {
last_msgchunk->sb_next = NULL;
}
while (tofree != NULL) {
msgchunk_T *tofree_next = tofree->sb_next;
xfree(tofree);
tofree = tofree_next;
}
}
/// Ending to edit the command line: clear old lines but the last one later.
void sb_text_end_cmdline(void)
{
do_clear_sb_text = SB_CLEAR_CMDLINE_DONE;
msg_sb_eol();
}
/// Clear any text remembered for scrolling back.

View File

@ -118,7 +118,9 @@ func Test_message_more()
let buf = RunVimInTerminal('', {'rows': 6})
call term_sendkeys(buf, ":call setline(1, range(1, 100))\n")
call term_sendkeys(buf, ":%p#\n")
call term_sendkeys(buf, ":%pfoo\<C-H>\<C-H>\<C-H>#")
call WaitForAssert({-> assert_equal(':%p#', term_getline(buf, 6))})
call term_sendkeys(buf, "\n")
call WaitForAssert({-> assert_equal(' 5 5', term_getline(buf, 5))})
call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))})
@ -194,6 +196,13 @@ func Test_message_more()
call WaitForAssert({-> assert_equal('100 100', term_getline(buf, 5))})
call WaitForAssert({-> assert_equal('Press ENTER or type command to continue', term_getline(buf, 6))})
" A command line that doesn't print text is appended to scrollback,
" even if it invokes a nested command line.
call term_sendkeys(buf, ":\<C-R>=':'\<CR>:\<CR>g<")
call WaitForAssert({-> assert_equal('100 100', term_getline(buf, 4))})
call WaitForAssert({-> assert_equal(':::', term_getline(buf, 5))})
call WaitForAssert({-> assert_equal('Press ENTER or type command to continue', term_getline(buf, 6))})
call term_sendkeys(buf, ":%p#\n")
call WaitForAssert({-> assert_equal(' 5 5', term_getline(buf, 5))})
call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))})

View File

@ -27,7 +27,16 @@ describe('messages', function()
it('works', function()
command('call setline(1, range(1, 100))')
feed(':%p#\n')
feed(':%pfoo<C-H><C-H><C-H>#')
screen:expect([[
1 |
2 |
3 |
4 |
5 |
:%p#^ |
]])
feed('\n')
screen:expect([[
{2: 1 }1 |
{2: 2 }2 |
@ -241,6 +250,18 @@ describe('messages', function()
{1:Press ENTER or type command to continue}^ |
]])
-- A command line that doesn't print text is appended to scrollback,
-- even if it invokes a nested command line.
feed([[:<C-R>=':'<CR>:<CR>g<lt>]])
screen:expect([[
{2: 97 }97 |
{2: 98 }98 |
{2: 99 }99 |
{2:100 }100 |
::: |
{1:Press ENTER or type command to continue}^ |
]])
feed(':%p#\n')
screen:expect([[
{2: 1 }1 |