Out of box, this plugin reconstructs completion item and applies treesitter highlight queries to produce richly colorized completion items with variable-size highlight ranges.
Has built-in support for
- rust-analyzer (Rust)
- gopls (Go)
- typescript-language-server/vtsls (TypeScript)
- lua-ls (Lua)
- clangd (C/CPP)
- intelephense (PHP)
- zls (Zig)
- roslyn (C#)
- basedpyright/pylance/pyright (Python)
- dartls (Dart)
For other languages, it defaults to use highlight group of item's kind. (feel free to open feature request for more languages)
Currently supports nvim-cmp and blink.cmp.
With lazy.nvim:
return {
"xzbdmw/colorful-menu.nvim",
config = function()
-- You don't need to set these options.
require("colorful-menu").setup({
ls = {
lua_ls = {
-- Maybe you want to dim arguments a bit.
arguments_hl = "@comment",
},
gopls = {
-- By default, we render variable/function's type in the right most side,
-- to make them not to crowd together with the original label.
-- when true:
-- foo *Foo
-- ast "go/ast"
-- when false:
-- foo *Foo
-- ast "go/ast"
align_type_to_right = true,
-- When true, label for field and variable will format like "foo: Foo"
-- instead of go's original syntax "foo Foo". If align_type_to_right is
-- true, this option has no effect.
add_colon_before_type = false,
-- See https://github.com/xzbdmw/colorful-menu.nvim/pull/36
preserve_type_when_truncate = true,
},
-- for lsp_config or typescript-tools
ts_ls = {
-- false means do not include any extra info,
-- see https://github.com/xzbdmw/colorful-menu.nvim/issues/42
extra_info_hl = "@comment",
},
vtsls = {
-- false means do not include any extra info,
-- see https://github.com/xzbdmw/colorful-menu.nvim/issues/42
extra_info_hl = "@comment",
},
["rust-analyzer"] = {
-- Such as (as Iterator), (use std::io).
extra_info_hl = "@comment",
-- Similar to the same setting of gopls.
align_type_to_right = true,
-- See https://github.com/xzbdmw/colorful-menu.nvim/pull/36
preserve_type_when_truncate = true,
},
clangd = {
-- Such as "From <stdio.h>".
extra_info_hl = "@comment",
-- Similar to the same setting of gopls.
align_type_to_right = true,
-- the hl group of leading dot of "•std::filesystem::permissions(..)"
import_dot_hl = "@comment",
-- See https://github.com/xzbdmw/colorful-menu.nvim/pull/36
preserve_type_when_truncate = true,
},
zls = {
-- Similar to the same setting of gopls.
align_type_to_right = true,
},
roslyn = {
extra_info_hl = "@comment",
},
dartls = {
extra_info_hl = "@comment",
},
-- The same applies to pyright/pylance
basedpyright = {
-- It is usually import path such as "os"
extra_info_hl = "@comment",
},
-- If true, try to highlight "not supported" languages.
fallback = true,
},
-- If the built-in logic fails to find a suitable highlight group,
-- this highlight is applied to the label.
fallback_highlight = "@variable",
-- If provided, the plugin truncates the final displayed text to
-- this width (measured in display cells). Any highlights that extend
-- beyond the truncation point are ignored. When set to a float
-- between 0 and 1, it'll be treated as percentage of the width of
-- the window: math.floor(max_width * vim.api.nvim_win_get_width(0))
-- Default 60.
max_width = 60,
})
end,
}
require("cmp").setup({
formatting = {
format = function(entry, vim_item)
local highlights_info = require("colorful-menu").cmp_highlights(entry)
-- highlight_info is nil means we are missing the ts parser, it's
-- better to fallback to use default `vim_item.abbr`. What this plugin
-- offers is two fields: `vim_item.abbr_hl_group` and `vim_item.abbr`.
if highlights_info ~= nil then
vim_item.abbr_hl_group = highlights_info.highlights
vim_item.abbr = highlights_info.text
end
return vim_item
end,
},
})
config = function()
require("blink.cmp").setup({
completion = {
menu = {
draw = {
-- We don't need label_description now because label and label_description are already
-- combined together in label by colorful-menu.nvim.
columns = { { "kind_icon" }, { "label", gap = 1 } },
components = {
label = {
text = function(ctx)
return require("colorful-menu").blink_components_text(ctx)
end,
highlight = function(ctx)
return require("colorful-menu").blink_components_highlight(ctx)
end,
},
},
},
},
},
})
end
If you want to customize a bit more in those options, here is a more granular control approach:
Click to see
config = function()
require("blink.cmp").setup({
completion = {
menu = {
draw = {
-- We don't need label_description now because label and label_description are already
-- combined together in label by colorful-menu.nvim.
columns = { { "kind_icon" }, { "label", gap = 1 } },
components = {
label = {
width = { fill = true, max = 60 },
text = function(ctx)
local highlights_info = require("colorful-menu").blink_highlights(ctx)
if highlights_info ~= nil then
-- Or you want to add more item to label
return highlights_info.label
else
return ctx.label
end
end,
highlight = function(ctx)
local highlights = {}
local highlights_info = require("colorful-menu").blink_highlights(ctx)
if highlights_info ~= nil then
highlights = highlights_info.highlights
end
for _, idx in ipairs(ctx.label_matched_indices) do
table.insert(highlights, { idx, idx + 1, group = "BlinkCmpLabelMatch" })
end
-- Do something else
return highlights
end,
},
},
},
},
},
})
end
You can configure your completion engine (below is for nvim-cmp
with both colorful-menu.nvim
and lspkind.nvim
to get completion menu like those in Screen section.
Click to see
formatting = {
fields = { "kind", "abbr", "menu" },
format = function(entry, vim_item)
local kind = require("lspkind").cmp_format({
mode = "symbol_text",
})(entry, vim.deepcopy(vim_item))
local highlights_info = require("colorful-menu").cmp_highlights(entry)
-- highlight_info is nil means we are missing the ts parser, it's
-- better to fallback to use default `vim_item.abbr`. What this plugin
-- offers is two fields: `vim_item.abbr_hl_group` and `vim_item.abbr`.
if highlights_info ~= nil then
vim_item.abbr_hl_group = highlights_info.highlights
vim_item.abbr = highlights_info.text
end
local strings = vim.split(kind.kind, "%s", { trimempty = true })
vim_item.kind = " " .. (strings[1] or "") .. " "
vim_item.menu = ""
return vim_item
end,
}
đź’ˇ Note: You may want to set
CmpItemAbbrMatch
orBlinkCmpLabelMatch
to only have bold style (withoutfg
) to achieve a similar effect as the images below.










Thanks to @pnx


Thanks to @seblj




Feel free to open issues or submit pull requests if you encounter any bugs or have feature requests.
MIT License.
Zed for the initial idea of colorize.
@David van Munster for the pr which make this plugin possible.
JetBrains for its right-aligned type layout