fix(messages): message kind for :recover and swapfile attention #39444

Problem:  No message kind and multiple events for :recover and
          (non-prompt) swapfile attention messages.
Solution: Assign these the "list_cmd" and "wmsg" kind.
This commit is contained in:
luukvbaal
2026-04-28 16:05:06 +02:00
committed by GitHub
parent 72bc6c5801
commit 62db5bebdd
3 changed files with 118 additions and 37 deletions

View File

@@ -857,8 +857,8 @@ must handle.
"lua_error" Error in |:lua| code
"lua_print" |print()| from |:lua| code
"progress" Progress message emitted by |nvim_echo()|
"rpc_error" Error response from |rpcrequest()|
"quickfix" Quickfix navigation message
"rpc_error" Error response from |rpcrequest()|
"search_cmd" Entered search command
"search_count" Search count message ("S" flag of 'shortmess')
"shell_cmd" |:!cmd| executed command

View File

@@ -801,7 +801,9 @@ void ml_recover(bool checkext)
} else { // several swapfiles found, choose
// list the names of the swapfiles
recover_names(fname, true, NULL, 0, NULL);
msg_putchar('\n');
if (!ui_has(kUIMessages)) {
msg_putchar('\n');
}
i = prompt_for_input(_("Enter number of swap file to use (0 to quit): "), 0, false, NULL);
if (i < 1 || i > len) {
goto theend;
@@ -849,6 +851,7 @@ void ml_recover(bool checkext)
mfp->mf_page_size = MIN_SWAP_PAGE_SIZE;
int hl_id = HLF_E;
msg_ext_set_kind("emsg");
// try to read block 0
if ((hp = mf_get(mfp, 0, 1)) == NULL) {
msg_start();
@@ -920,6 +923,8 @@ void ml_recover(bool checkext)
}
}
msg_ext_set_kind("wmsg");
msg_ext_skip_flush = true;
home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, true);
smsg(0, _("Using swap file \"%s\""), NameBuff);
@@ -928,8 +933,10 @@ void ml_recover(bool checkext)
} else {
home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, true);
}
msg_putchar('\n');
smsg(0, _("Original file \"%s\""), NameBuff);
msg_putchar('\n');
msg_ext_skip_flush = false;
// check date of swapfile and original file
FileInfo org_file_info;
@@ -1209,17 +1216,21 @@ void ml_recover(bool checkext)
curbuf->b_flags |= BF_RECOVERED;
check_cursor(curwin);
msg_ext_skip_flush = !got_int;
recoverymode = false;
if (got_int) {
emsg(_("E311: Recovery Interrupted"));
} else if (error) {
no_wait_return++;
msg(">>>>>>>>>>>>>", 0);
msg_ext_set_kind("emsg");
msg(">>>>>>>>>>>>>\n", 0);
emsg(_("E312: Errors detected while recovering; look for lines starting with ???"));
no_wait_return--;
msg_putchar('\n');
msg(_("See \":help E312\" for more information."), 0);
msg(">>>>>>>>>>>>>", 0);
msg("\n>>>>>>>>>>>>>", 0);
} else {
msg_ext_set_kind("wmsg");
if (curbuf->b_changed) {
msg(_("Recovery completed. You should check if everything is OK."), 0);
msg_puts(_("\n(You might want to write out this file under another name\n"));
@@ -1234,12 +1245,15 @@ void ml_recover(bool checkext)
msg_puts(_("\nNote: process STILL RUNNING: "));
msg_outnum((int)char_to_long(b0p->b0_pid));
}
msg_puts("\n\n");
if (!ui_has(kUIMessages)) {
msg_puts("\n\n");
}
cmdline_row = msg_row;
}
redraw_curbuf_later(UPD_NOT_VALID);
theend:
msg_ext_skip_flush = false;
xfree(fname_used);
recoverymode = false;
if (mfp != NULL) {
@@ -1298,8 +1312,10 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
#endif
}
msg_ext_skip_flush = true;
if (do_list) {
// use msg() to start the scrolling properly
msg_ext_set_kind("list_cmd");
msg(_("Swap files found:"), 0);
msg_putchar('\n');
}
@@ -1448,6 +1464,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
FreeWild(num_files, files);
}
}
msg_ext_skip_flush = false;
xfree(dir_name.data);
return file_count;
}
@@ -1548,7 +1565,7 @@ static time_t swapfile_info(char *fname, StringBuilder *msg)
kv_printf(*msg, _(" dated: "));
}
#else
msg_puts(_(" dated: "));
kv_printf(*msg, _(" dated: "));
#endif
x = file_info.stat.st_mtim.tv_sec;
char ctime_buf[100]; // hopefully enough for every language
@@ -3604,6 +3621,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
msg_reset_scroll();
} else {
bool need_clear = false;
msg_ext_set_kind("wmsg");
msg_multiline(cbuf_as_string(msg.items, msg.size), 0, false, false, &need_clear);
}
no_wait_return--;

