fix(ui)!: decouple ext_messages from message grid #27963

Problem:  ext_messages is implemented to mimic the message grid
          implementation w.r.t. scrolling messages, clearing scrolled
          messages, hit-enter-prompts and replacing a previous message.
          Meanwhile, an ext_messages UI may not be implemented in a way
          where these events are wanted. Moreover, correctness of these
          events even assuming a "scrolled message" implementation
          depends on fragile "currently visible messages" global state,
          which already isn't correct after a previous message was
          supposed to have been overwritten (because that should not only
          happen when `msg_scroll == false`).

Solution: - No longer attempt to keep track of the currently visible
            messages: remove the `msg_ext(_history)_visible` variables.
            UIs may remove messages pre-emptively (timer based), or never
            show messages that don't fit a certain area in the first place.
          - No longer emit the `msg(_history)_clear` events to clear
            "scrolled" messages. This opens up the `msg_clear` event to
            be emitted when messages should actually be cleared (e.g.
            when the screen is cleared). May also be useful to emit before
            the first message in an event loop cycle as a hint to the UI
            that it is a new batch of messages (vim._extui currently
            schedules an event to determine that).
          - Set `replace_last` explicitly at the few callsites that want
            this to be set to true to replace an incomplete status message.
          - Don't store a "keep" message to be re-emitted.
This commit is contained in:
luukvbaal
2025-06-25 17:25:40 +02:00
committed by GitHub
parent 0694ca8822
commit 4369d7d9a7
14 changed files with 115 additions and 369 deletions

View File

@ -67,7 +67,10 @@ EDITOR
EVENTS
todo
|ui-messages| no longer emits the `msg_show.return_prompt`, `msg_clear` and
`msg_history_clear` events. These events arbitrarily assume a message UI
mimicking the legacy message grid. Benefit: reduced UI event traffic and
more flexibility for UIs.
HIGHLIGHTS

View File

@ -836,7 +836,6 @@ must handle.
"lua_error" Error in |:lua| code
"lua_print" |print()| from |:lua| code
"rpc_error" Error response from |rpcrequest()|
"return_prompt" |press-enter| prompt after a multiple messages
"quickfix" Quickfix navigation message
"search_cmd" Entered search command
"search_count" Search count message ("S" flag of 'shortmess')
@ -894,7 +893,4 @@ must handle.
Sent when |:messages| command is invoked. History is sent as a list of
entries, where each entry is a `[kind, content, append]` tuple.
["msg_history_clear"] ~
Clear the |:messages| history.
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -174,8 +174,6 @@ void msg_ruler(Array content)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
void msg_history_show(Array entries)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
void msg_history_clear(void)
FUNC_API_SINCE(10) FUNC_API_REMOTE_ONLY;
// This UI event is currently undocumented.
// - When the server needs to intentionally exit with an exit code, and there is no

View File

@ -1763,7 +1763,6 @@ restore_backup:
if (msg_add_fileformat(fileformat)) {
insert_space = true;
}
msg_ext_set_kind("bufwrite");
msg_add_lines(insert_space, lnum, nchars); // add line/char count
if (!shortmess(SHM_WRITE)) {
if (append) {
@ -1773,6 +1772,8 @@ restore_backup:
}
}
msg_ext_set_kind("bufwrite");
msg_ext_overwrite = true;
set_keep_msg(msg_trunc(IObuff, false, 0), 0);
}

View File

