Merge #31661 cmdline_show/hide events

This commit is contained in:
Justin M. Keyes
2024-12-22 16:06:46 -08:00
committed by GitHub
9 changed files with 282 additions and 86 deletions

View File

@@ -92,6 +92,13 @@ EVENTS
• |vim.ui_attach()| callbacks for |ui-messages| `msg_show` events are executed in • |vim.ui_attach()| callbacks for |ui-messages| `msg_show` events are executed in
|api-fast| context. |api-fast| context.
• New/enhanced arguments in these existing UI events:
• `cmdline_show`: `hl_id` argument to highlight the prompt text.
• `cmdline_hide`: `abort` argument indicating if the cmdline was aborted.
• `msg_show`:
• `history` argument indicating if the message was added to the history.
• new message kinds: "bufwrite", "completion", "list_cmd",
"lua_print", "number_prompt", "search_cmd", "undo", "wildlist".
HIGHLIGHTS HIGHLIGHTS

View File

@@ -715,7 +715,7 @@ Activated by the `ext_cmdline` |ui-option|.
This UI extension delegates presentation of the |cmdline| (except 'wildmenu'). This UI extension delegates presentation of the |cmdline| (except 'wildmenu').
For command-line 'wildmenu' UI events, activate |ui-popupmenu|. For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
["cmdline_show", content, pos, firstc, prompt, indent, level] ~ ["cmdline_show", content, pos, firstc, prompt, indent, level, hl_id] ~
content: List of [attrs, string] content: List of [attrs, string]
[[{}, "t"], [attrs, "est"], ...] [[{}, "t"], [attrs, "est"], ...]
@@ -728,8 +728,8 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
`firstc` and `prompt` are text, that if non-empty should be `firstc` and `prompt` are text, that if non-empty should be
displayed in front of the command line. `firstc` always indicates displayed in front of the command line. `firstc` always indicates
built-in command lines such as `:` (ex command) and `/` `?` (search), built-in command lines such as `:` (ex command) and `/` `?` (search),
while `prompt` is an |input()| prompt. `indent` tells how many spaces while `prompt` is an |input()| prompt, highlighted with `hl_id`.
the content should be indented. `indent` tells how many spaces the content should be indented.
The Nvim command line can be invoked recursively, for instance by The Nvim command line can be invoked recursively, for instance by
typing `<c-r>=` at the command line prompt. The `level` field is used typing `<c-r>=` at the command line prompt. The `level` field is used
@@ -749,8 +749,9 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
Should be hidden at next cmdline_show. Should be hidden at next cmdline_show.
["cmdline_hide"] ~ ["cmdline_hide", abort] ~
Hide the cmdline. Hide the cmdline. `abort` is true if the cmdline is hidden after an
aborting condition (|c_Esc| or |c_CTRL-C|).
["cmdline_block_show", lines] ~ ["cmdline_block_show", lines] ~
Show a block of context to the current command line. For example if Show a block of context to the current command line. For example if
@@ -783,7 +784,7 @@ will be set to zero, but can be changed and used for the replacing cmdline or
message window. Cmdline state is emitted as |ui-cmdline| events, which the UI message window. Cmdline state is emitted as |ui-cmdline| events, which the UI
must handle. must handle.
["msg_show", kind, content, replace_last] ~ ["msg_show", kind, content, replace_last, history] ~
Display a message to the user. Display a message to the user.
kind kind
@@ -826,6 +827,9 @@ must handle.
true: Replace the message in the most-recent `msg_show` call, true: Replace the message in the most-recent `msg_show` call,
but any other visible message should still remain. but any other visible message should still remain.
history
True if the message was added to the |:messages| history.
["msg_clear"] ~ ["msg_clear"] ~
Clear all messages currently displayed by "msg_show". (Messages sent Clear all messages currently displayed by "msg_show". (Messages sent
by other "msg_" events below will not be affected). by other "msg_" events below will not be affected).

View File