View File

@@ -142,37 +142,70 @@ describe("preserve and (R)ecover with custom 'directory'", function()
test_recover(swappath1)
end)
it('manual :recover with multiple swapfiles', function()
local swappath1 = setup_swapname()
eq('.swp', swappath1:match('%.[^.]+$'))
nvim0:close()
neq(nil, uv.fs_stat(swappath1))
local swappath2 = swappath1:gsub('%.swp$', '.swo')
eq(true, uv.fs_copyfile(swappath1, swappath2))
clear()
exec(init)
local screen = Screen.new(256, 40)
feed(':recover! ' .. testfile .. '<CR>')
screen:expect({
any = {
'\nSwap files found:',
'\n In directory ',
vim.pesc('\n1. '),
vim.pesc('\n2. '),
vim.pesc('\nEnter number of swap file to use (0 to quit): ^'),
},
none = vim.pesc('{18:^@}'),
})
feed('2<CR>')
screen:expect({
any = {
vim.pesc('\nRecovery completed.'),
vim.pesc('\n{6:Press ENTER or type command to continue}^'),
},
})
feed('<CR>')
expect('sometext')
end)
for _, ext in ipairs({ false, true }) do
it('manual :recover with multiple swapfiles' .. (ext and 'with ext_messages' or ''), function()
local swappath1 = setup_swapname()
eq('.swp', swappath1:match('%.[^.]+$'))
nvim0:close()
neq(nil, uv.fs_stat(swappath1))
local swappath2 = swappath1:gsub('%.swp$', '.swo')
eq(true, uv.fs_copyfile(swappath1, swappath2))
clear()
exec(init)
local screen, msg = Screen.new(256, 40, { ext_messages = ext }), nil
feed(':recover! ' .. testfile .. '<CR>')
if ext then
screen:expect({
cmdline = {
{
content = { { '' } },
pos = 0,
prompt = 'Enter number of swap file to use (0 to quit): ',
},
},
condition = function()
msg = msg or screen.messages[1]
eq(true, msg.content[1][2]:match('Swap.*none --') ~= nil)
eq('list_cmd', msg.kind)
screen.messages = {}
end,
})
else
screen:expect({
any = {
'\nSwap files found:',
'\n In directory ',
vim.pesc('\n1. '),
vim.pesc('\n2. '),
vim.pesc('\nEnter number of swap file to use (0 to quit): ^'),
},
none = vim.pesc('{18:^@}'),
})
end
feed('2<CR>')
if ext then
screen:expect({
any = { 'sometext' },
condition = function()
eq('wmsg', screen.messages[1].kind)
eq(true, screen.messages[1].content[1][2]:match('Using.*Original') ~= nil)
eq('wmsg', screen.messages[1].kind)
eq(true, screen.messages[2].content[1][2]:match('Recovery.*You might.*You may') ~= nil)
screen.messages = {}
end,
})
else
screen:expect({
any = {
vim.pesc('\nRecovery completed.'),
vim.pesc('\n{6:Press ENTER or type command to continue}^'),
},
})
end
feed('<CR>')
expect('sometext')
end)
end
end)
describe('swapfile detection', function()
@@ -393,6 +426,36 @@ pcall(vim.cmd.edit, 'Xtest_swapredraw.lua')
nvim1:close()
end)
it('attention message kind', function()
exec(init)
command('edit Xfile1')
command('preserve') -- Make sure the swap file exists.
local screen = Screen.new(nil, nil, { ext_messages = true })
local nvim = n.new_session(true)
set_session(nvim)
screen:attach()
exec(init)
command('edit Xfile1')
command('autocmd! nvim.swapfile') -- Delete the default handler (which skips the dialog).
command('edit Xfile2 | bunload 1') -- Unload to get non-prompt attention message.
command('silent! call bufload("Xfile1")')
screen:expect({
condition = function()
for _, msg in pairs(screen.messages) do
local ok = msg.content[1][2]:match('W325')
eq(true, ok and msg.kind == 'echomsg' or msg.kind == 'wmsg')
eq(true, (ok or msg.content[1][2]:match('Found a swap.*If you did')) ~= nil)
end
screen.messages = {}
end,
cmdline = {
{ content = { { '' } }, hl = 'MoreMsg', pos = 0, prompt = 'Press any key to continue' },
},
})
nvim:close()
end)
-- oldtest: Test_swap_prompt_splitwin()
it('selecting "q" in the attention prompt', function()
exec(init)