Highly experimental plugin that completely replaces the UI for messages
, cmdline
and the popupmenu
.
:hi
):Noice
command to show a full message historyvim
and lua
on the cmdlineNoice is using the new experimental vim.ui_attach
API, so issues are to be expected.
It is highly recommended to use Neovim nightly, since a bunch of issues have already been fixed upstream.
Check this tracking issue for a list of known issues.
vim
, regex
, lua
, bash
, markdown
and markdown_inline
Install the plugin with your preferred package manager:
-- lazy.nvim
{
"folke/noice.nvim",
event = "VeryLazy",
opts = {
-- add any options here
},
dependencies = {
-- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
"MunifTanjim/nui.nvim",
-- OPTIONAL:
-- `nvim-notify` is only needed, if you want to use the notification view.
-- If not available, we use `mini` as the fallback
"rcarriga/nvim-notify",
}
}
Suggested setup:
require("noice").setup({
lsp = {
-- override markdown rendering so that **cmp** and other plugins use **Treesitter**
override = {
["vim.lsp.util.convert_input_to_markdown_lines"] = true,
["vim.lsp.util.stylize_markdown"] = true,
["cmp.entry.get_documentation"] = true, -- requires hrsh7th/nvim-cmp
},
},
-- you can enable a preset for easier configuration
presets = {
bottom_search = true, -- use a classic bottom cmdline for search
command_palette = true, -- position the cmdline and popupmenu together
long_message_to_split = true, -- long messages will be sent to a split
inc_rename = false, -- enables an input dialog for inc-rename.nvim
lsp_doc_border = false, -- add a border to hover docs and signature help
},
})
It's a good idea to run :checkhealth noice
after installing to check for common issues.
noice.nvim comes with the following defaults:
Check the wiki for configuration recipes.
{
cmdline = {
enabled = true, -- enables the Noice cmdline UI
view = "cmdline_popup", -- view for rendering the cmdline. Change to `cmdline` to get a classic cmdline at the bottom
opts = {}, -- global options for the cmdline. See section on views
---@type table<string, CmdlineFormat>
format = {
-- conceal: (default=true) This will hide the text in the cmdline that matches the pattern.
-- view: (default is cmdline view)
-- opts: any options passed to the view
-- icon_hl_group: optional hl_group for the icon
-- title: set to anything or empty string to hide
cmdline = { pattern = "^:", icon = "ο", lang = "vim" },
search_down = { kind = "search", pattern = "^/", icon = "ο ο", lang = "regex" },
search_up = { kind = "search", pattern = "^%?", icon = "ο ο", lang = "regex" },
filter = { pattern = "^:%s*!", icon = "$", lang = "bash" },
lua = { pattern = { "^:%s*lua%s+", "^:%s*lua%s*=%s*", "^:%s*=%s*" }, icon = "ξ ", lang = "lua" },
help = { pattern = "^:%s*he?l?p?%s+", icon = "ο" },
input = { view = "cmdline_input", icon = "σ°₯» " }, -- Used by input()
-- lua = false, -- to disable a format, set to `false`
},
},
messages = {
-- NOTE: If you enable messages, then the cmdline is enabled automatically.
-- This is a current Neovim limitation.
enabled = true, -- enables the Noice messages UI
view = "notify", -- default view for messages
view_error = "notify", -- view for errors
view_warn = "notify", -- view for warnings
view_history = "messages", -- view for :messages
view_search = "virtualtext", -- view for search count messages. Set to `false` to disable
},
popupmenu = {
enabled = true, -- enables the Noice popupmenu UI
---@type 'nui'|'cmp'
backend = "nui", -- backend to use to show regular cmdline completions
---@type NoicePopupmenuItemKind|false
-- Icons for completion item kinds (see defaults at noice.config.icons.kinds)
kind_icons = {}, -- set to `false` to disable icons
},
-- default options for require('noice').redirect
-- see the section on Command Redirection
---@type NoiceRouteConfig
redirect = {
view = "popup",
filter = { event = "msg_show" },
},
-- You can add any custom commands below that will be available with `:Noice command`
---@type table<string, NoiceCommand>
commands = {
history = {
-- options for the message history that you get with `:Noice`
view = "split",
opts = { enter = true, format = "details" },
filter = {
any = {
{ event = "notify" },
{ error = true },
{ warning = true },
{ event = "msg_show", kind = { "" } },
{ event = "lsp", kind = "message" },
},
},
},
-- :Noice last
last = {
view = "popup",
opts = { enter = true, format = "details" },
filter = {
any = {
{ event = "notify" },
{ error = true },
{ warning = true },
{ event = "msg_show", kind = { "" } },
{ event = "lsp", kind = "message" },
},
},
filter_opts = { count = 1 },
},
-- :Noice errors
errors = {
-- options for the message history that you get with `:Noice`
view = "popup",
opts = { enter = true, format = "details" },
filter = { error = true },
filter_opts = { reverse = true },
},
all = {
-- options for the message history that you get with `:Noice`
view = "split",
opts = { enter = true, format = "details" },
filter = {},
},
},
notify = {
-- Noice can be used as `vim.notify` so you can route any notification like other messages
-- Notification messages have their level and other properties set.
-- event is always "notify" and kind can be any log level as a string
-- The default routes will forward notifications to nvim-notify
-- Benefit of using Noice for this is the routing and consistent history view
enabled = true,
view = "notify",
},
lsp = {
progress = {
enabled = true,
-- Lsp Progress is formatted using the builtins for lsp_progress. See config.format.builtin
-- See the section on formatting for more details on how to customize.
--- @type NoiceFormat|string
format = "lsp_progress",
--- @type NoiceFormat|string
format_done = "lsp_progress_done",
throttle = 1000 / 30, -- frequency to update lsp progress message
view = "mini",
},
override = {
-- override the default lsp markdown formatter with Noice
["vim.lsp.util.convert_input_to_markdown_lines"] = false,
-- override the lsp markdown formatter with Noice
["vim.lsp.util.stylize_markdown"] = false,
-- override cmp documentation with Noice (needs the other options to work)
["cmp.entry.get_documentation"] = false,
},
hover = {
enabled = true,
silent = false, -- set to true to not show a message if hover is not available
view = nil, -- when nil, use defaults from documentation
---@type NoiceViewOptions
opts = {}, -- merged with defaults from documentation
},
signature = {
enabled = true,
auto_open = {
enabled = true,
trigger = true, -- Automatically show signature help when typing a trigger character from the LSP
luasnip = true, -- Will open signature help when jumping to Luasnip insert nodes
throttle = 50, -- Debounce lsp signature help request by 50ms
},
view = nil, -- when nil, use defaults from documentation
---@type NoiceViewOptions
opts = {}, -- merged with defaults from documentation
},
message = {
-- Messages shown by lsp servers
enabled = true,
view = "notify",
opts = {},
},
-- defaults for hover and signature help
documentation = {
view = "hover",
---@type NoiceViewOptions
opts = {
lang = "markdown",
replace = true,
render = "plain",
format = { "{message}" },
win_options = { concealcursor = "n", conceallevel = 3 },
},
},
},
markdown = {
hover = {
["|(%S-)|"] = vim.cmd.help, -- vim help links
["%[.-%]%((%S-)%)"] = require("noice.util").open, -- markdown links
},
highlights = {
["|%S-|"] = "@text.reference",
["@%S+"] = "@parameter",
["^%s*(Parameters:)"] = "@text.title",
["^%s*(Return:)"] = "@text.title",
["^%s*(See also:)"] = "@text.title",
["{%S-}"] = "@parameter",
},
},
health = {
checker = true, -- Disable if you don't want health checks to run
},
---@type NoicePresets
presets = {
-- you can enable a preset by setting it to true, or a table that will override the preset config
-- you can also add custom presets that you can enable/disable with enabled=true
bottom_search = false, -- use a classic bottom cmdline for search
command_palette = false, -- position the cmdline and popupmenu together
long_message_to_split = false, -- long messages will be sent to a split
inc_rename = false, -- enables an input dialog for inc-rename.nvim
lsp_doc_border = false, -- add a border to hover docs and signature help
},
throttle = 1000 / 30, -- how frequently does Noice need to check for ui updates? This has no effect when in blocking mode.
---@type NoiceConfigViews
views = {}, ---@see section on views
---@type NoiceRouteConfig[]
routes = {}, --- @see section on routes
---@type table<string, NoiceFilter>
status = {}, --- @see section on statusline components
---@type NoiceFormatOptions
format = {}, --- @see section on formatting
}
Noice uses filters to route messages to specific views.
Name | Type | Description |
---|---|---|
any | filter[] |
checks that at least one of the filters matches |
blocking | boolean |
are we in blocking mode? |
cleared | boolean |
checks if the message is cleared, meaning it's in the history |
cmdline | boolean or string |
checks if the message was generated by executing a cmdline. When string , then it is used as a pattern |
error | boolean |
all error-like kinds from ext_messages |
event | string or string[] |
any of the events from ext_messages or cmdline . See :h ui-messages |
find | string |
uses lua string.find to match the pattern |
has | boolean |
checks if the message is exists, meaning it's in the history |
kind | string or string[] |
any of the kinds from ext_messages . See :h ui-messages |
max_height | number |
maximum height of the message |
max_length | number |
maximum length of the message (total width of all the lines) |
max_width | number |
maximum width of the message |
min_height | number |
minimum height of the message |
min_length | number |
minimum length of the message (total width of all the lines) |
min_width | number |
minimum width of the message |
mode | string |
checks if vim.api.nvim_get_mode() contains the given mode |
not | filter |
checks whether the filter matches or not |
warning | boolean |
all warning-like kinds from ext_messages |
Noice comes with the following built-in backends:
search_count
)A View (config.views
) is a combination of a backend
and options.
Noice comes with the following built-in views with sane defaults:
View | Backend | Description |
---|---|---|
notify | notify |
nvim-notify with level=nil , replace=false , merge=false |
split | split |
horizontal split |
vsplit | split |
vertical split |
popup | popup |
simple popup |
mini | mini |
minimal view, by default bottom right, right-aligned |
cmdline | popup |
bottom line, similar to the classic cmdline |
cmdline_popup | popup |
fancy cmdline popup, with different styles according to the cmdline mode |
cmdline_output | split |
split used by config.presets.cmdline_output_to_split |
messages | split |
split used for :messages |
confirm | popup |
popup used for confirm events |
hover | popup |
popup used for lsp signature help and hover |
popupmenu | nui.menu |
special view with the options used to render the popupmenu when backend is nui |
Please refer to noice.config.views
to see the options.
Any options passed to existing views in config.views
, will override those options only.
You can configure completely new views and use them in custom routes.
All built-in Noice views have the filetype
noice
See the Nui documentation for Popup and Split.
Option | Description |
size, position | Size, position and their constituents can additionally be specified as "auto", to use the message height and width. |
win_options.winhighlight | String or can also be a table like: ```lua { win_options = { winhighlight = { Normal = "NormalFloat", FloatBorder = "FloatBorder" }, } } ``` | scrollbar | Set to false to hide the scrollbar. |
Option | Type | Default | Description |
---|---|---|---|
title | string |
"Notification" |
title to be used for the notification. Uses Message.title if available. |
replace | boolean |
false |
when true, messages routing to the same notify instance will replace existing messages instead of pushing a new notification every time |
merge | boolean |
false |
Merge messages into one Notification or create separate notifications |
level | number\|string |
nil |
notification level. Uses Message.level if available. |
Right now there's only an option to set the hl_group
used to render the virtual text.
Formatting options can be specified with config.format
.
For a list of the defaults, please refer to config.format
Noice includes the following formatters:
icon
and hl_group
per levelhl_group
hl_group
hl_group
hl_group
hl_group
to override message highlightsconfirm
messages. Will format the choices as buttons.Message.opts
. Useful in combination with the opts passed to vim.notify
Formatters are used in format
definitions. Noice includes the following built-in formats:
{
-- default format
default = { "{level} ", "{title} ", "{message}" },
-- default format for vim.notify views
notify = { "{message}" },
-- default format for the history
details = {
"{level} ",
"{date} ",
"{event}",
{ "{kind}", before = { ".", hl_group = "NoiceFormatKind" } },
" ",
"{title} ",
"{cmdline} ",
"{message}",
},
telescope = ..., -- formatter used to display telescope results
telescope_preview = ..., -- formatter used to preview telescope results
fzf = ..., -- formatter used to display fzf results
fzf_preview = ..., -- formatter used to preview fzf results
lsp_progress = ..., -- formatter used by lsp progress
lsp_progress_done = ..., -- formatter used by lsp progress
}
Text before/after the formatter or in the before/after options, will only be rendered if the formatter itself rendered something.
The format
view option, can be either a string
(one of the built-in formats), or a table with a custom format definition.
To align text, you can use the align
option for a view. Can be center
, left
or right
.
A route has a filter
, view
and optional opts
attribute.
Route options can be any of the view options above, or one of:
Option | Type | Default | Description |
---|---|---|---|
skip | boolean |
false |
messages matching this filter will be skipped and not shown in any views |
stop | boolean |
true |
When false and a route matches the filter, then other routes can still process the message too. Useful if you want certain messages to be shown in multiple views. |
Please refer to noice.config.routes
for an overview of the default routes.
Routes passed to setup()
will be prepended to the default routes.
Noice comes with the following statusline components:
event=show_msg
)showcmd
showmode
(@recording messages)See noice.config.status for the default config.
You can add custom statusline components in setup under the status
key.
Statusline components have the following methods:
For convenience, you can do :Noice pick
, which will open a picker with all the messages in the history,
either with telescope
or fzf-lua
.
In order to use Noice in Telescope, you can either do :Noice telescope
,
or register the extension and use :Telescope noice
.
The results panel is formatted using config.format.formatters.telescope
. The preview is formatted with config.format.formatters.telescope_preview
require("telescope").load_extension("noice")
In order to use Noice in FzfLua, you can do :Noice fzf
.
The results panel is formatted using config.format.formatters.fzf
. The preview is formatted with config.format.formatters.telescope_fzf
:Noice
or :Noice history
shows the message history:Noice last
shows the last message in a popup:Noice dismiss
dismiss all visible messages:Noice errors
shows the error messages in a split. Last errors on top:Noice disable
disables Noice:Noice enable
enables Noice:Noice stats
shows debugging stats:Noice telescope
opens message history in TelescopeAlternatively, all commands also exist as a full name like :NoiceLast
, :NoiceDisable
.
You can also use Lua
equivalents.
vim.keymap.set("n", "<leader>nl", function()
require("noice").cmd("last")
end)
vim.keymap.set("n", "<leader>nh", function()
require("noice").cmd("history")
end)
You can add custom commands with
config.commands
Sometimes it's useful to redirect the messages generated by a command or function to a different view. That can be easily achieved with command redirection.
The redirect API can taken an optional routes
parameter, which defaults to {config.redirect}
.
-- redirect ":hi"
require("noice").redirect("hi")
-- redirect some function
require("noice").redirect(function()
print("test")
end)
Adding the following keymap, will redirect the active cmdline when pressing <S-Enter>
.
The cmdline stays open, so you can change the command and execute it again.
When exiting the cmdline, the popup window will be focused.
vim.keymap.set("c", "<S-Enter>", function()
require("noice").redirect(vim.fn.getcmdline())
end, { desc = "Redirect Cmdline" })
vim.keymap.set({ "n", "i", "s" }, "<c-f>", function()
if not require("noice.lsp").scroll(4) then
return "<c-f>"
end
end, { silent = true, expr = true })
vim.keymap.set({ "n", "i", "s" }, "<c-b>", function()
if not require("noice.lsp").scroll(-4) then
return "<c-b>"
end
end, { silent = true, expr = true })