From e3bd04f2aff738722c06276cc926d4bdd4501402 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 18 Mar 2024 22:25:55 +0800 Subject: [PATCH] fix(pager): handle consecutive newlines properly (#27913) --- src/nvim/eval.c | 10 +- src/nvim/message.c | 15 ++- test/functional/ui/messages_spec.lua | 173 +++++++++++++++++++++++++++ 3 files changed, 189 insertions(+), 9 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index e4ee254193..f5f9c4f77b 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8085,10 +8085,12 @@ void ex_echo(exarg_T *eap) // Call msg_start() after eval1(), evaluating the expression // may cause a message to appear. if (eap->cmdidx == CMD_echo) { - // Mark the saved text as finishing the line, so that what - // follows is displayed on a new line when scrolling back - // at the more prompt. - msg_sb_eol(); + if (!msg_didout) { + // Mark the saved text as finishing the line, so that what + // follows is displayed on a new line when scrolling back + // at the more prompt. + msg_sb_eol(); + } msg_start(); } } else if (eap->cmdidx == CMD_echo) { diff --git a/src/nvim/message.c b/src/nvim/message.c index 2725ad02c6..5a47908eb6 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1191,7 +1191,7 @@ void wait_return(int redraw) check_timestamps(false); } - hit_return_msg(); + hit_return_msg(true); do { // Remember "got_int", if it is set vgetc() probably returns a @@ -1240,7 +1240,7 @@ void wait_return(int redraw) got_int = false; } else if (c != K_IGNORE) { c = K_IGNORE; - hit_return_msg(); + hit_return_msg(false); } } else if (msg_scrolled > Rows - 2 && (c == 'j' || c == 'd' || c == 'f' @@ -1313,14 +1313,19 @@ void wait_return(int redraw) } /// Write the hit-return prompt. -static void hit_return_msg(void) +/// +/// @param newline_sb if starting a new line, add it to the scrollback. +static void hit_return_msg(bool newline_sb) { int save_p_more = p_more; - p_more = false; // don't want to see this message when scrolling back + if (!newline_sb) { + p_more = false; + } if (msg_didout) { // start on a new line msg_putchar('\n'); } + p_more = false; // don't want to see this message when scrolling back msg_ext_set_kind("return_prompt"); if (got_int) { msg_puts(_("Interrupt: ")); @@ -2968,7 +2973,7 @@ void repeat_message(void) msg_col = 0; msg_clr_eos(); } - hit_return_msg(); + hit_return_msg(false); msg_row = Rows - 1; } } diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 6b71d85861..32d3359a0b 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -10,6 +10,7 @@ local api = helpers.api local async_meths = helpers.async_meths local test_build_dir = helpers.paths.test_build_dir local nvim_prog = helpers.nvim_prog +local testprg = helpers.testprg local exec = helpers.exec local exec_capture = helpers.exec_capture local exc_exec = helpers.exc_exec @@ -2498,6 +2499,178 @@ aliquip ex ea commodo consequat.]] ]], } end) + + it('g< shows blank line from :echo properly', function() + screen:try_resize(60, 8) + feed([[:echo 1 | echo "\n" | echo 2]]) + screen:expect([[ + | + {1:~ }|*2 + {12: }| + 1 | + | + 2 | + {4:Press ENTER or type command to continue}^ | + ]]) + + feed('') + screen:expect([[ + ^ | + {1:~ }|*6 + | + ]]) + + feed('g') + screen:expect([[ + | + {1:~ }| + {12: }| + :echo 1 | echo "\n" | echo 2 | + 1 | + | + 2 | + {4:Press ENTER or type command to continue}^ | + ]]) + + feed('') + screen:expect([[ + ^ | + {1:~ }|*6 + | + ]]) + end) + + it('scrolling works properly when :echo output ends with newline', function() + screen:try_resize(60, 6) + feed([[:echo range(100)->join("\n") .. "\n"]]) + screen:expect([[ + 0 | + 1 | + 2 | + 3 | + 4 | + {4:-- More --}^ | + ]]) + feed('G') + screen:expect([[ + 96 | + 97 | + 98 | + 99 | + | + {4:Press ENTER or type command to continue}^ | + ]]) + for _ = 1, 3 do + feed('k') + screen:expect([[ + 95 | + 96 | + 97 | + 98 | + 99 | + {4:-- More --}^ | + ]]) + feed('k') + screen:expect([[ + 94 | + 95 | + 96 | + 97 | + 98 | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 95 | + 96 | + 97 | + 98 | + 99 | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96 | + 97 | + 98 | + 99 | + | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96 | + 97 | + 98 | + 99 | + | + {4:Press ENTER or type command to continue}^ | + ]]) + end + end) + + it('scrolling works properly when :!cmd output ends with newline #27902', function() + screen:try_resize(60, 6) + api.nvim_set_option_value('shell', testprg('shell-test'), {}) + api.nvim_set_option_value('shellcmdflag', 'REP 100', {}) + api.nvim_set_option_value('shellxquote', '', {}) -- win: avoid extra quotes + feed([[:!foo]]) + screen:expect([[ + 96: foo | + 97: foo | + 98: foo | + 99: foo | + | + {4:Press ENTER or type command to continue}^ | + ]]) + for _ = 1, 3 do + feed('k') + screen:expect([[ + 95: foo | + 96: foo | + 97: foo | + 98: foo | + 99: foo | + {4:-- More --}^ | + ]]) + feed('k') + screen:expect([[ + 94: foo | + 95: foo | + 96: foo | + 97: foo | + 98: foo | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 95: foo | + 96: foo | + 97: foo | + 98: foo | + 99: foo | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96: foo | + 97: foo | + 98: foo | + 99: foo | + | + {4:-- More --}^ | + ]]) + feed('j') + screen:expect([[ + 96: foo | + 97: foo | + 98: foo | + 99: foo | + | + {4:Press ENTER or type command to continue}^ | + ]]) + end + end) end) it('pager works in headless mode with UI attached', function()