@@ -136,13 +136,13 @@ void tabline_update(Tabpage current, Array tabs, Buffer current_buffer, Array bu
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer indent, void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer indent,
Integer level) Integer level, Integer hl_id)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_pos(Integer pos, Integer level) void cmdline_pos(Integer pos, Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_special_char(String c, Boolean shift, Integer level) void cmdline_special_char(String c, Boolean shift, Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_hide(Integer level) void cmdline_hide(Integer level, Boolean abort)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_block_show(Array lines) void cmdline_block_show(Array lines)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
@@ -158,7 +158,7 @@ void wildmenu_select(Integer selected)
void wildmenu_hide(void) void wildmenu_hide(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void msg_show(String kind, Array content, Boolean replace_last) void msg_show(String kind, Array content, Boolean replace_last, Boolean history)
FUNC_API_SINCE(6) FUNC_API_FAST FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(6) FUNC_API_FAST FUNC_API_REMOTE_ONLY;
void msg_clear(void) void msg_clear(void)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;

View File

@@ -956,7 +956,7 @@ theend:
char *p = ccline.cmdbuff; char *p = ccline.cmdbuff;
if (ui_has(kUICmdline)) { if (ui_has(kUICmdline)) {
ui_call_cmdline_hide(ccline.level); ui_call_cmdline_hide(ccline.level, s->gotesc);
msg_ext_clear_later(); msg_ext_clear_later();
} }
if (!cmd_silent) { if (!cmd_silent) {
@@ -3423,8 +3423,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
ui_call_cmdline_show(content, line->cmdpos, ui_call_cmdline_show(content, line->cmdpos,
cstr_as_string(charbuf), cstr_as_string(charbuf),
cstr_as_string((line->cmdprompt)), cstr_as_string((line->cmdprompt)),
line->cmdindent, line->cmdindent, line->level, line->hl_id);
line->level);
if (line->special_char) { if (line->special_char) {
charbuf[0] = line->special_char; charbuf[0] = line->special_char;
ui_call_cmdline_special_char(cstr_as_string(charbuf), ui_call_cmdline_special_char(cstr_as_string(charbuf),
@@ -4478,7 +4477,7 @@ static int open_cmdwin(void)
invalidate_botline(curwin); invalidate_botline(curwin);
if (ui_has(kUICmdline)) { if (ui_has(kUICmdline)) {
ccline.redraw_state = kCmdRedrawNone; ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level); ui_call_cmdline_hide(ccline.level, false);
} }
redraw_later(curwin, UPD_SOME_VALID); redraw_later(curwin, UPD_SOME_VALID);

View File

@@ -153,6 +153,7 @@ static sattr_T msg_ext_last_attr = -1;
static int msg_ext_last_hl_id; static int msg_ext_last_hl_id;
static size_t msg_ext_cur_len = 0; static size_t msg_ext_cur_len = 0;
static bool msg_ext_history = false; ///< message was added to history
static bool msg_ext_overwrite = false; ///< will overwrite last message static bool msg_ext_overwrite = false; ///< will overwrite last message
static int msg_ext_visible = 0; ///< number of messages currently visible static int msg_ext_visible = 0; ///< number of messages currently visible
@@ -988,7 +989,7 @@ static void add_msg_hist(const char *s, int len, int hl_id, bool multiline)
static void add_msg_hist_multihl(const char *s, int len, int hl_id, bool multiline, static void add_msg_hist_multihl(const char *s, int len, int hl_id, bool multiline,
HlMessage multihl) HlMessage multihl)
{ {
if (msg_hist_off || msg_silent != 0) { if (msg_hist_off || msg_silent != 0 || (s != NULL && *s == NUL)) {
hl_msg_free(multihl); hl_msg_free(multihl);
return; return;
} }
@@ -999,12 +1000,13 @@ static void add_msg_hist_multihl(const char *s, int len, int hl_id, bool multili
if (len < 0) { if (len < 0) {
len = (int)strlen(s); len = (int)strlen(s);
} }
assert(len > 0);
// remove leading and trailing newlines // remove leading and trailing newlines
while (len > 0 && *s == '\n') { while (*s == '\n') {
s++; s++;
len--; len--;
} }
while (len > 0 && s[len - 1] == '\n') { while (s[len - 1] == '\n') {
len--; len--;
} }
p->msg = xmemdupz(s, (size_t)len); p->msg = xmemdupz(s, (size_t)len);
@@ -1024,6 +1026,7 @@ static void add_msg_hist_multihl(const char *s, int len, int hl_id, bool multili
first_msg_hist = last_msg_hist; first_msg_hist = last_msg_hist;
} }
msg_hist_len++; msg_hist_len++;
msg_ext_history = true;
check_msg_hist(); check_msg_hist();
} }
@@ -3138,13 +3141,14 @@ void msg_ext_ui_flush(void)
msg_ext_emit_chunk(); msg_ext_emit_chunk();
if (msg_ext_chunks->size > 0) { if (msg_ext_chunks->size > 0) {
Array *tofree = msg_ext_init_chunks(); Array *tofree = msg_ext_init_chunks();
ui_call_msg_show(cstr_as_string(msg_ext_kind), *tofree, msg_ext_overwrite); ui_call_msg_show(cstr_as_string(msg_ext_kind), *tofree, msg_ext_overwrite, msg_ext_history);
api_free_array(*tofree); api_free_array(*tofree);
xfree(tofree); xfree(tofree);
if (!msg_ext_overwrite) { if (!msg_ext_overwrite) {
msg_ext_visible++; msg_ext_visible++;
} }
msg_ext_overwrite = false; msg_ext_overwrite = false;
msg_ext_history = false;
msg_ext_kind = NULL; msg_ext_kind = NULL;
} }
} }

View File

@@ -261,9 +261,11 @@ describe('vim.ui_attach', function()
lled in a fast event context | lled in a fast event context |
{1:~ }| {1:~ }|
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'E122: Function Foo already exists, add ! to replace it', 9, 6 } }, content = { { 'E122: Function Foo already exists, add ! to replace it', 9, 6 } },
history = true,
kind = 'emsg', kind = 'emsg',
}, },
}, },
@@ -278,9 +280,11 @@ describe('vim.ui_attach', function()
Y)? | Y)? |
{1:~ }| {1:~ }|
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'replace with Replacement (y/n/a/q/l/^E/^Y)?', 6, 18 } }, content = { { 'replace with Replacement (y/n/a/q/l/^E/^Y)?', 6, 18 } },
history = true,
kind = 'confirm_sub', kind = 'confirm_sub',
}, },
}, },
@@ -294,13 +298,16 @@ describe('vim.ui_attach', function()
e mouse (q or empty cancels): | e mouse (q or empty cancels): |
{1:^~ }| {1:^~ }|
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'Select:\nOne\nTwo\n' } }, content = { { 'Select:\nOne\nTwo\n' } },
history = false,
kind = 'list_cmd', kind = 'list_cmd',
}, },
{ {
content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } }, content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } },
history = false,
kind = 'number_prompt', kind = 'number_prompt',
}, },
}, },
@@ -359,6 +366,7 @@ describe('vim.ui_attach', function()
{9:back from ns: 1.} | {9:back from ns: 1.} |
{100:Press ENTER or type command to continue}^ | {100:Press ENTER or type command to continue}^ |
]], ]],
cmdline = { { abort = false } },
}) })
feed('<cr>') feed('<cr>')
-- Also when scheduled -- Also when scheduled
@@ -378,6 +386,7 @@ describe('vim.ui_attach', function()
6, 6,
}, },
}, },
history = true,
kind = 'lua_error', kind = 'lua_error',
}, },
{ {
@@ -388,10 +397,12 @@ describe('vim.ui_attach', function()
6, 6,
}, },
}, },
history = true,
kind = 'lua_error', kind = 'lua_error',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 100, 18 } }, content = { { 'Press ENTER or type command to continue', 100, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },

View File

@@ -91,25 +91,27 @@ local function test_cmdline(linegrid)
{1:~ }|*3 {1:~ }|*3
| |
]], ]],
cmdline = { { abort = true } },
} }
end) end)
it('works with input()', function() it('works with input()', function()
feed(':call input("input", "default")<cr>') feed(':call input("input", "default")<cr>')
screen:expect { screen:expect({
grid = [[ grid = [[
^ | ^ |
{1:~ }|*3 {1:~ }|*3
| |
]], ]],
cmdline = { cmdline = {
{ {
prompt = 'input',
content = { { 'default' } }, content = { { 'default' } },
hl_id = 0,
pos = 7, pos = 7,
prompt = 'input',
}, },
}, },
} })
feed('<cr>') feed('<cr>')
screen:expect { screen:expect {
@@ -118,6 +120,7 @@ local function test_cmdline(linegrid)
{1:~ }|*3 {1:~ }|*3
| |
]], ]],
cmdline = { { abort = false } },
} }
end) end)
@@ -210,6 +213,7 @@ local function test_cmdline(linegrid)
content = { { 'xx3' } }, content = { { 'xx3' } },
pos = 3, pos = 3,
}, },
{ abort = false },
}, },
} }
@@ -220,6 +224,7 @@ local function test_cmdline(linegrid)
{1:~ }|*3 {1:~ }|*3
| |
]], ]],
cmdline = { { abort = true } },
} }
end) end)
@@ -294,6 +299,7 @@ local function test_cmdline(linegrid)
{1:~ }|*3 {1:~ }|*3
| |
]], ]],
cmdline = { { abort = false } },
} }
-- Try once more, to check buffer is reinitialized. #8007 -- Try once more, to check buffer is reinitialized. #8007
@@ -324,6 +330,7 @@ local function test_cmdline(linegrid)
{1:~ }|*3 {1:~ }|*3
| |
]], ]],
cmdline = { { abort = false } },
} }
end) end)
@@ -353,6 +360,7 @@ local function test_cmdline(linegrid)
{3:[Command Line] }| {3:[Command Line] }|
| |
]], ]],
cmdline = { { abort = false } },
} }
-- nested cmdline -- nested cmdline
@@ -404,6 +412,7 @@ local function test_cmdline(linegrid)
{3:[Command Line] }| {3:[Command Line] }|
| |
]], ]],
cmdline = { [2] = { abort = true } },
} }
feed('<c-c>') feed('<c-c>')
@@ -452,6 +461,7 @@ local function test_cmdline(linegrid)
cmdline = { cmdline = {
{ {
prompt = 'secret:', prompt = 'secret:',
hl_id = 0,
content = { { '******' } }, content = { { '******' } },
pos = 6, pos = 6,
}, },
@@ -495,6 +505,7 @@ local function test_cmdline(linegrid)
cmdline = { cmdline = {
{ {
prompt = '>', prompt = '>',
hl_id = 0,
content = { content = {
{ '(', 30 }, { '(', 30 },
{ 'a' }, { 'a' },
@@ -797,11 +808,14 @@ local function test_cmdline(linegrid)
-- This used to send an invalid event where pos where larger than the total -- This used to send an invalid event where pos where larger than the total
-- length of content. Checked in _handle_cmdline_show. -- length of content. Checked in _handle_cmdline_show.
feed('<esc>') feed('<esc>')
screen:expect([[ screen:expect({
^ | grid = [[
{1:~ }|*3 ^ |
| {1:~ }|*3
]]) |
]],
cmdline = { { abort = true } },
})
end) end)
it('does not move cursor to curwin #20309', function() it('does not move cursor to curwin #20309', function()
@@ -827,6 +841,30 @@ local function test_cmdline(linegrid)
} }, } },
} }
end) end)
it('show prompt hl_id', function()
screen:expect([[
^ |
{1:~ }|*3
|
]])
feed(':echohl Error | call input("Prompt:")<CR>')
screen:expect({
grid = [[
^ |
{1:~ }|*3
|
]],
cmdline = {
{
content = { { '' } },
hl_id = 237,
pos = 0,
prompt = 'Prompt:',
},
},
})
end)
end end
-- the representation of cmdline and cmdline_block contents changed with ext_linegrid -- the representation of cmdline and cmdline_block contents changed with ext_linegrid

