-
Notifications
You must be signed in to change notification settings - Fork 105
A Guide to Messages
The message area in vim/neovim displays a large variety of notifications. Some are triggered by vim's internal functionality and others are dispatched by error handlers, echo/print calls, command output, tools such as LSP, external plugins etc...
If you are suddenly alarmed at search hit bottom
message, E:486 pattern not found
error message, or various LSP notifications, you found yourself in the right
wiki.
Many of vim's internal messages are classified as Hit-enter messages.
:h messages
Press ENTER or type command to continue
This message is given when there is something on the screen for you to read,
and the screen is about to be redrawn:
- After executing an external command (e.g., ":!ls" and "=").
- Something is displayed on the status line that is longer than the width of
the window, or runs into the 'showcmd' or 'ruler' output.
When cmdheight
> 0, it's possible that many of these messages are
ignored or entirely unnoticed by users as many of motion and other
key-press make these messages disappear.
Neovim also has nvim_ui_attach
Api method to handle/override Ui events and related functions.
When using GUI-neovim (with appropriate UI features) or any plugin that makes
use of external UI Api, neovim hands over these messages via ext-messages
.
Check :help ui-messages
(or skip head).
This plugin handles the ext-messages
using various views. For more information
on the specifics check :help noice.nvim-views
This guide is a best effort collection of tips and tricks to customize/hide both
messages
and ui-messages
for both using Neovim's internal systems and
noice
routing system.
Vim option shortmess
allows customizing or avoiding these hit enter messages.
Here is a quick overview.
Set (:set shortmess=
, vim.o.shortmess=
) or append (:set shortmess+=
,
vim.opt.shortmess:append()
) to the option as necessary.
s don't give "search hit BOTTOM, continuing at TOP" or "search
hit TOP, continuing at BOTTOM" messages; when using the search
count do not show "W" after the count message (see S below)
W don't give "written" or "[w]" when writing a file
A don't give the "ATTENTION" message when an existing swap file
is found.
I don't give the intro message when starting Vim |:intro|.
c don't give |ins-completion-menu| messages. For example,
"-- XXX completion (YYY)", "match 1 of 2", "The only match",
"Pattern not found", "Back at original", etc.
C don't give messages while scanning for ins-completion items,
for instance "scanning tags"
q use "recording" instead of "recording @a"
F don't give the file info when editing a file, like `:silent`
was used for the command
S do not show search count message when searching, e.g.
"[1/5]"
Check :help shortmess
for a full list of flags. Neovim defaults to filnxtToOF
For external UI and noice, these messages are of event msg_show
. This event
categorizes the messages using the key kind
.
Name indicating the message kind:
"" (empty) Unknown (consider a feature-request: |bugs|)
"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
"lua_error" Error in |:lua| code
"rpc_error" Error response from |rpcrequest()|
"return_prompt" |press-enter| prompt after a multiple messages
"quickfix" Quickfix navigation message
"search_count" Search count message ("S" flag of 'shortmess')
"wmsg" Warning ("search hit BOTTOM", |W10|, …)
Some quick notes:
- "Written" messages have the kind
""
- Lua print and pretty_print messages also have the kind
""
For customizing these messages using noice
, you can edit the following
snippet:
- Avoid written messages
require("noice").setup({
routes = {
{
filter = {
event = "msg_show",
kind = "",
find = "written",
},
opts = { skip = true },
},
},
})
- Avoid search messages. Noice by default uses virttext, this snippets also disables that.
require("noice").setup({
routes = {
{
filter = {
event = "msg_show",
kind = "search_count",
},
opts = { skip = true },
},
},
})
- Avoid all messages with kind
""
require("noice").setup({
routes = {
{
filter = {
event = "msg_show",
kind = "",
},
opts = { skip = true },
},
},
})
Vim option showmode
is responsible for messages such as --INSERT
For external UI, this corresponds to event msg_showmode
which also handles
Macros messages such as recording @
Noice by default skips these messages. But to enable it, use this snippet.
require("noice").setup ({
routes = {
{
view = "notify",
filter = { event = "msg_showmode" },
},
},
})
If you wish to have the showmode
messages displayed in statusline, use the
following snippet (Written for lualine)
require("lualine").setup({
sections = {
lualine_x = {
{
require("noice").api.statusline.mode.get,
cond = require("noice").api.statusline.mode.has,
color = { fg = "#ff9e64" },
}
},
},
})
Depending on the definition, vim/neovim commands (:help command
) and key mappings (:help map
) produce output in the command area.
The simplest way of avoiding these messages is to add the :silent
modifier for commands.
For keymaps, use the <silent>
flag when defining.
Eg: imap <silent> 'key' 'key or command'
vim.keymap.set({"v", "s"}, "keys" , function()...end, {silent = true} )
If you are using which-key you can avoid help prompts and key press messages as follows:
require('which-key').setup {
show_help = false,
show_keys = false,
}
The default vim.notify simply parses the message to determine the importance
based on vim.log.levels
. For errors, it uses the default lua error handling. It
uses :lua print
for the rest. So, the ui-message event would be msg_show
and
kind is ""
Use one of the snippets defined earlier to reroute those messages.
Plugins that override vim.notify
such as nvim-notify
or noice
take
advantage of opts
key passed to vim.notify(msg, level,{opts})
to categories
and stylize the notification and then render as a popup or virttext.
One of the keys that can help identity and filter the messages is opts.title
(if set).
noice
by default overrides vim.notify
and redirects it either to
nvim-notify
or its custom mini
view, which is a virttext rendering similar to
notifier.nvim
and fidget.nvim
.
An example snippet to reroute long notifications to splits
require("noice").setup({
routes = {
{
filter = {
event = "notify",
min_height = 15
},
view = 'split'
},
},
})
Neovim LSP client uses handler functions to manage various requests. This
includes [$/progress]
for LSP progress updates, [window/showMessage]
to
display messages notified by the server and other calls to update on job status.
Neovim LSP client uses vim.notify
for many such use cases. Since noice
by
default overrides vim.notify
, you can customize them similar to the previous
snippet.
Methods [$/progress]
and [window/showMessage]
are overridden by noice
.
Some language servers such as ltex-ls and null-ls provide various notifications, which many users find to be excessive.
Here is a snippet that customizes [$/progress]
by taking advantage of
opts.title
and the lsp token. This snippet cuts off any recurring
notifications of the same kind.
Please note: This snippet overrides the progress handler. So you will need
to disable noice
's handling of the same:
require("noice").setup({
lsp = { progress = { enabled = false }}
})
local null_ls_token = nil
local ltex_token = nil
vim.lsp.handlers['$/progress'] = function(_, result, ctx)
local value = result.value
if not value.kind then
return
end
local client_id = ctx.client_id
local name = vim.lsp.get_client_by_id(client_id).name
if name == 'null-ls' then
if result.token == null_ls_token then
return
end
if value.title == 'formatting' then
null_ls_token = result.token
return
end
end
if name == 'ltex' then
if result.token == ltex_token then
return
end
if value.title == 'Checking document' then
ltex_token = result.token
return
end
end
vim.notify(value.message, 'info', {
title = value.title,
})
end
If you wish to only reduce the notifications from ltex-ls
and still preserve
noice
lsp_progress implementation, simply change the diagnostic config
vim.diagnostic.config({
update_in_insert = false
})