diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2019-05-09 23:54:04 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2019-05-11 23:42:55 +0200 |
commit | 3d1ed7c959017dc8664497b26c86c9ffabf02891 (patch) | |
tree | 99a2d680a63de8d1ac63fc5abb05b04dd16518b6 | |
parent | 7c9d4d971cab4525fb2245ec527736b4e9471e84 (diff) | |
download | rneovim-3d1ed7c959017dc8664497b26c86c9ffabf02891.tar.gz rneovim-3d1ed7c959017dc8664497b26c86c9ffabf02891.tar.bz2 rneovim-3d1ed7c959017dc8664497b26c86c9ffabf02891.zip |
UI/ext_messages: learn more message kinds
ref #6201
-rw-r--r-- | runtime/doc/ui.txt | 50 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 7 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 7 | ||||
-rw-r--r-- | src/nvim/message.c | 3 | ||||
-rw-r--r-- | src/nvim/misc1.c | 1 | ||||
-rw-r--r-- | src/nvim/vim.h | 1 | ||||
-rw-r--r-- | test/functional/ui/messages_spec.lua | 131 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 28 |
8 files changed, 177 insertions, 51 deletions
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index bfcd0369ad..9b0b32299a 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -672,29 +672,33 @@ of the cmdline. ["msg_show", kind, content, replace_last] Display a message to the user. - `kind` will be one of the following - `emsg`: Internal error message - `echo`: temporary message from plugin (|:echo|) - `echomsg`: ordinary message from plugin (|:echomsg|) - `echoerr`: error message from plugin (|:echoerr|) - `return_prompt`: |press-enter| prompt after a group of messages - `quickfix`: Quickfix navigation message - `kind` can also be the empty string. The message is then some internal - informative or warning message, that hasn't yet been assigned a kind. - New message kinds can be added in later versions; clients should - handle messages of an unknown kind just like empty kind. - - `content` will be an array of `[attr_id, text_chunk]` tuples, - building up the message text of chunks of different highlights. - No extra spacing should be added between chunks, the `text_chunk` by - itself should contain any necessary whitespace. Messages can contain - line breaks `"\n"`. - - `replace_last` controls how multiple messages should be displayed. - If `replace_last` is false, this message should be displayed together - with all previous messages that are still visible. If `replace_last` - is true, this message should replace the message in the most recent - `msg_show` call, but any other visible message should still remain. + kind + Name indicating the message kind: + "" (empty) Unknown, report a |feature-request| + "confirm" |confirm()| or |:confirm| dialog + "confirm_sub" |:substitute| confirm dialog |:s_c| + "emsg" Error (|errors|, internal error, |:throw|, …) + "echo" |:echo| message + "echomsg" |:echomsg| message + "echoerr" |:echoerr| message + "return_prompt" |press-enter| prompt after a multiple messages + "quickfix" Quickfix navigation message + "wmsg" Warning ("search hit BOTTOM", |W10|, …) + New kinds may be added in the future; clients should treat unknown + kinds as the empty kind. + + content + Array of `[attr_id, text_chunk]` tuples, building up the message + text of chunks of different highlights. No extra spacing should be + added between chunks, the `text_chunk` by itself contains any + necessary whitespace. Messages can contain line breaks "\n". + + replace_last + Decides how multiple messages should be displayed: + false: Display the message together with all previous messages + that are still visible. + true: Replace the message in the most-recent `msg_show` call, + but any other visible message should still remain. ["msg_clear"] Clear all messages currently displayed by "msg_show". (Messages sent diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index d20b6f5f58..560f4e5df2 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3692,10 +3692,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, i = msg_scroll; msg_scroll = 0; /* truncate msg when needed */ - msg_no_more = TRUE; - /* write message same highlighting as for - * wait_return */ - smsg_attr(HL_ATTR(HLF_R), + msg_no_more = true; + msg_ext_set_kind("confirm_sub"); + smsg_attr(HL_ATTR(HLF_R), // Same highlight as wait_return(). _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub); msg_no_more = FALSE; msg_scroll = i; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 19bf77a2dc..9c4a3f389a 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -839,9 +839,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, sourcing_lnum = current_exception->throw_lnum; current_exception->throw_name = NULL; - discard_current_exception(); /* uses IObuff if 'verbose' */ - suppress_errthrow = TRUE; - force_abort = TRUE; + discard_current_exception(); // uses IObuff if 'verbose' + suppress_errthrow = true; + force_abort = true; + msg_ext_set_kind("emsg"); // kind=emsg for :throw, exceptions. #9993 if (messages != NULL) { do { diff --git a/src/nvim/message.c b/src/nvim/message.c index 4c5f357451..cb83d6482c 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -3008,6 +3008,8 @@ void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1) } else { keep_msg_attr = 0; } + msg_ext_set_kind("wmsg"); + if (msg_attr((const char *)message, keep_msg_attr) && msg_scrolled == 0) { set_keep_msg(message, keep_msg_attr); } @@ -3348,6 +3350,7 @@ void display_confirm_msg(void) // Avoid that 'q' at the more prompt truncates the message here. confirm_msg_used++; if (confirm_msg != NULL) { + msg_ext_set_kind("confirm"); msg_puts_attr((const char *)confirm_msg, HL_ATTR(HLF_M)); } confirm_msg_used--; diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 61fe5e74eb..0008409731 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -2248,6 +2248,7 @@ change_warning ( if (msg_row == Rows - 1) msg_col = col; msg_source(HL_ATTR(HLF_W)); + msg_ext_set_kind("wmsg"); MSG_PUTS_ATTR(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST); set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1); msg_clr_eos(); diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 767936ecee..3e0a5907be 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -277,7 +277,6 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() // Enums need a typecast to be used as array index (for Ultrix). #define HL_ATTR(n) highlight_attr[(int)(n)] -#define TERM_STR(n) term_strings[(int)(n)] /// Maximum number of bytes in a multi-byte character. It can be one 32-bit /// character of up to 6 bytes, or one 16-bit character of up to three bytes diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 697ddc1887..d49d2f0316 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -22,8 +22,129 @@ describe('ui/ext_messages', function() [6] = {bold = true, reverse = true}, }) end) + after_each(function() + os.remove('Xtest') + end) + + it('msg_show kind=confirm,confirm_sub,emsg,wmsg', function() + feed('iline 1\nline 2<esc>') + + -- kind=confirm + feed(':echo confirm("test")<cr>') + screen:expect{grid=[[ + line 1 | + line ^2 | + {1:~ }| + {1:~ }| + {1:~ }| + ]], messages={ { + content = {{"\ntest\n[O]k: ", 4}}, + kind = 'confirm', + }}} + feed('<cr><cr>') + screen:expect{grid=[[ + line 1 | + line ^2 | + {1:~ }| + {1:~ }| + {1:~ }| + ]], messages={ { + content = { { "\ntest\n[O]k: ", 4 } }, + kind = "confirm" + }, { + content = { { "1" } }, + kind = "echo" + }, { + content = { { "Press ENTER or type command to continue", 4 } }, + kind = "return_prompt" + } }} + feed('<cr><cr>') + + -- kind=confirm_sub + feed(':%s/i/X/gc<cr>') + screen:expect{grid=[[ + l{7:i}ne 1 | + l{8:i}ne ^2 | + {1:~ }| + {1:~ }| + {1:~ }| + ]], attr_ids={ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + [3] = {bold = true}, + [4] = {bold = true, foreground = Screen.colors.SeaGreen4}, + [5] = {foreground = Screen.colors.Blue1}, + [6] = {bold = true, reverse = true}, + [7] = {reverse = true}, + [8] = {background = Screen.colors.Yellow}, + }, messages={ { + content = { { "replace with X (y/n/a/q/l/^E/^Y)?", 4 } }, + kind = "confirm_sub" + } }} + feed('nq') + + -- kind=wmsg (editing readonly file) + command('write Xtest') + command('set readonly nohls') + feed('G$x') + screen:expect{grid=[[ + line 1 | + {IGNORE}| + {1:~ }| + {1:~ }| + {1:~ }| + ]], attr_ids={ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [7] = {foreground = Screen.colors.Red}, + }, messages={ { + content = { { "W10: Warning: Changing a readonly file", 7 } }, + kind = "wmsg" + } + }} + + -- kind=wmsg ('wrapscan' after search reaches EOF) + feed('uG$/i<cr>') + screen:expect{grid=[[ + l^ine 1 | + line 2 | + {1:~ }| + {1:~ }| + {1:~ }| + ]], attr_ids={ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + [3] = {bold = true}, + [4] = {bold = true, foreground = Screen.colors.SeaGreen4}, + [5] = {foreground = Screen.colors.Blue1}, + [6] = {bold = true, reverse = true}, + [7] = {foreground = Screen.colors.Red}, + }, messages={ { + content = { { "search hit BOTTOM, continuing at TOP", 7 } }, + kind = "wmsg" + } }} + + -- kind=emsg after :throw + feed(':throw "foo"<cr>') + screen:expect{grid=[[ + l^ine 1 | + line 2 | + {1:~ }| + {1:~ }| + {1:~ }| + ]], messages={ { + content = { { "Error detected while processing :", 2 } }, + kind = "emsg" + }, { + content = { { "E605: Exception not caught: foo", 2 } }, + kind = "" + }, { + content = { { "Press ENTER or type command to continue", 4 } }, + kind = "return_prompt" + } } + } + end) - it('supports :echoerr', function() + it(':echoerr', function() feed(':echoerr "raa"<cr>') screen:expect{grid=[[ ^ | @@ -142,7 +263,7 @@ describe('ui/ext_messages', function() }} end) - it('supports showmode', function() + it('&showmode', function() command('imap <f2> <cmd>echomsg "stuff"<cr>') feed('i') screen:expect{grid=[[ @@ -230,7 +351,7 @@ describe('ui/ext_messages', function() }} end) - it('supports showmode with recording message', function() + it('&showmode with macro-recording message', function() feed('qq') screen:expect{grid=[[ ^ | @@ -268,7 +389,7 @@ describe('ui/ext_messages', function() ]]) end) - it('shows recording message with noshowmode', function() + it('shows macro-recording message with &noshowmode', function() command("set noshowmode") feed('qq') -- also check mode to avoid immediate success @@ -308,7 +429,7 @@ describe('ui/ext_messages', function() ]], mode="normal"} end) - it('supports showcmd and ruler', function() + it('supports &showcmd and &ruler', function() command('set showcmd ruler') screen:expect{grid=[[ ^ | diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 983a2f3d40..53b6642207 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -74,6 +74,7 @@ local global_helpers = require('test.helpers') local deepcopy = global_helpers.deepcopy local shallowcopy = global_helpers.shallowcopy +local concat_tables = global_helpers.concat_tables local helpers = require('test.functional.helpers')(nil) local request, run_session = helpers.request, helpers.run_session local eq = helpers.eq @@ -413,26 +414,23 @@ screen:redraw_debug() to show all intermediate screen states. ]]) end end - -- Extension features. The default expectations should cover the case of + -- UI extensions. The default expectations should cover the case of -- the ext_ feature being disabled, or the feature currently not activated - -- (for instance no external cmdline visible). Some extensions require + -- (e.g. no external cmdline visible). Some extensions require -- preprocessing to represent highlights in a reproducible way. local extstate = self:_extstate_repr(attr_state) - - -- convert assertion errors into invalid screen state descriptions - local status, res = pcall(function() - for _, k in ipairs(ext_keys) do - -- Empty states is considered the default and need not be mentioned - if not (expected[k] == nil and isempty(extstate[k])) then - eq(expected[k], extstate[k], k) + if expected['mode'] ~= nil then + extstate['mode'] = self.mode + end + -- Convert assertion errors into invalid screen state descriptions. + for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do + -- Empty states are considered the default and need not be mentioned. + if (not (expected[k] == nil and isempty(extstate[k]))) then + local status, res = pcall(eq, expected[k], extstate[k], k) + if not status then + return (tostring(res)..'\nHint: full state of "'..k..'":\n '..inspect(extstate[k])) end end - if expected.mode ~= nil then - eq(expected.mode, self.mode, "mode") - end - end) - if not status then - return tostring(res) end end, expected) end |