View File

@@ -47,9 +47,11 @@ describe('ui/ext_messages', function()
line ^1 | line ^1 |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { '\ntest\n[O]k: ', 6, 10 } }, content = { { '\ntest\n[O]k: ', 6, 10 } },
history = false,
kind = 'confirm', kind = 'confirm',
}, },
}, },
@@ -75,9 +77,11 @@ describe('ui/ext_messages', function()
line ^2 | line ^2 |
{1:~ }|*3 {1:~ }|*3
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { '\ntest\n[O]k: ', 6, 10 } }, content = { { '\ntest\n[O]k: ', 6, 10 } },
history = false,
kind = 'confirm', kind = 'confirm',
}, },
}, },
@@ -87,14 +91,17 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { '\ntest\n[O]k: ', 6, 10 } }, content = { { '\ntest\n[O]k: ', 6, 10 } },
history = false,
kind = 'confirm', kind = 'confirm',
}, },
{ {
content = { { '1' } }, content = { { '1' } },
history = false,
kind = 'echo', kind = 'echo',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -109,9 +116,11 @@ describe('ui/ext_messages', function()
l{10:i}ne ^2 | l{10:i}ne ^2 |
{1:~ }|*3 {1:~ }|*3
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6, 18 } }, content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6, 18 } },
history = true,
kind = 'confirm_sub', kind = 'confirm_sub',
}, },
}, },
@@ -131,6 +140,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'W10: Warning: Changing a readonly file', 19, 26 } }, content = { { 'W10: Warning: Changing a readonly file', 19, 26 } },
history = true,
kind = 'wmsg', kind = 'wmsg',
}, },
}, },
@@ -144,9 +154,11 @@ describe('ui/ext_messages', function()
line 2 | line 2 |
{1:~ }|*3 {1:~ }|*3
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'search hit BOTTOM, continuing at TOP', 19, 26 } }, content = { { 'search hit BOTTOM, continuing at TOP', 19, 26 } },
history = true,
kind = 'wmsg', kind = 'wmsg',
}, },
}, },
@@ -155,17 +167,21 @@ describe('ui/ext_messages', function()
-- kind=emsg after :throw -- kind=emsg after :throw
feed(':throw "foo"<cr>') feed(':throw "foo"<cr>')
screen:expect { screen:expect {
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'Error detected while processing :', 9, 6 } }, content = { { 'Error detected while processing :', 9, 6 } },
history = true,
kind = 'emsg', kind = 'emsg',
}, },
{ {
content = { { 'E605: Exception not caught: foo', 9, 6 } }, content = { { 'E605: Exception not caught: foo', 9, 6 } },
history = true,
kind = 'emsg', kind = 'emsg',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -181,9 +197,11 @@ describe('ui/ext_messages', function()
^line 2 | ^line 2 |
{1:~ }|*3 {1:~ }|*3
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { '(2 of 2): line2' } }, content = { { '(2 of 2): line2' } },
history = true,
kind = 'quickfix', kind = 'quickfix',
}, },
}, },
@@ -197,15 +215,20 @@ describe('ui/ext_messages', function()
line 2 | line 2 |
{1:~ }|*3 {1:~ }|*3
]], ]],
messages = { { cmdline = { { abort = false } },
content = { { '?line ' } }, messages = {
kind = 'search_cmd', {
} }, content = { { '?line ' } },
history = false,
kind = 'search_cmd',
},
},
}) })
-- highlight -- highlight
feed(':filter character highlight<CR>') feed(':filter character highlight<CR>')
screen:expect({ screen:expect({
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { content = {
@@ -219,6 +242,7 @@ describe('ui/ext_messages', function()
{ 'links to', 18, 5 }, { 'links to', 18, 5 },
{ ' SpecialChar' }, { ' SpecialChar' },
}, },
history = false,
kind = 'list_cmd', kind = 'list_cmd',
}, },
}, },
@@ -234,6 +258,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'Already at oldest change' } }, content = { { 'Already at oldest change' } },
history = true,
kind = 'undo', kind = 'undo',
}, },
}, },
@@ -249,6 +274,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'Already at newest change' } }, content = { { 'Already at newest change' } },
history = true,
kind = 'undo', kind = 'undo',
}, },
}, },
@@ -261,6 +287,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'The only match' } }, content = { { 'The only match' } },
history = false,
kind = 'completion', kind = 'completion',
}, },
}, },
@@ -276,10 +303,14 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { cmdline = { { abort = false } },
content = { { 'raa', 9, 6 } }, messages = {
kind = 'echoerr', {
} }, content = { { 'raa', 9, 6 } },
history = true,
kind = 'echoerr',
},
},
} }
-- cmdline in a later input cycle clears error message -- cmdline in a later input cycle clears error message
@@ -302,17 +333,21 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'bork', 9, 6 } }, content = { { 'bork', 9, 6 } },
history = true,
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'fail', 9, 6 } }, content = { { 'fail', 9, 6 } },
history = true,
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -324,21 +359,26 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'bork', 9, 6 } }, content = { { 'bork', 9, 6 } },
history = true,
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'fail', 9, 6 } }, content = { { 'fail', 9, 6 } },
history = true,
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'extrafail', 9, 6 } }, content = { { 'extrafail', 9, 6 } },
history = true,
kind = 'echoerr', kind = 'echoerr',
}, },
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -359,13 +399,17 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { messages = {
content = { { 'problem', 9, 6 } }, {
kind = 'echoerr', content = { { 'problem', 9, 6 } },
} }, history = true,
kind = 'echoerr',
},
},
cmdline = { cmdline = {
{ {
prompt = 'foo> ', prompt = 'foo> ',
hl_id = 0,
content = { { '' } }, content = { { '' } },
pos = 0, pos = 0,
}, },
@@ -378,6 +422,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
} }
eq('solution', eval('x')) eq('solution', eval('x'))
@@ -387,6 +432,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
msg_history = { msg_history = {
{ kind = 'echoerr', content = { { 'raa', 9, 6 } } }, { kind = 'echoerr', content = { { 'raa', 9, 6 } } },
{ kind = 'echoerr', content = { { 'bork', 9, 6 } } }, { kind = 'echoerr', content = { { 'bork', 9, 6 } } },
@@ -397,6 +443,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -419,9 +466,11 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'bork\nfail', 9, 6 } }, content = { { 'bork\nfail', 9, 6 } },
history = true,
kind = 'echoerr', kind = 'echoerr',
}, },
}, },
@@ -433,9 +482,11 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -459,8 +510,9 @@ describe('ui/ext_messages', function()
{10:line} 2 | {10:line} 2 |
{1:~ }|*3 {1:~ }|*3
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ content = { { '/line W [1/2]' } }, kind = 'search_count' }, { content = { { '/line W [1/2]' } }, kind = 'search_count', history = false },
}, },
} }
@@ -472,7 +524,7 @@ describe('ui/ext_messages', function()
{1:~ }|*3 {1:~ }|*3
]], ]],
messages = { messages = {
{ content = { { '/line [2/2]' } }, kind = 'search_count' }, { content = { { '/line [2/2]' } }, kind = 'search_count', history = false },
}, },
} }
end) end)
@@ -485,11 +537,13 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ content = { { 'x #1' } }, kind = 'list_cmd' }, { content = { { 'x #1' } }, kind = 'list_cmd', history = false },
{ content = { { 'y #2' } }, kind = 'list_cmd' }, { content = { { 'y #2' } }, kind = 'list_cmd', history = false },
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -560,10 +614,13 @@ describe('ui/ext_messages', function()
items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } }, items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
pos = 1, pos = 1,
}, },
messages = { { messages = {
content = { { 'stuff' } }, {
kind = 'echomsg', content = { { 'stuff' } },
} }, history = true,
kind = 'echomsg',
},
},
showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 1 of 2', 6, 18 } }, showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 1 of 2', 6, 18 } },
} }
@@ -580,10 +637,13 @@ describe('ui/ext_messages', function()
items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } }, items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
pos = 0, pos = 0,
}, },
messages = { { messages = {
content = { { 'stuff' } }, {
kind = 'echomsg', content = { { 'stuff' } },
} }, history = true,
kind = 'echomsg',
},
},
showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 2 of 2', 6, 18 } }, showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 2 of 2', 6, 18 } },
} }
@@ -595,6 +655,7 @@ describe('ui/ext_messages', function()
alphpabe^t | alphpabe^t |
{1:~ }|*2 {1:~ }|*2
]], ]],
cmdline = { { abort = false } },
msg_history = { { msg_history = { {
content = { { 'stuff' } }, content = { { 'stuff' } },
kind = 'echomsg', kind = 'echomsg',
@@ -602,6 +663,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -793,10 +855,14 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { cmdline = { { abort = false } },
content = { { 'howdy' } }, messages = {
kind = 'echomsg', {
} }, content = { { 'howdy' } },
history = true,
kind = 'echomsg',
},
},
} }
-- always test a message without kind. If this one gets promoted to a -- always test a message without kind. If this one gets promoted to a
@@ -810,6 +876,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'Type :qa and press <Enter> to exit Nvim' } }, content = { { 'Type :qa and press <Enter> to exit Nvim' } },
history = true,
kind = '', kind = '',
}, },
}, },
@@ -821,10 +888,14 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { cmdline = { { abort = false } },
content = { { 'bork', 9, 6 } }, messages = {
kind = 'echoerr', {
} }, content = { { 'bork', 9, 6 } },
history = true,
kind = 'echoerr',
},
},
} }
feed(':echo "xyz"<cr>') feed(':echo "xyz"<cr>')
@@ -833,10 +904,14 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
messages = { { cmdline = { { abort = false } },
content = { { 'xyz' } }, messages = {
kind = 'echo', {
} }, content = { { 'xyz' } },
history = false,
kind = 'echo',
},
},
} }
feed(':call nosuchfunction()<cr>') feed(':call nosuchfunction()<cr>')
@@ -845,9 +920,11 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'E117: Unknown function: nosuchfunction', 9, 6 } }, content = { { 'E117: Unknown function: nosuchfunction', 9, 6 } },
history = true,
kind = 'emsg', kind = 'emsg',
}, },
}, },
@@ -859,6 +936,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
msg_history = { msg_history = {
{ kind = 'echomsg', content = { { 'howdy' } } }, { kind = 'echomsg', content = { { 'howdy' } } },
{ kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } }, { kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } },
@@ -868,6 +946,7 @@ describe('ui/ext_messages', function()
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -892,11 +971,14 @@ describe('ui/ext_messages', function()
} }
feed('<cr>') feed('<cr>')
screen:expect([[ screen:expect({
^ | grid = [[
{1:~ }|*3 ^ |
| {1:~ }|*3
]]) |
]],
cmdline = { { abort = false } },
})
eq(1, eval('&cmdheight')) eq(1, eval('&cmdheight'))
feed(':set cmdheight=0') feed(':set cmdheight=0')
@@ -915,10 +997,15 @@ describe('ui/ext_messages', function()
}, },
} }
feed('<cr>') feed('<cr>')
screen:expect([[ screen:expect({
^ | grid = [[
{1:~ }|*4 ^ |
]]) {1:~ }|*4
]],
cmdline = { {
abort = false,
} },
})
eq(0, eval('&cmdheight')) eq(0, eval('&cmdheight'))
end) end)
@@ -929,6 +1016,7 @@ describe('ui/ext_messages', function()
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { content = {
@@ -943,6 +1031,7 @@ stack traceback:
6, 6,
}, },
}, },
history = true,
kind = 'lua_error', kind = 'lua_error',
}, },
}, },
@@ -957,11 +1046,13 @@ stack traceback:
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { content = {
{ "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9, 6 }, { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9, 6 },
}, },
history = true,
kind = 'rpc_error', kind = 'rpc_error',
}, },
}, },
@@ -981,6 +1072,7 @@ stack traceback:
feed(':map<cr>') feed(':map<cr>')
screen:expect { screen:expect {
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { content = {
@@ -988,6 +1080,7 @@ stack traceback:
{ '*', 18, 1 }, { '*', 18, 1 },
{ ' k' }, { ' k' },
}, },
history = false,
kind = 'list_cmd', kind = 'list_cmd',
}, },
}, },
@@ -1008,6 +1101,7 @@ stack traceback:
messages = { messages = {
{ {
content = { { 'wildmenu wildmode' } }, content = { { 'wildmenu wildmode' } },
history = false,
kind = 'wildlist', kind = 'wildlist',
}, },
}, },
@@ -1035,10 +1129,12 @@ stack traceback:
messages = { messages = {
{ {
content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } }, content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } },
history = false,
kind = 'list_cmd', kind = 'list_cmd',
}, },
{ {
content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } }, content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } },
history = false,
kind = 'number_prompt', kind = 'number_prompt',
}, },
}, },
@@ -1054,14 +1150,17 @@ stack traceback:
messages = { messages = {
{ {
content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } }, content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } },
history = false,
kind = 'list_cmd', kind = 'list_cmd',
}, },
{ {
content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } }, content = { { 'Type number and <Enter> or click with the mouse (q or empty cancels): ' } },
history = false,
kind = 'number_prompt', kind = 'number_prompt',
}, },
{ {
content = { { '1' } }, content = { { '1' } },
history = false,
kind = '', kind = '',
}, },
}, },
@@ -1090,6 +1189,7 @@ stack traceback:
messages = { messages = {
{ {
content = { { 'wow, ', 10, 8 }, { 'such\n\nvery ', 9, 6 }, { 'color', 8, 12 } }, content = { { 'wow, ', 10, 8 }, { 'such\n\nvery ', 9, 6 }, { 'color', 8, 12 } },
history = true,
kind = 'echomsg', kind = 'echomsg',
}, },
}, },
@@ -1101,8 +1201,13 @@ stack traceback:
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ content = { { '\n 1 %a "[No Name]" line 1' } }, kind = 'list_cmd' }, {
content = { { '\n 1 %a "[No Name]" line 1' } },
kind = 'list_cmd',
history = false,
},
}, },
} }
@@ -1112,9 +1217,11 @@ stack traceback:
^ | ^ |
{1:~ }|*4 {1:~ }|*4
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -1139,7 +1246,11 @@ stack traceback:
command('write ' .. fname) command('write ' .. fname)
screen:expect({ screen:expect({
messages = { messages = {
{ content = { { string.format('"%s" [New] 0L, 0B written', fname) } }, kind = 'bufwrite' }, {
content = { { string.format('"%s" [New] 0L, 0B written', fname) } },
kind = 'bufwrite',
history = true,
},
}, },
}) })
end) end)
@@ -1166,6 +1277,7 @@ stack traceback:
messages = { messages = {
{ {
content = { { 'foo\nbar\nbaz' } }, content = { { 'foo\nbar\nbaz' } },
history = true,
kind = 'lua_print', kind = 'lua_print',
}, },
}, },
@@ -1179,6 +1291,7 @@ stack traceback:
messages = { messages = {
{ {
content = { { '{\n foo = "bar"\n}' } }, content = { { '{\n foo = "bar"\n}' } },
history = true,
kind = 'lua_print', kind = 'lua_print',
}, },
}, },
@@ -1853,9 +1966,11 @@ describe('ui/ext_messages', function()
type :help iccf{18:<Enter>} for information | type :help iccf{18:<Enter>} for information |
|*5 |*5
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ {
content = { { 'Press ENTER or type command to continue', 6, 18 } }, content = { { 'Press ENTER or type command to continue', 6, 18 } },
history = false,
kind = 'return_prompt', kind = 'return_prompt',
}, },
}, },
@@ -1935,8 +2050,9 @@ describe('ui/ext_messages', function()
{1:~ }|*10 {1:~ }|*10
{3:[No Name] }| {3:[No Name] }|
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ content = { { ' cmdheight=0' } }, kind = 'list_cmd' }, { content = { { ' cmdheight=0' } }, kind = 'list_cmd', history = false },
}, },
}) })
@@ -1951,8 +2067,9 @@ describe('ui/ext_messages', function()
{1:~ }|*9 {1:~ }|*9
{3:[No Name] }| {3:[No Name] }|
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ content = { { ' laststatus=3' } }, kind = 'list_cmd' }, { content = { { ' laststatus=3' } }, kind = 'list_cmd', history = false },
}, },
}) })
@@ -1971,8 +2088,9 @@ describe('ui/ext_messages', function()
{1:~ }|*10 {1:~ }|*10
{3:[No Name] }| {3:[No Name] }|
]], ]],
cmdline = { { abort = false } },
messages = { messages = {
{ content = { { ' cmdheight=0' } }, kind = 'list_cmd' }, { content = { { ' cmdheight=0' } }, kind = 'list_cmd', history = false },
}, },
}) })
end) end)

