mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	| @@ -672,29 +672,33 @@ of the cmdline. | |||||||
| ["msg_show", kind, content, replace_last] | ["msg_show", kind, content, replace_last] | ||||||
| 	Display a message to the user. | 	Display a message to the user. | ||||||
|  |  | ||||||
| 	`kind` will be one of the following | 	kind | ||||||
| 		`emsg`:		Internal error message | 	    Name indicating the message kind: | ||||||
| 		`echo`:		temporary message from plugin (|:echo|) | 		"" (empty)	Unknown, report a |feature-request| | ||||||
| 		`echomsg`:	ordinary message from plugin (|:echomsg|) | 		"confirm"	|confirm()| or |:confirm| dialog | ||||||
| 		`echoerr`:	error message from plugin (|:echoerr|) | 		"confirm_sub"	|:substitute| confirm dialog |:s_c| | ||||||
| 		`return_prompt`:  |press-enter| prompt after a group of messages | 		"emsg"		Error (|errors|, internal error, |:throw|, …) | ||||||
| 		`quickfix`:	Quickfix navigation message | 		"echo"		|:echo| message | ||||||
| 	`kind` can also be the empty string. The message is then some internal | 		"echomsg"	|:echomsg| message | ||||||
| 	informative or warning message, that hasn't yet been assigned a kind. | 		"echoerr"	|:echoerr| message | ||||||
| 	New message kinds can be added in later versions; clients should | 		"return_prompt"	|press-enter| prompt after a multiple messages | ||||||
| 	handle messages of an unknown kind just like empty kind. | 		"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` will be an array of `[attr_id, text_chunk]` tuples, | 	content | ||||||
| 	building up the message text of chunks of different highlights. | 	    Array of `[attr_id, text_chunk]` tuples, building up the message | ||||||
| 	No extra spacing should be added between chunks, the `text_chunk` by | 	    text of chunks of different highlights. No extra spacing should be | ||||||
| 	itself should contain any necessary whitespace. Messages can contain | 	    added between chunks, the `text_chunk` by itself contains any | ||||||
| 	line breaks `"\n"`. | 	    necessary whitespace. Messages can contain line breaks "\n". | ||||||
|  |  | ||||||
| 	`replace_last` controls how multiple messages should be displayed. | 	replace_last | ||||||
| 	If `replace_last` is false, this message should be displayed together | 	    Decides how multiple messages should be displayed: | ||||||
| 	with all previous messages that are still visible. If `replace_last` | 	    false: Display the message together with all previous messages | ||||||
| 	is true, this message should replace the message in the most recent | 		   that are still visible. | ||||||
| 	`msg_show` call, but any other visible message should still remain. | 	    true:  Replace the message in the most-recent `msg_show` call, | ||||||
|  | 		   but any other visible message should still remain. | ||||||
|  |  | ||||||
| ["msg_clear"] | ["msg_clear"] | ||||||
| 	Clear all messages currently displayed by "msg_show". (Messages sent | 	Clear all messages currently displayed by "msg_show". (Messages sent | ||||||
|   | |||||||
| @@ -3692,10 +3692,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, | |||||||
|               i = msg_scroll; |               i = msg_scroll; | ||||||
|               msg_scroll = 0;                           /* truncate msg when |               msg_scroll = 0;                           /* truncate msg when | ||||||
|                                                            needed */ |                                                            needed */ | ||||||
|               msg_no_more = TRUE; |               msg_no_more = true; | ||||||
|               /* write message same highlighting as for |               msg_ext_set_kind("confirm_sub"); | ||||||
|                * wait_return */ |               smsg_attr(HL_ATTR(HLF_R),  // Same highlight as wait_return(). | ||||||
|               smsg_attr(HL_ATTR(HLF_R), |  | ||||||
|                         _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub); |                         _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub); | ||||||
|               msg_no_more = FALSE; |               msg_no_more = FALSE; | ||||||
|               msg_scroll = i; |               msg_scroll = i; | ||||||
|   | |||||||
| @@ -839,9 +839,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, | |||||||
|       sourcing_lnum = current_exception->throw_lnum; |       sourcing_lnum = current_exception->throw_lnum; | ||||||
|       current_exception->throw_name = NULL; |       current_exception->throw_name = NULL; | ||||||
|  |  | ||||||
|       discard_current_exception();              /* uses IObuff if 'verbose' */ |       discard_current_exception();              // uses IObuff if 'verbose' | ||||||
|       suppress_errthrow = TRUE; |       suppress_errthrow = true; | ||||||
|       force_abort = TRUE; |       force_abort = true; | ||||||
|  |       msg_ext_set_kind("emsg");  // kind=emsg for :throw, exceptions. #9993 | ||||||
|  |  | ||||||
|       if (messages != NULL) { |       if (messages != NULL) { | ||||||
|         do { |         do { | ||||||
|   | |||||||
| @@ -3008,6 +3008,8 @@ void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1) | |||||||
|   } else { |   } else { | ||||||
|     keep_msg_attr = 0; |     keep_msg_attr = 0; | ||||||
|   } |   } | ||||||
|  |   msg_ext_set_kind("wmsg"); | ||||||
|  |  | ||||||
|   if (msg_attr((const char *)message, keep_msg_attr) && msg_scrolled == 0) { |   if (msg_attr((const char *)message, keep_msg_attr) && msg_scrolled == 0) { | ||||||
|     set_keep_msg(message, keep_msg_attr); |     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. |   // Avoid that 'q' at the more prompt truncates the message here. | ||||||
|   confirm_msg_used++; |   confirm_msg_used++; | ||||||
|   if (confirm_msg != NULL) { |   if (confirm_msg != NULL) { | ||||||
|  |     msg_ext_set_kind("confirm"); | ||||||
|     msg_puts_attr((const char *)confirm_msg, HL_ATTR(HLF_M)); |     msg_puts_attr((const char *)confirm_msg, HL_ATTR(HLF_M)); | ||||||
|   } |   } | ||||||
|   confirm_msg_used--; |   confirm_msg_used--; | ||||||
|   | |||||||
| @@ -2248,6 +2248,7 @@ change_warning ( | |||||||
|     if (msg_row == Rows - 1) |     if (msg_row == Rows - 1) | ||||||
|       msg_col = col; |       msg_col = col; | ||||||
|     msg_source(HL_ATTR(HLF_W)); |     msg_source(HL_ATTR(HLF_W)); | ||||||
|  |     msg_ext_set_kind("wmsg"); | ||||||
|     MSG_PUTS_ATTR(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST); |     MSG_PUTS_ATTR(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST); | ||||||
|     set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1); |     set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1); | ||||||
|     msg_clr_eos(); |     msg_clr_eos(); | ||||||
|   | |||||||
| @@ -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). | // Enums need a typecast to be used as array index (for Ultrix). | ||||||
| #define HL_ATTR(n)      highlight_attr[(int)(n)] | #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 | /// 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 | /// character of up to 6 bytes, or one 16-bit character of up to three bytes | ||||||
|   | |||||||
| @@ -22,8 +22,129 @@ describe('ui/ext_messages', function() | |||||||
|       [6] = {bold = true, reverse = true}, |       [6] = {bold = true, reverse = true}, | ||||||
|     }) |     }) | ||||||
|   end) |   end) | ||||||
|  |   after_each(function() | ||||||
|  |     os.remove('Xtest') | ||||||
|  |   end) | ||||||
|  |  | ||||||
|   it('supports :echoerr', function() |   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(':echoerr', function() | ||||||
|     feed(':echoerr "raa"<cr>') |     feed(':echoerr "raa"<cr>') | ||||||
|     screen:expect{grid=[[ |     screen:expect{grid=[[ | ||||||
|       ^                         | |       ^                         | | ||||||
| @@ -142,7 +263,7 @@ describe('ui/ext_messages', function() | |||||||
|     }} |     }} | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   it('supports showmode', function() |   it('&showmode', function() | ||||||
|     command('imap <f2> <cmd>echomsg "stuff"<cr>') |     command('imap <f2> <cmd>echomsg "stuff"<cr>') | ||||||
|     feed('i') |     feed('i') | ||||||
|     screen:expect{grid=[[ |     screen:expect{grid=[[ | ||||||
| @@ -230,7 +351,7 @@ describe('ui/ext_messages', function() | |||||||
|     }} |     }} | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   it('supports showmode with recording message', function() |   it('&showmode with macro-recording message', function() | ||||||
|     feed('qq') |     feed('qq') | ||||||
|     screen:expect{grid=[[ |     screen:expect{grid=[[ | ||||||
|       ^                         | |       ^                         | | ||||||
| @@ -268,7 +389,7 @@ describe('ui/ext_messages', function() | |||||||
|     ]]) |     ]]) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   it('shows recording message with noshowmode', function() |   it('shows macro-recording message with &noshowmode', function() | ||||||
|     command("set noshowmode") |     command("set noshowmode") | ||||||
|     feed('qq') |     feed('qq') | ||||||
|     -- also check mode to avoid immediate success |     -- also check mode to avoid immediate success | ||||||
| @@ -308,7 +429,7 @@ describe('ui/ext_messages', function() | |||||||
|     ]], mode="normal"} |     ]], mode="normal"} | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   it('supports showcmd and ruler', function() |   it('supports &showcmd and &ruler', function() | ||||||
|     command('set showcmd ruler') |     command('set showcmd ruler') | ||||||
|     screen:expect{grid=[[ |     screen:expect{grid=[[ | ||||||
|       ^                         | |       ^                         | | ||||||
|   | |||||||
| @@ -74,6 +74,7 @@ | |||||||
| local global_helpers = require('test.helpers') | local global_helpers = require('test.helpers') | ||||||
| local deepcopy = global_helpers.deepcopy | local deepcopy = global_helpers.deepcopy | ||||||
| local shallowcopy = global_helpers.shallowcopy | local shallowcopy = global_helpers.shallowcopy | ||||||
|  | local concat_tables = global_helpers.concat_tables | ||||||
| local helpers = require('test.functional.helpers')(nil) | local helpers = require('test.functional.helpers')(nil) | ||||||
| local request, run_session = helpers.request, helpers.run_session | local request, run_session = helpers.request, helpers.run_session | ||||||
| local eq = helpers.eq | local eq = helpers.eq | ||||||
| @@ -413,26 +414,23 @@ screen:redraw_debug() to show all intermediate screen states.  ]]) | |||||||
|       end |       end | ||||||
|     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 |     -- 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. |     -- preprocessing to represent highlights in a reproducible way. | ||||||
|     local extstate = self:_extstate_repr(attr_state) |     local extstate = self:_extstate_repr(attr_state) | ||||||
|  |     if expected['mode'] ~= nil then | ||||||
|     -- convert assertion errors into invalid screen state descriptions |       extstate['mode'] = self.mode | ||||||
|     local status, res = pcall(function() |     end | ||||||
|       for _, k in ipairs(ext_keys) do |     -- Convert assertion errors into invalid screen state descriptions. | ||||||
|         -- Empty states is considered the default and need not be mentioned |     for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do | ||||||
|         if not (expected[k] == nil and isempty(extstate[k])) then |       -- Empty states are considered the default and need not be mentioned. | ||||||
|           eq(expected[k], extstate[k], k) |       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 | ||||||
|       end |       end | ||||||
|       if expected.mode ~= nil then |  | ||||||
|         eq(expected.mode, self.mode, "mode") |  | ||||||
|       end |  | ||||||
|     end) |  | ||||||
|     if not status then |  | ||||||
|       return tostring(res) |  | ||||||
|     end |     end | ||||||
|   end, expected) |   end, expected) | ||||||
| end | end | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes