diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2025-01-09 06:36:29 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-09 06:36:29 -0800 |
commit | 5135a232199047e473e3941b0b5a738c77fbecb5 (patch) | |
tree | c6f964678048febab756f825e6cf76470017d89c | |
parent | dcaf8bef08d094889ef5fac24d123871dd0e6a6f (diff) | |
parent | 5c92b40b4b173c7d85106689fef811e41994abb0 (diff) | |
download | rneovim-5135a232199047e473e3941b0b5a738c77fbecb5.tar.gz rneovim-5135a232199047e473e3941b0b5a738c77fbecb5.tar.bz2 rneovim-5135a232199047e473e3941b0b5a738c77fbecb5.zip |
Merge #31900 from luukvbaal/nvim_echo
-rw-r--r-- | runtime/doc/api.txt | 26 | ||||
-rw-r--r-- | runtime/doc/deprecated.txt | 3 | ||||
-rw-r--r-- | runtime/doc/news.txt | 2 | ||||
-rw-r--r-- | runtime/lua/vim/_defaults.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/_editor.lua | 10 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api.lua | 21 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api_keysets.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/client.lua | 6 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 5 | ||||
-rw-r--r-- | src/nvim/api/deprecated.c | 80 | ||||
-rw-r--r-- | src/nvim/api/keysets_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 4 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 88 | ||||
-rw-r--r-- | src/nvim/eval.c | 3 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 2 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 2 | ||||
-rw-r--r-- | src/nvim/message.c | 55 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 24 | ||||
-rw-r--r-- | test/functional/ui/messages_spec.lua | 15 |
19 files changed, 190 insertions, 160 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index c8e0dcd0c5..852037bb34 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -662,28 +662,13 @@ nvim_echo({chunks}, {history}, {opts}) *nvim_echo()* `hl_group` element can be omitted for no highlight. • {history} if true, add to |message-history|. • {opts} Optional parameters. + • err: Treat the message like |:echoerr|. Omitted `hlgroup` + uses |hl-ErrorMsg| instead. • verbose: Message is printed as a result of 'verbose' option. If Nvim was invoked with -V3log_file, the message will be redirected to the log_file and suppressed from direct output. -nvim_err_write({str}) *nvim_err_write()* - Writes a message to the Vim error buffer. Does not append "\n", the - message is buffered (won't display) until a linefeed is written. - - Parameters: ~ - • {str} Message - -nvim_err_writeln({str}) *nvim_err_writeln()* - Writes a message to the Vim error buffer. Appends "\n", so the buffer is - flushed (and displayed). - - Parameters: ~ - • {str} Message - - See also: ~ - • nvim_err_write() - nvim_eval_statusline({str}, {opts}) *nvim_eval_statusline()* Evaluates statusline string. @@ -1154,13 +1139,6 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()* Return: ~ Channel id, or 0 on error -nvim_out_write({str}) *nvim_out_write()* - Writes a message to the Vim output buffer. Does not append "\n", the - message is buffered (won't display) until a linefeed is written. - - Parameters: ~ - • {str} Message - nvim_paste({data}, {crlf}, {phase}) *nvim_paste()* Pastes at cursor (in any mode), and sets "redo" so dot (|.|) will repeat the input. UIs call this to implement "paste", but it's also intended for diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index ec98cc844f..dbdb8f541b 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -18,6 +18,9 @@ DEPRECATED IN 0.11 *deprecated-0.11* API • nvim_subscribe() Plugins must maintain their own "multicast" channels list. • nvim_unsubscribe() Plugins must maintain their own "multicast" channels list. +• nvim_out_write() Use |nvim_echo()|. +• nvim_err_write() Use |nvim_echo()| with `{err=true}`. +• nvim_err_writeln() Use |nvim_echo()| with `{err=true}`. DIAGNOSTICS • *vim.diagnostic.goto_next()* Use |vim.diagnostic.jump()| with `{count=1, float=true}` instead. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 931f5e117c..960b6f05f9 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -178,6 +178,8 @@ API • Improved API "meta" docstrings and :help documentation. • |nvim__ns_set()| can set properties for a namespace +• |nvim_echo()| `err` field to print error messages and `chunks` accepts + highlight group IDs. DEFAULTS diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 4216a2acb7..d71116117e 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -224,7 +224,7 @@ do local function cmd(opts) local ok, err = pcall(vim.api.nvim_cmd, opts, {}) if not ok then - vim.api.nvim_err_writeln(err:sub(#'Vim:' + 1)) + vim.api.nvim_echo({ { err:sub(#'Vim:' + 1) } }, true, { err = true }) end end diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 44f17b3f85..66815a967e 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -58,6 +58,7 @@ vim._extra = { --- @private vim.log = { + --- @enum vim.log.levels levels = { TRACE = 0, DEBUG = 1, @@ -620,13 +621,8 @@ end ---@param opts table|nil Optional parameters. Unused by default. ---@diagnostic disable-next-line: unused-local function vim.notify(msg, level, opts) -- luacheck: no unused args - if level == vim.log.levels.ERROR then - vim.api.nvim_err_writeln(msg) - elseif level == vim.log.levels.WARN then - vim.api.nvim_echo({ { msg, 'WarningMsg' } }, true, {}) - else - vim.api.nvim_echo({ { msg } }, true, {}) - end + local chunks = { { msg, level == vim.log.levels.WARN and 'WarningMsg' or nil } } + vim.api.nvim_echo(chunks, true, { err = level == vim.log.levels.ERROR }) end do diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 7297c8ad38..f6d8153c27 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1104,22 +1104,19 @@ function vim.api.nvim_del_var(name) end --- `hl_group` element can be omitted for no highlight. --- @param history boolean if true, add to `message-history`. --- @param opts vim.api.keyset.echo_opts Optional parameters. +--- - err: Treat the message like `:echoerr`. Omitted `hlgroup` +--- uses `hl-ErrorMsg` instead. --- - verbose: Message is printed as a result of 'verbose' option. --- If Nvim was invoked with -V3log_file, the message will be --- redirected to the log_file and suppressed from direct output. function vim.api.nvim_echo(chunks, history, opts) end ---- Writes a message to the Vim error buffer. Does not append "\n", the ---- message is buffered (won't display) until a linefeed is written. ---- ---- @param str string Message +--- @deprecated +--- @param str string function vim.api.nvim_err_write(str) end ---- Writes a message to the Vim error buffer. Appends "\n", so the buffer is ---- flushed (and displayed). ---- ---- @see vim.api.nvim_err_write ---- @param str string Message +--- @deprecated +--- @param str string function vim.api.nvim_err_writeln(str) end --- Evaluates a Vimscript `expression`. Dicts and Lists are recursively expanded. @@ -1859,10 +1856,8 @@ function vim.api.nvim_open_term(buffer, opts) end --- @return integer # Window handle, or 0 on error function vim.api.nvim_open_win(buffer, enter, config) end ---- Writes a message to the Vim output buffer. Does not append "\n", the ---- message is buffered (won't display) until a linefeed is written. ---- ---- @param str string Message +--- @deprecated +--- @param str string function vim.api.nvim_out_write(str) end --- Parse command line. diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index c08ab0663b..98e916115e 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -88,6 +88,7 @@ error('Cannot require a meta file') --- @field pattern? string|string[] --- @class vim.api.keyset.echo_opts +--- @field err? boolean --- @field verbose? boolean --- @class vim.api.keyset.empty diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 5d11312c77..a99363d3d6 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -702,14 +702,14 @@ local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'err --- --- @param ... string List to write to the buffer local function err_message(...) - local message = table.concat(vim.iter({ ... }):flatten():totable()) + local chunks = { { table.concat({ ... }) } } if vim.in_fast_event() then vim.schedule(function() - api.nvim_err_writeln(message) + vim.api.nvim_echo(chunks, true, { err = true }) api.nvim_command('redraw') end) else - api.nvim_err_writeln(message) + vim.api.nvim_echo(chunks, true, { err = true }) api.nvim_command('redraw') end end diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 1945040bda..3779c342e8 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -582,9 +582,8 @@ NSC['window/showMessage'] = function(_, params, ctx) if message_type == protocol.MessageType.Error then err_message('LSP[', client_name, '] ', message) else - --- @type string - local message_type_name = protocol.MessageType[message_type] - api.nvim_out_write(string.format('LSP[%s][%s] %s\n', client_name, message_type_name, message)) + message = ('LSP[%s][%s] %s\n'):format(client_name, protocol.MessageType[message_type], message) + api.nvim_echo({ { message } }, true, { err = true }) end return params end diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index d5eddb74de..406d5e7b4f 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -21,9 +21,11 @@ #include "nvim/lua/executor.h" #include "nvim/memory.h" #include "nvim/memory_defs.h" +#include "nvim/message.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/pos_defs.h" +#include "nvim/strings.h" #include "nvim/types_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -812,3 +814,81 @@ void nvim_unsubscribe(uint64_t channel_id, String event) { // Does nothing. `rpcnotify(0,…)` broadcasts to all channels, there are no "subscriptions". } + +enum { LINE_BUFFER_MIN_SIZE = 4096, }; + +/// Writes a message to vim output or error buffer. The string is split +/// and flushed after each newline. Incomplete lines are kept for writing +/// later. +/// +/// @param message Message to write +/// @param to_err true: message is an error (uses `emsg` instead of `msg`) +/// @param writeln Append a trailing newline +static void write_msg(String message, bool to_err, bool writeln) +{ + static StringBuilder out_line_buf = KV_INITIAL_VALUE; + static StringBuilder err_line_buf = KV_INITIAL_VALUE; + StringBuilder *line_buf = to_err ? &err_line_buf : &out_line_buf; + +#define PUSH_CHAR(c) \ + if (kv_max(*line_buf) == 0) { \ + kv_resize(*line_buf, LINE_BUFFER_MIN_SIZE); \ + } \ + if (c == NL) { \ + kv_push(*line_buf, NUL); \ + if (to_err) { \ + emsg(line_buf->items); \ + } else { \ + msg(line_buf->items, 0); \ + } \ + if (msg_silent == 0) { \ + msg_didout = true; \ + } \ + kv_drop(*line_buf, kv_size(*line_buf)); \ + kv_resize(*line_buf, LINE_BUFFER_MIN_SIZE); \ + } else if (c == NUL) { \ + kv_push(*line_buf, NL); \ + } else { \ + kv_push(*line_buf, c); \ + } + + no_wait_return++; + for (uint32_t i = 0; i < message.size; i++) { + if (got_int) { + break; + } + PUSH_CHAR(message.data[i]); + } + if (writeln) { + PUSH_CHAR(NL); + } + no_wait_return--; + msg_end(); +} + +/// @deprecated +/// +/// @param str Message +void nvim_out_write(String str) + FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13) +{ + write_msg(str, false, false); +} + +/// @deprecated +/// +/// @param str Message +void nvim_err_write(String str) + FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13) +{ + write_msg(str, true, false); +} + +/// @deprecated +/// +/// @param str Message +void nvim_err_writeln(String str) + FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(13) +{ + write_msg(str, true, true); +} diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h index 40e89d230d..664406ab6e 100644 --- a/src/nvim/api/keysets_defs.h +++ b/src/nvim/api/keysets_defs.h @@ -326,6 +326,7 @@ typedef struct { } Dict(cmd_opts); typedef struct { + Boolean err; Boolean verbose; } Dict(echo_opts); diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 78aa7c00f7..c98635f8fd 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -776,7 +776,7 @@ char *api_typename(ObjectType t) UNREACHABLE; } -HlMessage parse_hl_msg(Array chunks, Error *err) +HlMessage parse_hl_msg(Array chunks, bool is_err, Error *err) { HlMessage hl_msg = KV_INITIAL_VALUE; for (size_t i = 0; i < chunks.size; i++) { @@ -791,7 +791,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err) String str = copy_string(chunk.items[0].data.string, NULL); - int hl_id = 0; + int hl_id = is_err ? HLF_E : 0; if (chunk.size == 2) { hl_id = object_to_hl_id(chunk.items[1], "text highlight", err); } diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index e3e69f4ff6..ed9edb1beb 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -86,8 +86,6 @@ #include "nvim/vim_defs.h" #include "nvim/window.h" -#define LINE_BUFFER_MIN_SIZE 4096 - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/vim.c.generated.h" #endif @@ -775,13 +773,15 @@ void nvim_set_vvar(String name, Object value, Error *err) /// `hl_group` element can be omitted for no highlight. /// @param history if true, add to |message-history|. /// @param opts Optional parameters. +/// - err: Treat the message like |:echoerr|. Omitted `hlgroup` +/// uses |hl-ErrorMsg| instead. /// - verbose: Message is printed as a result of 'verbose' option. /// If Nvim was invoked with -V3log_file, the message will be /// redirected to the log_file and suppressed from direct output. void nvim_echo(Array chunks, Boolean history, Dict(echo_opts) *opts, Error *err) FUNC_API_SINCE(7) { - HlMessage hl_msg = parse_hl_msg(chunks, err); + HlMessage hl_msg = parse_hl_msg(chunks, opts->err, err); if (ERROR_SET(err)) { goto error; } @@ -790,7 +790,7 @@ void nvim_echo(Array chunks, Boolean history, Dict(echo_opts) *opts, Error *err) verbose_enter(); } - msg_multihl(hl_msg, history ? "echomsg" : "echo", history); + msg_multihl(hl_msg, opts->err ? "echoerr" : history ? "echomsg" : "echo", history, opts->err); if (opts->verbose) { verbose_leave(); @@ -806,37 +806,6 @@ error: hl_msg_free(hl_msg); } -/// Writes a message to the Vim output buffer. Does not append "\n", the -/// message is buffered (won't display) until a linefeed is written. -/// -/// @param str Message -void nvim_out_write(String str) - FUNC_API_SINCE(1) -{ - write_msg(str, false, false); -} - -/// Writes a message to the Vim error buffer. Does not append "\n", the -/// message is buffered (won't display) until a linefeed is written. -/// -/// @param str Message -void nvim_err_write(String str) - FUNC_API_SINCE(1) -{ - write_msg(str, true, false); -} - -/// Writes a message to the Vim error buffer. Appends "\n", so the buffer is -/// flushed (and displayed). -/// -/// @param str Message -/// @see nvim_err_write() -void nvim_err_writeln(String str) - FUNC_API_SINCE(1) -{ - write_msg(str, true, true); -} - /// Gets the current list of buffer handles /// /// Includes unlisted (unloaded/deleted) buffers, like `:ls!`. @@ -1662,55 +1631,6 @@ Array nvim_list_chans(Arena *arena) return channel_all_info(arena); } -/// Writes a message to vim output or error buffer. The string is split -/// and flushed after each newline. Incomplete lines are kept for writing -/// later. -/// -/// @param message Message to write -/// @param to_err true: message is an error (uses `emsg` instead of `msg`) -/// @param writeln Append a trailing newline -static void write_msg(String message, bool to_err, bool writeln) -{ - static StringBuilder out_line_buf = KV_INITIAL_VALUE; - static StringBuilder err_line_buf = KV_INITIAL_VALUE; - StringBuilder *line_buf = to_err ? &err_line_buf : &out_line_buf; - -#define PUSH_CHAR(c) \ - if (kv_max(*line_buf) == 0) { \ - kv_resize(*line_buf, LINE_BUFFER_MIN_SIZE); \ - } \ - if (c == NL) { \ - kv_push(*line_buf, NUL); \ - if (to_err) { \ - emsg(line_buf->items); \ - } else { \ - msg(line_buf->items, 0); \ - } \ - if (msg_silent == 0) { \ - msg_didout = true; \ - } \ - kv_drop(*line_buf, kv_size(*line_buf)); \ - kv_resize(*line_buf, LINE_BUFFER_MIN_SIZE); \ - } else if (c == NUL) { \ - kv_push(*line_buf, NL); \ - } else { \ - kv_push(*line_buf, c); \ - } - - no_wait_return++; - for (uint32_t i = 0; i < message.size; i++) { - if (got_int) { - break; - } - PUSH_CHAR(message.data[i]); - } - if (writeln) { - PUSH_CHAR(NL); - } - no_wait_return--; - msg_end(); -} - // Functions used for testing purposes /// Returns object given as argument. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a90f275713..5b91f1248f 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7968,8 +7968,7 @@ void ex_execute(exarg_T *eap) } else if (eap->cmdidx == CMD_echoerr) { // We don't want to abort following commands, restore did_emsg. int save_did_emsg = did_emsg; - msg_ext_set_kind("echoerr"); - emsg_multiline(ga.ga_data, true); + emsg_multiline(ga.ga_data, "echoerr", HLF_E, true); if (!force_abort) { did_emsg = save_did_emsg; } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 6f9f0f07c9..137226e2ad 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -982,7 +982,7 @@ void handle_did_throw(void) if (messages != NULL) { do { msglist_T *next = messages->next; - emsg_multiline(messages->msg, messages->multiline); + emsg_multiline(messages->msg, "emsg", HLF_E, messages->multiline); xfree(messages->msg); xfree(messages->sfile); xfree(messages); diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 0a412b4ca9..68d3af6074 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -958,7 +958,7 @@ static void nlua_print_event(void **argv) HlMessage msg = KV_INITIAL_VALUE; HlMessageChunk chunk = { { .data = argv[0], .size = (size_t)(intptr_t)argv[1] - 1 }, 0 }; kv_push(msg, chunk); - msg_multihl(msg, "lua_print", true); + msg_multihl(msg, "lua_print", true, false); } /// Print as a Vim message diff --git a/src/nvim/message.c b/src/nvim/message.c index d45bc147cb..e288353ddc 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -293,20 +293,31 @@ void msg_multiline(String str, int hl_id, bool check_int, bool hist, bool *need_ } } -void msg_multihl(HlMessage hl_msg, const char *kind, bool history) +// Avoid starting a new message for each chunk and adding message to history in msg_keep(). +static bool is_multihl = false; + +void msg_multihl(HlMessage hl_msg, const char *kind, bool history, bool err) { no_wait_return++; msg_start(); msg_clr_eos(); bool need_clear = false; + msg_ext_history = history; msg_ext_set_kind(kind); + is_multihl = true; for (uint32_t i = 0; i < kv_size(hl_msg); i++) { HlMessageChunk chunk = kv_A(hl_msg, i); - msg_multiline(chunk.text, chunk.hl_id, true, false, &need_clear); + if (err) { + emsg_multiline(chunk.text.data, kind, chunk.hl_id, true); + } else { + msg_multiline(chunk.text, chunk.hl_id, true, false, &need_clear); + } + assert(msg_ext_kind == kind); } if (history && kv_size(hl_msg)) { add_msg_hist_multihl(NULL, 0, 0, true, hl_msg); } + is_multihl = false; no_wait_return--; msg_end(); } @@ -342,18 +353,19 @@ bool msg_keep(const char *s, int hl_id, bool keep, bool multiline) } entered++; - // Add message to history (unless it's a repeated kept message or a - // truncated message) - if (s != keep_msg - || (*s != '<' - && last_msg_hist != NULL - && last_msg_hist->msg != NULL - && strcmp(s, last_msg_hist->msg) != 0)) { + // Add message to history (unless it's a truncated, repeated kept or multihl message). + if ((s != keep_msg + || (*s != '<' + && last_msg_hist != NULL + && last_msg_hist->msg != NULL + && strcmp(s, last_msg_hist->msg) != 0)) && !is_multihl) { add_msg_hist(s, -1, hl_id, multiline); } + if (!is_multihl) { + msg_start(); + } // Truncate the message if needed. - msg_start(); char *buf = msg_strtrunc(s, false); if (buf != NULL) { s = buf; @@ -368,7 +380,10 @@ bool msg_keep(const char *s, int hl_id, bool keep, bool multiline) if (need_clear) { msg_clr_eos(); } - bool retval = msg_end(); + bool retval = true; + if (!is_multihl) { + retval = msg_end(); + } if (keep && retval && vim_strsize(s) < (Rows - cmdline_row - 1) * Columns + sc_col) { set_keep_msg(s, 0); @@ -618,6 +633,9 @@ void msg_source(int hl_id) msg_scroll = true; // this will take more than one line msg(p, hl_id); xfree(p); + if (is_multihl) { + msg_start(); // avoided in msg_keep() but need the "msg_didout" newline here + } } p = get_emsg_lnum(); if (p != NULL) { @@ -652,7 +670,7 @@ int emsg_not_now(void) return false; } -bool emsg_multiline(const char *s, bool multiline) +bool emsg_multiline(const char *s, const char *kind, int hl_id, bool multiline) { bool ignore = false; @@ -750,14 +768,13 @@ bool emsg_multiline(const char *s, bool multiline) } emsg_on_display = true; // remember there is an error message - int hl_id = HLF_E; // set highlight mode for error messages if (msg_scrolled != 0) { need_wait_return = true; // needed in case emsg() is called after } // wait_return() has reset need_wait_return // and a redraw is expected because // msg_scrolled is non-zero if (msg_ext_kind == NULL) { - msg_ext_set_kind("emsg"); + msg_ext_set_kind(kind); } // Display name and line number for the source of the error. @@ -765,7 +782,7 @@ bool emsg_multiline(const char *s, bool multiline) msg_source(hl_id); if (msg_ext_kind == NULL) { - msg_ext_set_kind("emsg"); + msg_ext_set_kind(kind); } // Display the error message itself. @@ -781,7 +798,7 @@ bool emsg_multiline(const char *s, bool multiline) /// @return true if wait_return() not called bool emsg(const char *s) { - return emsg_multiline(s, false); + return emsg_multiline(s, "emsg", HLF_E, false); } void emsg_invreg(int name) @@ -821,7 +838,7 @@ bool semsg_multiline(const char *const fmt, ...) vim_vsnprintf(errbuf, sizeof(errbuf), fmt, ap); va_end(ap); - ret = emsg_multiline(errbuf, true); + ret = emsg_multiline(errbuf, "emsg", HLF_E, true); return ret; } @@ -905,7 +922,7 @@ void msg_schedule_semsg(const char *const fmt, ...) static void msg_semsg_multiline_event(void **argv) { char *s = argv[0]; - emsg_multiline(s, true); + emsg_multiline(s, "emsg", HLF_E, true); xfree(s); } @@ -1196,7 +1213,7 @@ void ex_messages(exarg_T *eap) msg_hist_off = true; for (; p != NULL && !got_int; p = p->next) { if (kv_size(p->multihl)) { - msg_multihl(p->multihl, p->kind, false); + msg_multihl(p->multihl, p->kind, false, false); } else if (p->msg != NULL) { msg_keep(p->msg, p->hl_id, false, p->multiline); } diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 578fa361e8..e0ab31f702 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3680,6 +3680,30 @@ describe('API', function() async_meths.nvim_echo({ { 'msg\nmsg' }, { 'msg' } }, false, {}) eq('', exec_capture('messages')) end) + + it('can print error message', function() + async_meths.nvim_echo({ { 'Error\nMessage' } }, false, { err = true }) + screen:expect([[ + | + {1:~ }|*3 + {3: }| + {9:Error} | + {9:Message} | + {6:Press ENTER or type command to continue}^ | + ]]) + feed(':messages<CR>') + screen:expect([[ + ^ | + {1:~ }|*6 + | + ]]) + async_meths.nvim_echo({ { 'Error' }, { 'Message', 'Special' } }, false, { err = true }) + screen:expect([[ + ^ | + {1:~ }|*6 + {9:Error}{16:Message} | + ]]) + end) end) describe('nvim_open_term', function() diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 77ffc475b0..06048c665c 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -315,6 +315,21 @@ describe('ui/ext_messages', function() }) feed('<Esc>') command('set showmode') + + -- kind=echoerr for nvim_echo() err + feed(':call nvim_echo([["Error"], ["Message", "Special"]], 1, #{ err:1 })<CR>') + screen:expect({ + cmdline = { { + abort = false, + } }, + messages = { + { + content = { { 'Error', 9, 6 }, { 'Message', 16, 99 } }, + history = true, + kind = 'echoerr', + }, + }, + }) end) it(':echoerr', function() |