mirror of
https://github.com/neovim/neovim
synced 2025-07-15 16:51:49 +00:00
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:
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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' },
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user