@ -552,7 +552,6 @@ int update_screen(void)
}
win_ui_flush(true);
msg_ext_check_clear();
// reset cmdline_row now (may have been changed temporarily)
compute_cmdrow();
@ -965,10 +964,6 @@ int showmode(void)
{
int length = 0;
if (ui_has(kUIMessages) && clear_cmdline) {
msg_ext_clear(true);
}
// Don't make non-flushed message part of the showmode.
msg_ext_ui_flush();

View File

@ -751,9 +751,6 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
gotocmdline(true);
redrawcmdprompt(); // draw prompt or indent
ccline.cmdspos = cmd_startcol();
if (!msg_scroll) {
msg_ext_clear(false);
}
}
s->xpc.xp_context = EXPAND_NOTHING;
s->xpc.xp_backslash = XP_BS_NONE;
@ -965,7 +962,6 @@ theend:
if (ui_has(kUICmdline)) {
ui_ext_cmdline_hide(s->gotesc);
msg_ext_clear_later();
}
if (!cmd_silent) {
redraw_custom_title_later();

View File

@ -157,13 +157,6 @@ static sattr_T msg_ext_last_attr = -1;
static int msg_ext_last_hl_id;
static bool msg_ext_history = false; ///< message was added to history
static bool msg_ext_overwrite = false; ///< will overwrite last message
static int msg_ext_visible = 0; ///< number of messages currently visible
static bool msg_ext_history_visible = false;
/// Shouldn't clear message after leaving cmdline
static bool msg_ext_keep_after_cmdline = false;
static int msg_grid_pos_at_flush = 0;
@ -1223,8 +1216,6 @@ void ex_messages(exarg_T *eap)
if (kv_size(entries) > 0) {
ui_call_msg_history_show(entries);
api_free_array(entries);
msg_ext_history_visible = true;
wait_return(false);
}
}
@ -1232,7 +1223,6 @@ void ex_messages(exarg_T *eap)
/// and a delay.
void msg_end_prompt(void)
{
msg_ext_clear_later();
need_wait_return = false;
emsg_on_display = false;
cmdline_row = msg_row;
@ -1256,6 +1246,11 @@ void wait_return(int redraw)
redraw_all_later(UPD_NOT_VALID);
}
if (ui_has(kUIMessages)) {
prompt_for_input("Press any key to continue", HLF_M, true, NULL);
return;
}
// If using ":silent cmd", don't wait for a return. Also don't set
// need_wait_return to do it later.
if (msg_silent != 0) {
@ -1404,7 +1399,6 @@ void wait_return(int redraw)
}
skip_redraw = true; // skip redraw once
do_redraw = false;
msg_ext_keep_after_cmdline = true;
}
// If the screen size changed screen_resize() will redraw the screen.
@ -1430,9 +1424,6 @@ void wait_return(int redraw)
if (redraw == true || (msg_scrolled != 0 && redraw != -1)) {
redraw_later(curwin, UPD_VALID);
}
if (ui_has(kUIMessages)) {
msg_ext_clear(true);
}
}
}
@ -1450,8 +1441,6 @@ static void hit_return_msg(bool newline_sb)
msg_putchar('\n');
}
p_more = false; // don't want to see this message when scrolling back
msg_ext_skip_flush = false;
msg_ext_set_kind("return_prompt");
if (got_int) {
msg_puts(_("Interrupt: "));
}
@ -1466,6 +1455,11 @@ static void hit_return_msg(bool newline_sb)
/// Set "keep_msg" to "s". Free the old value and check for NULL pointer.
void set_keep_msg(const char *s, int hl_id)
{
// Kept message is not cleared and re-emitted with ext_messages: #20416.
if (ui_has(kUIMessages)) {
return;
}
xfree(keep_msg);
if (s != NULL && msg_silent == 0) {
keep_msg = xstrdup(s);
@ -1577,10 +1571,6 @@ void msg_start(void)
if (ui_has(kUIMessages)) {
msg_ext_ui_flush();
if (!msg_scroll && msg_ext_visible) {
// Will overwrite last message.
msg_ext_overwrite = true;
}
}
// When redirecting, may need to start a new line.
@ -2177,16 +2167,7 @@ void msg_puts_len(const char *const str, const ptrdiff_t len, int hl_id, bool hi
// need_wait_return after some prompt, and then outputting something
// without scrolling
// Not needed when only using CR to move the cursor.
bool overflow = false;
if (ui_has(kUIMessages)) {
int count = msg_ext_visible + (msg_ext_overwrite ? 0 : 1);
// TODO(bfredl): possible extension point, let external UI control this
if (count > 1) {
overflow = true;
}
} else {
overflow = msg_scrolled > (p_ch == 0 ? 1 : 0);
}
bool overflow = !ui_has(kUIMessages) && msg_scrolled > (p_ch == 0 ? 1 : 0);
if (overflow && !msg_scrolled_ign && strcmp(str, "\r") != 0) {
need_wait_return = true;
@ -2516,7 +2497,6 @@ void msg_scroll_flush(void)
void msg_reset_scroll(void)
{
if (ui_has(kUIMessages)) {
msg_ext_clear(true);
return;
}
// TODO(bfredl): some duplicate logic with update_screen(). Later on
@ -2713,7 +2693,6 @@ void show_sb_text(void)
{
if (ui_has(kUIMessages)) {
exarg_T ea = { .arg = "", .skip = true };
msg_ext_clear(true);
ex_messages(&ea);
return;
}
@ -3202,7 +3181,7 @@ void msg_ext_ui_flush(void)
Array *tofree = msg_ext_init_chunks();
ui_call_msg_show(cstr_as_string(msg_ext_kind), *tofree, msg_ext_overwrite, msg_ext_history,
msg_ext_append);
if (msg_ext_history || strequal(msg_ext_kind, "return_prompt")) {
if (msg_ext_history) {
api_free_array(*tofree);
} else {
// Add to history as temporary message for "g<".
@ -3216,9 +3195,6 @@ void msg_ext_ui_flush(void)
msg_hist_add_multihl(msg, true);
}
xfree(tofree);
if (!msg_ext_overwrite) {
msg_ext_visible++;
}
msg_ext_overwrite = false;
msg_ext_history = false;
msg_ext_append = false;
@ -3243,44 +3219,6 @@ void msg_ext_flush_showmode(void)
}
}
void msg_ext_clear(bool force)
{
if (msg_ext_visible && (!msg_ext_keep_after_cmdline || force)) {
ui_call_msg_clear();
msg_ext_visible = 0;
msg_ext_overwrite = false; // nothing to overwrite
}
if (msg_ext_history_visible) {
ui_call_msg_history_clear();
msg_ext_history_visible = false;
}
// Only keep once.
msg_ext_keep_after_cmdline = false;
}
void msg_ext_clear_later(void)
{
if (msg_ext_is_visible()) {
msg_ext_need_clear = true;
set_must_redraw(UPD_VALID);
}
}
void msg_ext_check_clear(void)
{
// Redraw after cmdline or prompt is expected to clear messages.
if (msg_ext_need_clear) {
msg_ext_clear(true);
msg_ext_need_clear = false;
}
}
bool msg_ext_is_visible(void)
{
return ui_has(kUIMessages) && msg_ext_visible > 0;
}
/// If the written message runs into the shown command or ruler, we have to
/// wait for hit-return and redraw the window later.
void msg_check(void)

View File

@ -31,10 +31,12 @@ enum {
extern MessageHistoryEntry *msg_hist_last;
EXTERN bool msg_ext_need_clear INIT( = false);
// Set to true to force grouping a set of message chunks into a single `cmdline_show` event.
/// Set to true to force grouping a set of message chunks into a single `cmdline_show` event.
EXTERN bool msg_ext_skip_flush INIT( = false);
// Set to true when message should be appended to previous message line.
/// Set to true when message should be appended to previous message line.
EXTERN bool msg_ext_append INIT( = false);
/// Set to true when previous message should be overwritten.
EXTERN bool msg_ext_overwrite INIT( = false);
/// allocated grid for messages. Used unless ext_messages is active.
/// See also the description at msg_scroll_flush()

View File

@ -1377,9 +1377,8 @@ static void normal_redraw(NormalState *s)
curbuf->b_last_used = time(NULL);
// Display message after redraw. If an external message is still visible,
// it contains the kept message already.
if (keep_msg != NULL && !msg_ext_is_visible()) {
// Display message after redraw.
if (keep_msg != NULL) {
char *const p = xstrdup(keep_msg);
// msg_start() will set keep_msg to NULL, make a copy

View File

@ -2681,6 +2681,7 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh
// keep the message even after redraw, but don't put in history
msg_hist_off = true;
msg_ext_overwrite = true;
msg_ext_set_kind("search_count");
give_warning(msgbuf, false);
msg_hist_off = false;

View File

@ -748,12 +748,6 @@ void ui_call_event(char *name, bool fast, Array args)
bool handled = false;
UIEventCallback *event_cb;
// Return prompt is still a non-fast event, other prompt messages are
// followed by a "cmdline_show" event.
if (strcmp(name, "msg_show") == 0) {
fast = !strequal(args.items[0].data.string.data, "return_prompt");
}
map_foreach(&ui_event_cbs, ui_event_ns_id, event_cb, {
Error err = ERROR_INIT;
uint32_t ns_id = ui_event_ns_id;

View File

@ -203,6 +203,10 @@ describe('vim.ui_attach', function()
{1:~ }|*4
]],
cmdline = { { abort = false } },
condition = function()
eq('list_cmd', screen.messages[1].kind)
screen.messages = {} -- Ignore the build dependent :version content
end,
})
feed([[:call confirm("Save changes?", "&Yes\n&No\n&Cancel")<CR>]])
screen:expect({
@ -440,104 +444,57 @@ describe('vim.ui_attach', function()
end)
it('detaches after excessive errors', function()
local screen = Screen.new(86, 10)
local screen = Screen.new(66, 10)
screen:add_extra_attr_ids({ [100] = { bold = true, foreground = Screen.colors.SeaGreen } })
exec_lua([[
vim.ui_attach(vim.api.nvim_create_namespace(''), { ext_messages = true }, function(ev)
if ev:find('msg') then
if ev == 'msg_show' then
vim.api.nvim_buf_set_lines(0, -2, -1, false, { err[1] })
end
end)
]])
local s1 = [[
^ |
{1:~ }|*9
]]
screen:expect(s1)
feed('Q<CR>')
feed('Q')
screen:expect({
grid = s1,
messages = {
{
content = { { "E354: Invalid register name: '^@'", 9, 6 } },
history = true,
kind = 'emsg',
},
{
content = {
{
'Lua callback:\n[string "<nvim>"]:3: attempt to index global \'err\' (a nil value)\nstack traceback:\n\t[string "<nvim>"]:3: in function <[string "<nvim>"]:1>',
9,
6,
},
},
history = true,
kind = 'lua_error',
},
{
content = { { 'Press ENTER or type command to continue', 100, 18 } },
kind = 'return_prompt',
},
},
grid = [[
|
{1:~ }|*5
{3: }|
{9:Error in "msg_show" UI event handler (ns=(UNKNOWN PLUGIN)):} |
{9:fast context failure} |
{100:Press ENTER or type command to continue}^ |
]],
condition = function()
screen.messages = {}
end,
})
feed('<CR>:messages<CR>')
feed('<Esc>')
screen:expect([[
{9:Error in "msg_show" UI event handler (ns=(UNKNOWN PLUGIN)):} |
{9:Lua: [string "<nvim>"]:3: attempt to index global 'err' (a nil value)} |
{9:stack traceback:} |
{9: [string "<nvim>"]:3: in function <[string "<nvim>"]:1>} |
{9:Error in "msg_clear" UI event handler (ns=(UNKNOWN PLUGIN)):} |
{9:Lua: [string "<nvim>"]:3: attempt to index global 'err' (a nil value)} |
{9:stack traceback:} |
{9: [string "<nvim>"]:3: in function <[string "<nvim>"]:1>} |
{9:Excessive errors in vim.ui_attach() callback (ns=(UNKNOWN PLUGIN))} |
{100:Press ENTER or type command to continue}^ |
^ |
{1:~ }|*8
|
]])
feed('<CR>')
-- Also when scheduled
exec_lua([[
vim.ui_attach(vim.api.nvim_create_namespace(''), { ext_messages = true }, function()
vim.schedule(function() vim.api.nvim_buf_set_lines(0, -2, -1, false, { err[1] }) end)
vim.ui_attach(vim.api.nvim_create_namespace(''), { ext_messages = true }, function(ev)
if ev == 'msg_show' then
vim.schedule(function() vim.api.nvim_buf_set_lines(0, -2, -1, false, { err[1] }) end)
end
end)
]])
feed('Q')
screen:expect({
grid = s1,
messages = {
{
content = {
{
'vim.schedule callback: [string "<nvim>"]:2: attempt to index global \'err\' (a nil value)\nstack traceback:\n\t[string "<nvim>"]:2: in function <[string "<nvim>"]:2>',
9,
6,
},
},
history = true,
kind = 'lua_error',
},
{
content = {
{
'vim.schedule callback: [string "<nvim>"]:2: attempt to index global \'err\' (a nil value)\nstack traceback:\n\t[string "<nvim>"]:2: in function <[string "<nvim>"]:2>',
9,
6,
},
},
history = true,
kind = 'lua_error',
},
{
content = { { 'Press ENTER or type command to continue', 100, 18 } },
kind = 'return_prompt',
},
},
grid = [[
|
{1:~ }|*6
{3: }|
{9:Excessive errors in vim.ui_attach() callback (ns=(UNKNOWN PLUGIN))}|
{100:Press ENTER or type command to continue}^ |
]],
condition = function()
screen.messages = {}
end,
})
feed('<Esc>:1messages clear<cr>:messages<CR>')
screen:expect([[
^ |
{1:~ }|*8
{9:Excessive errors in vim.ui_attach() callback (ns=(UNKNOWN PLUGIN))} |
]])
end)
it('sourcing invalid file does not crash #32166', function()

View File

@ -40,34 +40,6 @@ describe('ui/ext_messages', function()
os.remove(fname)
end)
it('msg_clear follows msg_show kind of confirm', function()
feed('iline 1<esc>')
feed(':call confirm("test")<cr>')
local s1 = [[
line ^1 |
{1:~ }|*4
]]
screen:expect({
grid = s1,
cmdline = {
{
content = { { '' } },
hl_id = 10,
pos = 0,
prompt = '[O]k: ',
},
},
messages = {
{
content = { { '\ntest\n', 6, 10 } },
kind = 'confirm',
},
},
})
feed('<cr>')
screen:expect({ grid = s1, cmdline = { { abort = false } } })
end)
it('msg_show kinds', function()
feed('iline 1\nline 2<esc>')
@ -100,21 +72,12 @@ describe('ui/ext_messages', function()
grid = s1,
cmdline = { { abort = false } },
messages = {
{
content = { { '\ntest\n', 6, 10 } },
kind = 'confirm',
},
{
content = { { '1' } },
kind = 'echo',
},
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
})
feed('<cr>')
-- :substitute confirm is now cmdline prompt
feed(':%s/i/X/gc<cr>')
@ -136,6 +99,8 @@ describe('ui/ext_messages', function()
feed('nq')
-- kind=wmsg (editing readonly file)
local byte = t.is_os('win') and 16 or 14
local writemsg = ('"Xtest_functional_ui_messages_spec" [New] 2L, %dB written'):format(byte)
command('write ' .. fname)
command('set readonly nohls')
feed('G$x')
@ -147,6 +112,7 @@ describe('ui/ext_messages', function()
]],
cmdline = { { abort = false } },
messages = {
{ content = { { writemsg } }, history = true, kind = 'bufwrite' },
{
content = { { 'W10: Warning: Changing a readonly file', 19, 26 } },
history = true,
@ -161,6 +127,12 @@ describe('ui/ext_messages', function()
grid = s1,
cmdline = { { abort = false } },
messages = {
{
content = { { '1 change; before #2 0 seconds ago' } },
history = true,
kind = 'undo',
},
{ content = { { '/i ' } }, kind = 'search_cmd' },
{
content = { { 'search hit BOTTOM, continuing at TOP', 19, 26 } },
history = true,
@ -186,7 +158,6 @@ describe('ui/ext_messages', function()
}
-- kind=quickfix after :cnext
feed('<c-c>')
command("caddexpr [expand('%').':1:line1',expand('%').':2:line2']")
feed(':cnext<CR>$')
screen:expect {
@ -238,7 +209,20 @@ describe('ui/ext_messages', function()
})
-- undo
feed('uu')
feed('u')
screen:expect({
grid = [[
^ |
{1:~ }|*4
]],
condition = function()
local msg = screen.messages[1].content[1][2]:gsub('%d seconds?', '0 seconds')
eq('2 fewer lines; before #1 0 seconds ago', msg)
eq('undo', screen.messages[1].kind)
screen.messages = {}
end,
})
feed('u')
screen:expect({
grid = [[
^ |
@ -253,7 +237,7 @@ describe('ui/ext_messages', function()
},
})
feed('<C-r><C-r><C-r>')
command('silent redo | silent redo | redo')
local s2 = [[
line 1 |
line^ |
@ -368,14 +352,9 @@ describe('ui/ext_messages', function()
content = { { '\n\tLast set from Lua (run Nvim with -V1 for more details)' } },
kind = 'verbose',
},
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
})
feed('<CR>')
exec([[
set verbose=9
augroup verbose
@ -385,36 +364,38 @@ describe('ui/ext_messages', function()
]])
feed(':edit! foo<CR>')
screen:expect({
grid = s2,
grid = [[
line 1 |
^line |
{1:~ }|*3
]],
cmdline = { { abort = false } },
messages = {
{
content = { { 'finished sourcing nvim_exec2()' } },
history = true,
kind = 'verbose',
},
{
content = { { 'Executing BufEnter Autocommands for "*"' } },
history = true,
kind = 'verbose',
},
{
content = { { 'autocommand echoh "BufEnter"\n' } },
history = true,
kind = 'verbose',
},
{ content = { { 'autocommand echoh "BufEnter"' } }, history = true, kind = 'verbose' },
{ content = { { '\n' } }, kind = '' },
{
content = { { 'Executing BufWinEnter Autocommands for "*"' } },
history = true,
kind = 'verbose',
},
{
content = { { 'autocommand bdelete\n' } },
content = { { 'autocommand bdelete' } },
history = true,
kind = 'verbose',
},
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
{ content = { { '\n' } }, kind = '' },
},
})
feed('<CR>')
command('autocmd! verbose')
command('augroup! verbose')
command('set verbose=0')
@ -476,17 +457,13 @@ describe('ui/ext_messages', function()
kind = 'shell_err',
},
{
content = { { '\nshell returned 3\n\n' } },
content = { { '\nshell returned 3\n' } },
kind = 'shell_ret',
},
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
})
feed('<CR>:registers .<CR>')
feed(':registers .<CR>')
screen:expect({
grid = s2,
cmdline = { {
@ -621,10 +598,6 @@ describe('ui/ext_messages', function()
history = true,
kind = 'echoerr',
},
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
}
@ -636,36 +609,14 @@ describe('ui/ext_messages', function()
]],
cmdline = { { abort = false } },
messages = {
{
content = { { 'bork', 9, 6 } },
history = true,
kind = 'echoerr',
},
{
content = { { 'fail', 9, 6 } },
history = true,
kind = 'echoerr',
},
{
content = { { 'extrafail', 9, 6 } },
history = true,
kind = 'echoerr',
},
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
}
feed('<cr>')
screen:expect {
grid = [[
^ |
{1:~ }|*4
]],
}
-- cmdline without interleaving wait/display keeps the error message
feed(':echoerr "problem" | let x = input("foo> ")<cr>')
screen:expect {
@ -714,20 +665,6 @@ describe('ui/ext_messages', function()
{ kind = 'echoerr', content = { { 'extrafail', 9, 6 } } },
{ kind = 'echoerr', content = { { 'problem', 9, 6 } } },
},
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
}
feed '<cr>'
screen:expect {
grid = [[
^ |
{1:~ }|*4
]],
}
end)
@ -756,12 +693,6 @@ describe('ui/ext_messages', function()
{1:~ }|*4
]],
cmdline = { { abort = false } },
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
msg_history = {
{
content = { { 'bork\nfail', 9, 6 } },
@ -813,10 +744,6 @@ describe('ui/ext_messages', function()
messages = {
{ content = { { 'x #1' } }, kind = 'list_cmd' },
{ content = { { 'y #2' } }, kind = 'list_cmd' },
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
}
end)
@ -908,13 +835,6 @@ describe('ui/ext_messages', function()
items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
pos = 0,
},
messages = {
{
content = { { 'stuff' } },
history = true,
kind = 'echomsg',
},
},
showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 2 of 2', 6, 18 } },
}
@ -931,12 +851,6 @@ describe('ui/ext_messages', function()
content = { { 'stuff' } },
kind = 'echomsg',
} },
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
}
end)
@ -1215,12 +1129,6 @@ describe('ui/ext_messages', function()
{ kind = 'echoerr', content = { { 'bork', 9, 6 } } },
{ kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 9, 6 } } },
},
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
}
end)
@ -1367,6 +1275,7 @@ stack traceback:
{1:~ }|*6
]],
messages = {
{ content = { { '\n' } }, kind = '' },
{
content = { { 'wildmenu wildmode\n' } },
kind = 'wildlist',
@ -1422,12 +1331,6 @@ stack traceback:
prompt = 'Type number and <Enter> or click with the mouse (q or empty cancels): ',
},
},
messages = {
{
content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"' } },
kind = 'confirm',
},
},
})
feed('<cr>')
@ -1516,12 +1419,6 @@ stack traceback:
{1:~ }|*4
]],
cmdline = { { abort = false } },
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
msg_history = {
{
content = { { 'wow, ', 10, 8 }, { 'such\n\nvery ', 9, 6 }, { 'color', 8, 12 } },
@ -1529,14 +1426,6 @@ stack traceback:
},
},
}
feed '<cr>'
screen:expect {
grid = [[
^ |
{1:~ }|*4
]],
}
end)
it('does not truncate messages', function()
@ -1606,7 +1495,15 @@ stack traceback:
},
})
exec_lua([[vim.print({ foo = "bar" })]])
screen:expect_unchanged()
screen:expect({
grid = [[
^ |
{1:~ }|*4
]],
messages = {
{ content = { { '{\n foo = "bar"\n}' } }, history = true, kind = 'lua_print' },
},
})
end)
it('ruler redraw does not crash due to double grid_line_start()', function()
@ -1651,10 +1548,6 @@ stack traceback:
{ content = { { 'foo' } }, kind = 'echo' },
{ content = { { 'bar' } }, kind = 'echo' },
{ content = { { 'baz' } }, kind = 'echo', append = true },
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
})
feed('g<lt>')
@ -1663,12 +1556,6 @@ stack traceback:
^ |
{1:~ }|*4
]],
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
msg_history = {
{ content = { { 'foo' } }, kind = 'echo' },
{ content = { { 'bar' } }, kind = 'echo' },
@ -1695,12 +1582,6 @@ stack traceback:
^ |
{1:~ }|*4
]],
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
msg_history = {
{
content = { { "E354: Invalid register name: '^@'", 9, 6 } },
@ -1753,10 +1634,6 @@ stack traceback:
{ content = { { 'foo' } }, kind = 'echo' },
{ content = { { ' bar' } }, kind = 'echo', append = true },
{ content = { { ' baz' } }, kind = 'echo', append = true },
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
})
end)
@ -1804,10 +1681,6 @@ stack traceback:
content = { { '12' } },
kind = 'echo',
},
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
},
})
end)
@ -2471,12 +2344,8 @@ describe('ui/ext_messages', function()
type :help iccf{18:<Enter>} for information |
|*5
]],
cmdline = { { abort = false } },
messages = {
{
content = { { 'Press ENTER or type command to continue', 6, 18 } },
kind = 'return_prompt',
},
cmdline = {
{ content = { { '' } }, hl_id = 10, pos = 0, prompt = 'Press any key to continue' },
},
}

View File

@ -700,6 +700,7 @@ screen:redraw_debug() to show all intermediate screen states.]]
self.cmdline[self.cmdline_hide_level] = nil
self.cmdline_hide_level = nil
end
self.messages, self.msg_history = {}, {}
end
function Screen:expect_unchanged(intermediate, waittime_ms)
@ -1412,10 +1413,6 @@ function Screen:_handle_msg_history_show(entries)
self.msg_history = entries
end
function Screen:_handle_msg_history_clear()
self.msg_history = {}
end
function Screen:_clear_block(grid, top, bot, left, right)
for i = top, bot do
self:_clear_row_section(grid, i, left, right)