diff options
-rw-r--r-- | src/nvim/ex_getln.c | 1 | ||||
-rw-r--r-- | src/nvim/message.c | 38 | ||||
-rw-r--r-- | src/nvim/testdir/test_messages.vim | 11 | ||||
-rw-r--r-- | test/functional/legacy/messages_spec.lua | 23 |
4 files changed, 67 insertions, 6 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1ee8581e00..4c17fdae02 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3823,6 +3823,7 @@ void redrawcmd(void) redrawing_cmdline = true; + sb_text_restart_cmdline(); msg_start(); redrawcmdprompt(); diff --git a/src/nvim/message.c b/src/nvim/message.c index 3a6c690ff6..80d11c096b 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -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) { + 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; + } +} + +/// 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; - msg_sb_eol(); + + 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. +/// 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. diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index 4be5a1b076..2f9c562771 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -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))}) diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua index 7bcbecc582..51c2406933 100644 --- a/test/functional/legacy/messages_spec.lua +++ b/test/functional/legacy/messages_spec.lua @@ -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 | |