### require("which-key").setup(opts) Source: https://context7.com/folke/which-key.nvim/llms.txt Initializes and configures the which-key.nvim plugin. This function should be called before any mappings are processed. It accepts an optional `wk.Opts` table to customize various aspects of the plugin, such as presets, delays, filters, inline specifications, plugin integrations, window appearance, layout, sorting, expansion, icons, and debug settings. Setup can be deferred until `VimEnter` if Neovim has not fully started. It also registers the `:WhichKey [mode] [keys]` user command. ```APIDOC ## require("which-key").setup(opts) — Initialize and configure which-key ### Description Bootstraps which-key with a merged options table. Must be called (or will be called automatically on first use) before any mappings are processed. Accepts a `wk.Opts` table; all fields are optional and deep-merged with defaults. Setup is deferred until `VimEnter` if Neovim has not fully started. Also registers the `:WhichKey [mode] [keys]` user command. ### Method ```lua require("which-key").setup({ preset = "modern", -- "classic" | "modern" | "helix" | false -- Delay before popup appears; 0 for plugin-triggered popups delay = function(ctx) return ctx.plugin and 0 or 200 end, -- Filter out mappings without a description filter = function(mapping) return mapping.desc and mapping.desc ~= "" end, -- Inline spec: define mappings at setup time spec = { { "f", group = "file" }, { "ff", "Telescope find_files", desc = "Find File" }, }, plugins = { marks = true, registers = true, spelling = { enabled = true, suggestions = 20 }, presets = { operators = true, motions = true, text_objects = true, windows = true, nav = true, z = true, g = true, }, }, win = { no_overlap = true, padding = { 1, 2 }, title = true, title_pos = "center", zindex = 1000, wo = { winblend = 10 }, }, layout = { width = { min = 20 }, spacing = 3 }, sort = { "local", "order", "group", "alphanum", "mod" }, expand = 0, -- auto-expand groups with <= n mappings icons = { breadcrumb = "»", separator = "➜", group = "+", mappings = true, -- set false to disable all mapping icons colors = true, }, show_help = true, show_keys = true, notify = true, debug = false, disable = { ft = { "TelescopePrompt" }, bt = { "terminal" } }, }) ``` ``` -------------------------------- ### Initialize and Configure which-key Plugin Source: https://context7.com/folke/which-key.nvim/llms.txt Call this function to bootstrap and configure which-key. It accepts a table of options that are deep-merged with defaults. Setup is deferred until `VimEnter` if Neovim has not fully started. This function also registers the `:WhichKey [mode] [keys]` user command. ```lua require("which-key").setup({ preset = "modern", -- "classic" | "modern" | "helix" | false -- Delay before popup appears; 0 for plugin-triggered popups delay = function(ctx) return ctx.plugin and 0 or 200 end, -- Filter out mappings without a description filter = function(mapping) return mapping.desc and mapping.desc ~= "" end, -- Inline spec: define mappings at setup time spec = { { "f", group = "file" }, { "ff", "Telescope find_files", desc = "Find File" }, }, plugins = { marks = true, registers = true, spelling = { enabled = true, suggestions = 20 }, presets = { operators = true, motions = true, text_objects = true, windows = true, nav = true, z = true, g = true, }, }, win = { no_overlap = true, padding = { 1, 2 }, title = true, title_pos = "center", zindex = 1000, wo = { winblend = 10 }, }, layout = { width = { min = 20 }, spacing = 3 }, sort = { "local", "order", "group", "alphanum", "mod" }, expand = 0, -- auto-expand groups with <= n mappings icons = { breadcrumb = "»", separator = "➜", group = "+", mappings = true, -- set false to disable all mapping icons colors = true, }, show_help = true, show_keys = true, notify = true, debug = false, disable = { ft = { "TelescopePrompt" }, bt = { "terminal" } }, }) ``` -------------------------------- ### Install which-key.nvim with Lazy.nvim Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Install the plugin using the Lazy.nvim package manager. Configure options within the `opts` table or leave it empty for default settings. ```lua { "folke/which-key.nvim", event = "VeryLazy", opts = { -- your configuration comes here -- or leave it empty to use the default settings -- refer to the configuration section below }, keys = { { "?", function() require("which-key").show({ global = false }) end, desc = "Buffer Local Keymaps (which-key)", }, }, } ``` -------------------------------- ### Install which-key.nvim with lazy.nvim Source: https://context7.com/folke/which-key.nvim/llms.txt This configuration snippet shows how to install and set up which-key.nvim as a plugin using lazy.nvim. It includes options for presets, delays, and defining keymap specifications with groups and icons. ```lua { "folke/which-key.nvim", event = "VeryLazy", opts = { preset = "modern", delay = 200, spec = { { "c", group = "code", icon = { icon = "󰅩", color = "blue" } }, { "d", group = "debug", icon = { icon = "", color = "red" } }, { "f", group = "find", icon = { icon = "", color = "cyan" } }, { "g", group = "git", icon = { icon = "", color = "orange" } }, { "h", group = "hunk", icon = { icon = "", color = "green" } }, { "n", group = "noice" }, { "s", group = "session" }, { "t", group = "test" }, { "u", group = "ui" }, { "x", group = "diagnostics/quickfix", icon = "󱖫" }, -- Proxy w to the built-in window commands { "w", proxy = "", group = "windows" }, -- Dynamic buffer/window switching { "b", group = "buffers", expand = function() return require("which-key.extras").expand.buf() end }, { "W", group = "windows", expand = function() return require("which-key.extras").expand.win() end }, }, icons = { rules = { { pattern = "telescope", icon = "", color = "blue" }, { pattern = "lsp", icon = "󰒍", color = "green" }, }, }, disable = { ft = { "TelescopePrompt", "neo-tree" } }, }, keys = { { "?", function() require("which-key").show({ global = false }) end, desc = "Buffer Local Keymaps" }, { "", function() require("which-key").show({ keys = "", loop = true }) end, desc = "Window Hydra Mode" }, }, } ``` -------------------------------- ### Manually Setup Triggers with which-key.nvim Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Shows how to manually set up triggers for which-key.nvim, specifying a leader key and modes for triggering. ```lua triggers = { { "", mode = { "n", "v" } }, } ``` -------------------------------- ### Configure which-key.nvim Options Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Example of configuring which-key.nvim options, including showing help and keys, disabling for specific buffer/file types, and enabling debug logging. ```lua show_help = true, show_keys = true, -- disable WhichKey for certain buf types and file types. disable = { ft = {}, bt = {}, }, debug = false ``` -------------------------------- ### Configure Icons with wk.Icon and opts.icons.rules Source: https://context7.com/folke/which-key.nvim/llms.txt Set icons globally using `opts.icons.rules` or per-mapping with strings or `wk.Icon` tables. Icons are resolved automatically if `mini.icons` or `nvim-web-devicons` is installed. ```lua require("which-key").setup({ icons = { breadcrumb = "»", separator = "➜", group = "+", mappings = true, -- false disables all mapping icons colors = true, -- use mini.icons highlight groups -- Custom rules applied to all mappings rules = { { pattern = "git", icon = "", color = "orange" }, { pattern = "find", icon = "", color = "blue" }, { pattern = "debug", icon = "", color = "red" }, { plugin = "flash", icon = "⚡", color = "yellow" }, }, }, }) -- Per-mapping icon as string require("which-key").add({ { "gd", "Gitsigns diffthis", desc = "Diff", icon = "" }, -- Per-mapping icon as wk.Icon object { "gf", "G", desc = "Fugitive", icon = { icon = "", color = "orange", -- named color }}, -- Resolve from mini.icons / nvim-web-devicons by category { "ln", desc = "New Lua File", icon = { cat = "filetype", name = "lua", -- resolves to Lua filetype icon }}, -- Icon with explicit highlight group { "xx", desc = "Diagnostics", icon = { icon = "󰅚", hl = "DiagnosticError", }}, }) ``` -------------------------------- ### Configure Auto Triggers for which-key.nvim Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Example of configuring automatic triggers for which-key.nvim, including default auto triggers and custom triggers for specific modes. ```lua triggers = { { "", mode = "nixsotc" }, { "a", mode = { "n", "v" } }, } ``` -------------------------------- ### Configure which-key Triggers with opts.triggers and opts.defer Source: https://context7.com/folke/which-key.nvim/llms.txt Customize when which-key intercepts input using `opts.triggers`. The special `` value installs triggers for specified modes automatically. `opts.defer` can delay the popup appearance, useful for operators. ```lua require("which-key").setup({ -- Default: auto-triggers for normal, visual, select, operator modes triggers = { { "", mode = "nxso" }, }, -- Custom: auto in most modes + manual trigger for 'a' in n/v triggers = { { "", mode = "nixsotc" }, { "a", mode = { "n", "v" } }, }, -- Manual only: only trigger on and triggers = { { "", mode = { "n", "v" } }, { "", mode = "n" }, }, -- Defer popup for d/y operators and block-visual mode defer = function(ctx) if vim.list_contains({ "d", "y" }, ctx.operator) then return true end return vim.list_contains({ "", "V" }, ctx.mode) end, }) ``` -------------------------------- ### Configure Which-key.nvim Plugin Source: https://github.com/folke/which-key.nvim/blob/main/README.md Set up the main configuration table for which-key.nvim. Customize icon rules, color usage, key mappings, and display preferences. ```lua { -- Set to `false` to disable keymap icons from rules --@type wk.IconRule[]|false rules = {}, -- use the highlights from mini.icons -- When `false`, it will use `WhichKeyIcon` instead colors = true, -- used by key format keys = { Up = " ", Down = " ", Left = " ", Right = " ", C = "󰘴 ", M = "󰘵 ", D = "󰘳 ", S = "󰘶 ", CR = "󰌑 ", Esc = "󱊷 ", ScrollWheelDown = "󱕐 ", ScrollWheelUp = "󱕑 ", NL = "󰌑 ", BS = "󰁮", Space = "󱁐 ", Tab = "󰌒 ", F1 = "󱊫", F2 = "󱊬", F3 = "󱊭", F4 = "󱊮", F5 = "󱊯", F6 = "󱊰", F7 = "󱊱", F8 = "󱊲", F9 = "󱊳", F10 = "󱊴", F11 = "󱊵", F12 = "󱊶", }, }, show_help = true, -- show a help message in the command line for using WhichKey show_keys = true, -- show the currently pressed key and its label as a message in the command line -- disable WhichKey for certain buf types and file types. disable = { ft = {}, bt = {}, }, debug = false, -- enable wk.log in the current directory } ``` -------------------------------- ### require("which-key").register(mappings, opts?) Source: https://context7.com/folke/which-key.nvim/llms.txt Legacy v1 API for registering mappings, kept for backward compatibility. It uses an older nested-table format and internally delegates to `wk.add()`. A migration warning is triggered, and users are advised to use the v3 spec instead. ```APIDOC ## `require("which-key").register(mappings, opts?) Legacy v1 API (deprecated) The original v1 registration API, kept for backward compatibility. Mappings use the old nested-table-with-string-values format instead of the v3 spec. Internally delegates to `wk.add()` with `{ version = 1 }`. Run `:checkhealth which-key` to get an auto-generated migration suggestion. ### Parameters #### `mappings` (table) - The v1 style nested table of mappings. #### `opts` (table, optional) - Options for registration, such as the mode. ### Example (v1 deprecated style) ```lua -- v1 (deprecated) style – still works but triggers a migration warning require("which-key").register({ [""] = { f = { name = "+file", f = { "Telescope find_files", "Find File" }, r = { "Telescope oldfiles", "Recent Files" }, }, b = { name = "+buffer", d = { "bd", "Delete Buffer" }, }, }, }, { mode = "n" }) -- Equivalent v3 spec (use this instead): require("which-key").add({ { "f", group = "file" }, { "ff", "Telescope find_files", desc = "Find File" }, { "fr", "Telescope oldfiles", desc = "Recent Files" }, { "b", group = "buffer" }, { "bd", "bd", desc = "Delete Buffer" }, }) ``` ``` -------------------------------- ### Programmatically Open Popup with `require("which-key").show` Source: https://context7.com/folke/which-key.nvim/llms.txt Use `require("which-key").show` to manually open the popup, optionally filtered by key prefix, mode, or buffer scope. Set `loop = true` for Hydra Mode, where the popup remains open until `` is pressed. ```lua local wk = require("which-key") -- Show all buffer-local keymaps in current mode vim.keymap.set("n", "?", function() wk.show({ global = false }) end, { desc = "Buffer Local Keymaps" }) -- Show all mappings immediately (no delay) vim.keymap.set("n", "", function() wk.show({ keys = "", mode = "n", delay = 0 }) end, { desc = "Show Leader Mappings" }) -- Show visual-mode keymaps vim.keymap.set("v", "?", function() wk.show({ mode = "v" }) end, { desc = "Visual Mode Keymaps" }) -- Hydra mode: keep popup open for window management vim.keymap.set("n", "W", function() wk.show({ keys = "", loop = true }) end, { desc = "Window Hydra Mode" }) ``` -------------------------------- ### Default Configuration Options for Which-key.nvim Source: https://github.com/folke/which-key.nvim/blob/main/README.md This snippet shows the default configuration options for Which-key.nvim. It includes settings for presets, delay, filtering, plugins, window appearance, layout, keybindings, sorting, expansion, and icons. Adjust these to customize the plugin's behavior. ```lua ---@class wk.Opts local defaults = { ---@type false | "classic" | "modern" | "helix" preset = "classic", -- Delay before showing the popup. Can be a number or a function that returns a number. ---@type number | fun(ctx: { keys: string, mode: string, plugin?: string }):number delay = function(ctx) return ctx.plugin and 0 or 200 end, ---@param mapping wk.Mapping filter = function(mapping) -- example to exclude mappings without a description -- return mapping.desc and mapping.desc ~= "" return true end, --- You can add any mappings here, or use `require('which-key').add()` later ---@type wk.Spec spec = {}, -- show a warning when issues were detected with your mappings notify = true, -- Which-key automatically sets up triggers for your mappings. -- But you can disable this and setup the triggers manually. -- Check the docs for more info. ---@type wk.Spec triggers = { { "", mode = "nxso" }, }, -- Start hidden and wait for a key to be pressed before showing the popup -- Only used by enabled xo mapping modes. ---@param ctx { mode: string, operator: string } defer = function(ctx) return ctx.mode == "V" or ctx.mode == "" end, plugins = { marks = true, -- shows a list of your marks on ' and ` registers = true, -- shows your registers on " in NORMAL or in INSERT mode -- the presets plugin, adds help for a bunch of default keybindings in Neovim -- No actual key bindings are created spelling = { enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions suggestions = 20, -- how many suggestions should be shown in the list? }, presets = { operators = true, -- adds help for operators like d, y, ... motions = true, -- adds help for motions text_objects = true, -- help for text objects triggered after entering an operator windows = true, -- default bindings on nav = true, -- misc bindings to work with windows z = true, -- bindings for folds, spelling and others prefixed with z g = true, -- bindings for prefixed with g }, }, ---@type wk.Win.opts win = { -- don't allow the popup to overlap with the cursor no_overlap = true, -- width = 1, -- height = { min = 4, max = 25 }, -- col = 0, -- row = math.huge, -- border = "none", padding = { 1, 2 }, -- extra window padding [top/bottom, right/left] title = true, title_pos = "center", zindex = 1000, -- Additional vim.wo and vim.bo options bo = {}, wo = { -- winblend = 10, -- value between 0-100 0 for fully opaque and 100 for fully transparent }, }, layout = { width = { min = 20 }, -- min and max width of the columns spacing = 3, -- spacing between columns }, keys = { scroll_down = "", -- binding to scroll down inside the popup scroll_up = "", -- binding to scroll up inside the popup }, ---@type (string|wk.Sorter)[] --- Mappings are sorted using configured sorters and natural sort of the keys --- Available sorters: --- * local: buffer-local mappings first --- * order: order of the items (Used by plugins like marks / registers) --- * group: groups last --- * alphanum: alpha-numerical first --- * mod: special modifier keys last --- * manual: the order the mappings were added --- * case: lower-case first sort = { "local", "order", "group", "alphanum", "mod" }, ---@type number|fun(node: wk.Node):boolean? expand = 0, -- expand groups when <= n mappings -- expand = function(node) -- return not node.desc -- expand all nodes without a description -- end, -- Functions/Lua Patterns for formatting the labels ---@type table replace = { key = { function(key) return require("which-key.view").format(key) end, -- { "", "SPC" }, }, desc = { { "%(?(.*)%)?", "%1" }, { "^%+", "" }, { "<[cC]md>", "" }, { "<[cC][rR]>", "" }, { "<[sS]ilent>", "" }, { "^lua%s+", "" }, { "^call%s+", "" }, { "^:%s*", "" }, }, }, icons = { breadcrumb = "»", -- symbol used in the command line area that shows your active key combo separator = "➜", -- symbol used between a key and it's label group = "+", -- symbol prepended to a group ellipsis = "…", -- set to false to disable all mapping icons, -- both those explicitly added in a mapping -- and those from rules mappings = true, --- See `lua/which-key/icons.lua` for more details } } ``` -------------------------------- ### Configure Layout Presets Source: https://context7.com/folke/which-key.nvim/llms.txt Set the window layout for which-key popups using built-in presets like 'classic', 'modern', or 'helix'. You can also disable presets entirely for full customization. ```lua -- Classic (default): full-width bar at the bottom require("which-key").setup({ preset = "classic", -- win: width=∞, height={min=4,max=25}, col=0, row=-1, border="none" }) ``` ```lua -- Modern: centered floating window require("which-key").setup({ preset = "modern", -- win: width=0.9, height={min=4,max=25}, col=0.5, row=-1, border="rounded" }) ``` ```lua -- Helix: narrow side panel (top-right corner) require("which-key").setup({ preset = "helix", -- win: width={min=30,max=60}, height={min=4,max=75%}, col=-1, row=-1, border="rounded" -- layout: width={min=30} }) ``` ```lua -- Fully custom (no preset) require("which-key").setup({ preset = false, win = { width = { min = 20, max = 80 }, height = { min = 4, max = 20 }, border = "single", title = true, title_pos = "left", no_overlap = true, padding = { 0, 1 }, wo = { winblend = 15 }, }, layout = { width = { min = 20, max = 50 }, spacing = 4 }, }) ``` -------------------------------- ### require("which-key").show(opts?) Source: https://context7.com/folke/which-key.nvim/llms.txt Programmatically opens the which-key popup. It can be filtered by key prefix, mode, or buffer scope. The `loop = true` option activates Hydra Mode, keeping the popup open until Esc is pressed. ```APIDOC ## `require("which-key").show(opts?) Programmatically open the popup Opens the which-key popup manually, optionally filtered to a specific key prefix, mode, or buffer scope. Useful for keymaps that show a contextual cheat-sheet. `opts` is a `wk.Filter` table. Passing `loop = true` activates **Hydra Mode** — the popup stays open until `` is pressed. ### Parameters #### `opts` (table, optional) - A `wk.Filter` table with options to filter the popup content. - `keys` (string): Filter by a specific key prefix. - `mode` (string): Filter by a specific mode (e.g., 'n', 'v'). - `global` (boolean): Whether to show global keymaps (default: true). - `delay` (number): Delay in milliseconds before showing the popup (default: depends on configuration). - `loop` (boolean): Activate Hydra Mode, keeping the popup open until Esc is pressed. ### Examples ```lua local wk = require("which-key") -- Show all buffer-local keymaps in current mode vim.keymap.set("n", "?", function() wk.show({ global = false }) end, { desc = "Buffer Local Keymaps" }) -- Show all mappings immediately (no delay) vim.keymap.set("n", "", function() wk.show({ keys = "", mode = "n", delay = 0 }) end, { desc = "Show Leader Mappings" }) -- Show visual-mode keymaps vim.keymap.set("v", "?", function() wk.show({ mode = "v" }) end, { desc = "Visual Mode Keymaps" }) -- Hydra mode: keep popup open for window management vim.keymap.set("n", "W", function() wk.show({ keys = "", loop = true }) end, { desc = "Window Hydra Mode" }) -- Via the :WhichKey command (mode prefix optional) -- :WhichKey → normal mode, all prefixes -- :WhichKey n → normal mode, leader prefix -- :WhichKey v → visual mode ``` ``` -------------------------------- ### Configure which-key.nvim Window Options Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Customize the appearance and behavior of the which-key.nvim popup window. Options include preventing overlap with the cursor, setting padding, title display, z-index, and additional buffer/window local options. ```lua win = { -- don't allow the popup to overlap with the cursor no_overlap = true, -- width = 1, -- height = { min = 4, max = 25 }, -- col = 0, -- row = math.huge, -- border = "none", padding = { 1, 2 }, -- extra window padding [top/bottom, right/left] title = true, title_pos = "center", zindex = 1000, -- Additional vim.wo and vim.bo options bo = {}, wo = { -- winblend = 10, -- value between 0-100 0 for fully opaque and 100 for fully transparent }, } ``` -------------------------------- ### Configure which-key.nvim Layout Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Adjust the layout of the which-key.nvim popup window, including minimum and maximum width for columns and spacing between them. ```lua layout = { width = { min = 20 }, -- min and max width of the columns spacing = 3, -- spacing between columns } ``` -------------------------------- ### Expand Buffer List Dynamically with which-key.extras.expand.buf() Source: https://context7.com/folke/which-key.nvim/llms.txt Use this function to dynamically populate which-key's popup with a list of the ten most recently used buffers, excluding the current one. It's ideal for creating fresh buffer lists each time the popup opens. ```lua require("which-key").add({ { "b", group = "buffers", expand = function() return require("which-key.extras").expand.buf() end }, -- Result in popup: -- b0 → switch to src/main.lua -- b1 → switch to README.md -- b2 → switch to tests/spec.lua -- ...up to 10 buffers }) ``` -------------------------------- ### Configure which-key.nvim Label Replacement Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Define rules for replacing or formatting keys and descriptions in which-key.nvim. This includes using a custom function for key formatting and regular expressions for description cleaning. ```lua replace = { key = { function(key) return require("which-key.view").format(key) end, -- { "", "SPC" }, }, desc = { { "%(?(.*)%)?", "%1" }, { "^%+", "" }, { "<[cC]md>", "" }, { "<[cC][rR]>", "" }, { "<[sS]ilent>", "" }, { "^lua%s+", "" }, { "^call%s+", "" }, { "^:%s*", "" }, }, } ``` -------------------------------- ### Add Mappings with which-key.nvim Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Demonstrates how to add custom keymap mappings using `which-key.nvim`'s `add` function. This includes defining groups, descriptions, modes, and nested mappings. ```lua local wk = require("which-key") wk.add({ { "f", group = "file" }, -- group { "ff", "Telescope find_files", desc = "Find File", mode = "n" }, { "fb", function() print("hello") end, desc = "Foobar" }, { "fn", desc = "New File" }, { "f1", hidden = true }, -- hide this keymap { "w", proxy = "", group = "windows" }, -- proxy to window mappings { "b", group = "buffers", expand = function() return require("which-key.extras").expand.buf() end }, { -- Nested mappings are allowed and can be added in any order -- Most attributes can be inherited or overridden on any level -- There's no limit to the depth of nesting mode = { "n", "v" }, -- NORMAL and VISUAL mode { "q", "q", desc = "Quit" }, -- no need to specify mode since it's inherited { "w", "w", desc = "Write" }, } }) ``` -------------------------------- ### Configure which-key.nvim Expansion Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Control the expansion of groups in which-key.nvim based on the number of mappings or a custom function. ```lua expand = 0, -- expand groups when <= n mappings -- expand = function(node) -- return not node.desc -- expand all nodes without a description -- end ``` -------------------------------- ### Configure which-key.nvim Keybindings for Scrolling Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Define custom keybindings for scrolling within the which-key.nvim popup window. ```lua keys = { scroll_down = "", -- binding to scroll down inside the popup scroll_up = "", -- binding to scroll up inside the popup } ``` -------------------------------- ### Default Configuration Options for which-key.nvim Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Explore the default configuration options for which-key.nvim, including presets, delay settings, filters, and trigger configurations. Use `:checkhealth which-key` if issues arise. ```lua --@class wk.Opts local defaults = { --@type false | "classic" | "modern" | "helix" preset = "classic", -- Delay before showing the popup. Can be a number or a function that returns a number. --@type number | fun(ctx: { keys: string, mode: string, plugin?: string }):number delay = function(ctx) return ctx.plugin and 0 or 200 end, --@param mapping wk.Mapping filter = function(mapping) -- example to exclude mappings without a description -- return mapping.desc and mapping.desc ~= "" return true end, -- You can add any mappings here, or use `require('which-key').add()` later --@type wk.Spec spec = {}, -- show a warning when issues were detected with your mappings notify = true, -- Which-key automatically sets up triggers for your mappings. -- But you can disable this and setup the triggers manually. -- Check the docs for more info. --@type wk.Spec triggers = { { "", mode = "nxso" }, }, -- Start hidden and wait for a key to be pressed before showing the popup } ``` -------------------------------- ### Configure which-key.nvim Icons Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Customize icons used in which-key.nvim for breadcrumbs, separators, groups, ellipsis, and mappings. Includes options for icon rules and color integration. ```lua icons = { breadcrumb = "»", -- symbol used in the command line area that shows your active key combo separator = "➜", -- symbol used between a key and it's label group = "+", -- symbol prepended to a group ellipsis = "…", -- set to false to disable all mapping icons, -- both those explicitly added in a mapping -- and those from rules mappings = true, --- See `lua/which-key/icons.lua` for more details --- Set to `false` to disable keymap icons from rules ---@type wk.IconRule[]|false rules = {}, -- use the highlights from mini.icons -- When `false`, it will use `WhichKeyIcon` instead colors = true, -- used by key format keys = { Up = " ", Down = " ", Left = " ", Right = " ", C = "󰘴 ", M = "󰘵 ", D = "󰘳 ", S = "󰘶 ", CR = "󰌑 ", Esc = "󱊷 ", ScrollWheelDown = "󱕐 ", ScrollWheelUp = "󱕑 ", NL = "󰌑 ", BS = "󰁮", Space = "󱁐 ", Tab = "󰌒 ", F1 = "󱊫", F2 = "󱊬", F3 = "󱊭", F4 = "󱊮", F5 = "󱊯", F6 = "󱊰", F7 = "󱊱", F8 = "󱊲", F9 = "󱊳", F10 = "󱊴", F11 = "󱊵", F12 = "󱊶", }, } ``` -------------------------------- ### Expand Window List Dynamically with which-key.extras.expand.win() Source: https://context7.com/folke/which-key.nvim/llms.txt This function provides a dynamic list of non-floating windows for which-key's popup, excluding the current window. It's useful for quickly switching focus between open splits. ```lua require("which-key").add({ { "W", group = "windows", expand = function() return require("which-key.extras").expand.win() end }, -- Result in popup (with two splits open): -- W0 → focus window containing init.lua -- W1 → focus window containing CHANGELOG.md }) ``` -------------------------------- ### Configure which-key.nvim Plugins Source: https://github.com/folke/which-key.nvim/blob/main/doc/which-key.nvim.txt Enable or disable specific plugins within which-key.nvim to customize its functionality. This includes options for marks, registers, spelling suggestions, and presets for operators, motions, text objects, windows, navigation, and 'z'/'g' prefixed bindings. ```lua defer = function(ctx) return ctx.mode == "V" or ctx.mode == "" end, plugins = { marks = true, -- shows a list of your marks on ' and ` registers = true, -- shows your registers on " in NORMAL or in INSERT mode -- the presets plugin, adds help for a bunch of default keybindings in Neovim -- No actual key bindings are created spelling = { enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions suggestions = 20, -- how many suggestions should be shown in the list? }, presets = { operators = true, -- adds help for operators like d, y, ... motions = true, -- adds help for motions text_objects = true, -- help for text objects triggered after entering an operator windows = true, -- default bindings on nav = true, -- misc bindings to work with windows z = true, -- bindings for folds, spelling and others prefixed with z g = true, -- bindings for prefixed with g }, } ``` -------------------------------- ### Legacy v1 API Registration with `require("which-key").register` Source: https://context7.com/folke/which-key.nvim/llms.txt The `require("which-key").register` function is a legacy v1 API for backward compatibility. It uses an older nested table format for mappings. It is recommended to migrate to the v3 spec using `wk.add()`. ```lua -- v1 (deprecated) style – still works but triggers a migration warning require("which-key").register({ [""] = { f = { name = "+file", f = { "Telescope find_files", "Find File" }, r = { "Telescope oldfiles", "Recent Files" }, }, b = { name = "+buffer", d = { "bd", "Delete Buffer" }, }, }, }, { mode = "n" }) -- Equivalent v3 spec (use this instead): require("which-key").add({ { "f", group = "file" }, { "ff", "Telescope find_files", desc = "Find File" }, { "fr", "Telescope oldfiles", desc = "Recent Files" }, { "b", group = "buffer" }, { "bd", "bd", desc = "Delete Buffer" }, }) ``` -------------------------------- ### Register Mappings and Groups with `require("which-key").add` Source: https://context7.com/folke/which-key.nvim/llms.txt Use `require("which-key").add` to register keymaps and descriptions. Attributes like mode, buffer, and icon are inherited by nested children. This API supports various configurations including dynamic expansion and conditional mappings. ```lua local wk = require("which-key") wk.add({ -- Group label only (no rhs → no keymap created) { "f", group = "file" }, { "g", group = "git", icon = { icon = "", color = "orange" } }, -- Simple mapping (creates the keymap via vim.keymap.set) { "ff", "Telescope find_files", desc = "Find File" }, { "fg", "Telescope live_grep", desc = "Live Grep" }, -- Lua function as rhs { "fb", function() vim.notify("hello from which-key") end, desc = "Say Hello" }, -- Hidden mapping (won't appear in popup) { "f1", hidden = true }, -- Proxy: w acts as , showing window mappings { "w", proxy = "", group = "windows" }, -- Dynamic expansion: numbered keys 0-9 map to open buffers { "b", group = "buffers", expand = function() return require("which-key.extras").expand.buf() end }, -- Conditional mapping (only active when a plugin is loaded) { "u", group = "ui", cond = function() return package.loaded["snacks"] ~= nil end }, -- Multi-mode block: inherit mode = { "n", "v" } for all children { mode = { "n", "v" }, { "q", "q", desc = "Quit" }, { "w", "w", desc = "Write" }, }, -- Buffer-local mapping (buffer = 0 → current buffer) { "r", "source %", desc = "Source File", buffer = 0 }, -- Icon as wk.Icon object { "d", group = "debug", icon = { cat = "filetype", name = "lua" } }, -- Dynamic description (evaluated at popup time) { "s", desc = function() return "Search (" .. vim.fn.getcwd() .. ")" end }, }) ``` -------------------------------- ### Migrate v1 Keymap Spec to v3 Source: https://context7.com/folke/which-key.nvim/llms.txt Use the `migrate` function to convert old v1-style mapping specifications to the v3 format. This is useful for updating configurations or when using `:checkhealth which-key`. ```lua local Migrate = require("which-key.migrate") local v1_spec = { [""] = { f = { name = "+file", f = { "Telescope find_files", "Find File" }, r = { "Telescope oldfiles", "Open Recent" }, }, }, } local v3_lua = Migrate.migrate(v1_spec) print(v3_lua) -- Output (formatted Lua string ready to paste): -- { -- { "f", group = "file" }, -- { "ff", "Telescope find_files", desc = "Find File" }, -- { "fr", "Telescope oldfiles", desc = "Open Recent" }, -- } ``` -------------------------------- ### Configure Keymap Sorting Source: https://context7.com/folke/which-key.nvim/llms.txt Control the order of keymaps in the popup using a list of sorter names. Options include 'local', 'order', 'group', 'alphanum', 'mod', 'manual', 'case', 'desc', and 'icase'. ```lua require("which-key").setup({ -- Available sorters: -- "local" – buffer-local mappings first -- "order" – insertion order (used by marks/registers plugins) -- "group" – groups after individual mappings -- "alphanum"– alphanumeric keys before symbols/modifiers -- "mod" – modifier keys (C-, M-, etc.) last -- "manual" – strict insertion order -- "case" – lowercase before uppercase -- "desc" – alphabetical by description -- "icase" – case-insensitive alphabetical by description sort = { "local", "order", "group", "alphanum", "mod" }, -- default -- Alternative: manual insertion order only sort = { "manual" }, -- Alternative: description-sorted with locals first sort = { "local", "desc" }, -- Auto-expand groups that have 3 or fewer child mappings expand = 3, -- Or use a function for fine-grained control expand = function(node) return not node.desc -- expand all nodes that have no description end, }) ```