View File

@@ -79,6 +79,7 @@ end
--- @field win_position table<integer,table<string,integer>> --- @field win_position table<integer,table<string,integer>>
--- @field float_pos table<integer,table> --- @field float_pos table<integer,table>
--- @field cmdline table<integer,table> --- @field cmdline table<integer,table>
--- @field cmdline_hide_level integer?
--- @field cmdline_block table[] --- @field cmdline_block table[]
--- @field hl_groups table<string,integer> --- @field hl_groups table<string,integer>
--- @field messages table<integer,table> --- @field messages table<integer,table>
@@ -654,6 +655,12 @@ screen:redraw_debug() to show all intermediate screen states.]]
end end
end end
-- Only test the abort state of a cmdline level once.
if self.cmdline_hide_level ~= nil then
self.cmdline[self.cmdline_hide_level] = nil
self.cmdline_hide_level = nil
end
if expected.hl_groups ~= nil then if expected.hl_groups ~= nil then
for name, id in pairs(expected.hl_groups) do for name, id in pairs(expected.hl_groups) do
local expected_hl = attr_state.ids[id] local expected_hl = attr_state.ids[id]
@@ -1296,7 +1303,7 @@ function Screen:_handle_popupmenu_hide()
self.popupmenu = nil self.popupmenu = nil
end end
function Screen:_handle_cmdline_show(content, pos, firstc, prompt, indent, level) function Screen:_handle_cmdline_show(content, pos, firstc, prompt, indent, level, hl_id)
if firstc == '' then if firstc == '' then
firstc = nil firstc = nil
end end
@@ -1320,11 +1327,13 @@ function Screen:_handle_cmdline_show(content, pos, firstc, prompt, indent, level
firstc = firstc, firstc = firstc,
prompt = prompt, prompt = prompt,
indent = indent, indent = indent,
hl_id = prompt and hl_id,
} }
end end
function Screen:_handle_cmdline_hide(level) function Screen:_handle_cmdline_hide(level, abort)
self.cmdline[level] = nil self.cmdline[level] = { abort = abort }
self.cmdline_hide_level = level
end end
function Screen:_handle_cmdline_special_char(char, shift, level) function Screen:_handle_cmdline_special_char(char, shift, level)
@@ -1360,12 +1369,12 @@ function Screen:_handle_wildmenu_hide()
self.wildmenu_items, self.wildmenu_pos = nil, nil self.wildmenu_items, self.wildmenu_pos = nil, nil
end end
function Screen:_handle_msg_show(kind, chunks, replace_last) function Screen:_handle_msg_show(kind, chunks, replace_last, history)
local pos = #self.messages local pos = #self.messages
if not replace_last or pos == 0 then if not replace_last or pos == 0 then
pos = pos + 1 pos = pos + 1
end end
self.messages[pos] = { kind = kind, content = chunks } self.messages[pos] = { kind = kind, content = chunks, history = history }
end end
function Screen:_handle_msg_clear() function Screen:_handle_msg_clear()
@@ -1468,7 +1477,9 @@ function Screen:_extstate_repr(attr_state)
local cmdline = {} local cmdline = {}
for i, entry in pairs(self.cmdline) do for i, entry in pairs(self.cmdline) do
entry = shallowcopy(entry) entry = shallowcopy(entry)
entry.content = self:_chunks_repr(entry.content, attr_state) if entry.content ~= nil then
entry.content = self:_chunks_repr(entry.content, attr_state)
end
cmdline[i] = entry cmdline[i] = entry
end end
@@ -1479,7 +1490,11 @@ function Screen:_extstate_repr(attr_state)
local messages = {} local messages = {}
for i, entry in ipairs(self.messages) do for i, entry in ipairs(self.messages) do
messages[i] = { kind = entry.kind, content = self:_chunks_repr(entry.content, attr_state) } messages[i] = {
kind = entry.kind,
content = self:_chunks_repr(entry.content, attr_state),
history = entry.history,
}
end end
local msg_history = {} local msg_history = {}