Skip to content

Commit

Permalink
docs: added documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Apr 28, 2021
1 parent bb90c74 commit 601dbf8
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 138 deletions.
320 changes: 194 additions & 126 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
# 🧐 Which Key

**WhichKey** is a lua plugin for Neovim 0.5 that displays a popup with possible keybindings of the command you started typing.
**WhichKey** is a lua plugin for Neovim 0.5 that displays a popup with possible keybindings of the command you started typing. Heavily inspired by the original [emacs-which-key](https://github.com/justbur/emacs-which-key) and [vim-which-key](https://github.com/liuchengxu/vim-which-key).

## ✨ Features

* opens a poup
* opens a poup with suggestions to complete a key binding
* works with any setting for [timeoutlen](https://neovim.io/doc/user/options.html#'timeoutlen'), including instantly (`timeoutlen=0`)
* works correctly with builtin keybindings
* works correctly with buffer-local mappings
* extensible plugin architecture
* builtin plugins:
+ **marks:** shows your marks when you hit one of the jump keys.
+ **registers:** shows the contents of your registers
+ **presets:** builtin keybinding help for `motions`, `text-objects`, `operators`, `windows`, `nav`, `z` and `g`

## ⚡️ Requirements

* Neovim >= 0.5.0
* Properly configured Neovim LSP client
* [nvim-web-devicons](https://github.com/kyazdani42/nvim-web-devicons) is optional to enable file icons
* a theme with properly configured highlight groups for Neovim LSP Diagnostics
* or install 🌈 [lsp-colors](https://github.com/folke/lsp-colors.nvim) to automatically create the missing highlight groups
* a [patched font](https://www.nerdfonts.com/) for the default severity and fold icons

## 📦 Installation

Expand All @@ -23,11 +26,10 @@ Install the plugin with your preferred package manager:

```vim
" Vim Script
Plug 'kyazdani42/nvim-web-devicons'
Plug 'folke/lsp-trouble.nvim'
Plug 'folke/which-key.nvim'
lua << EOF
require("trouble").setup {
require("which-key").setup {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
Expand All @@ -40,10 +42,9 @@ EOF
```lua
-- Lua
use {
"folke/lsp-trouble.nvim",
requires = "kyazdani42/nvim-web-devicons",
"folke/which-key.nvim",
config = function()
require("trouble").setup {
require("which-key").setup {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
Expand All @@ -54,144 +55,211 @@ use {

## ⚙️ Configuration

### Setup
> ❗️ IMPORTANT: the timeout when **WhichKey** opens is controlled by the vim setting [timeoutlen](https://neovim.io/doc/user/options.html#'timeoutlen'). Please refer to the documentation to properly set it up. Setting it to `0`, will effectively always show **WhichKey** immediately, but a setting of `500` (500ms) is probably more appropriate.
Trouble comes with the following defaults:
WhichKey comes with the following defaults:

```lua
{
height = 10, -- height of the trouble list
icons = true, -- use dev-icons for filenames
mode = "workspace", -- "workspace" or "document"
fold_open = "", -- icon used for open folds
fold_closed = "", -- icon used for closed folds
action_keys = { -- key mappings for actions in the trouble list
close = "q", -- close the list
cancel = "<esc>", -- cancel the preview and get back to your last window / buffer / cursor
refresh = "r", -- manually refresh
jump = {"<cr>", "<tab>"}, -- jump to the diagnostic or open / close folds
toggle_mode = "m", -- toggle between "workspace" and "document" mode
toggle_preview = "P", -- toggle auto_preview
preview = "p", -- preview the diagnostic location
close_folds = {"zM", "zm"}, -- close all folds
open_folds = {"zR", "zr"}, -- open all folds
toggle_fold = {"zA", "za"}, -- toggle fold of current file
previous = "k", -- preview item
next = "j" -- next item
plugins = {
marks = true, -- shows a list of your marks on ' and `
registers = true, -- shows your registers on " in NORMAL or <C-r> in INSERT mode
-- the presets plugin, adds help for a bunch of default keybindings in Neovim
-- No actual key bindings are created
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 <c-w>
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
},
indent_lines = true, -- add an indent guide below the fold icons
auto_open = false, -- automatically open the list when you have diagnostics
auto_close = false, -- automatically close the list when you have no diagnostics
auto_preview = true, -- automatically preview the location of the diagnostic. <esc> to close preview and go back
auto_fold = false, -- automatically fold a file trouble list at creation
signs = {
-- icons / text used for a diagnostic
error = "",
warning = "",
hint = "",
information = ""
},
use_lsp_diagnostic_signs = false -- enabling this will use the signs defined in your lsp client
},
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
},
window = {
border = "none", -- none, single, double, shadow
position = "bottom", -- bottom, top
margin = { 1, 0, 1, 0 }, -- extra window margin [top, right, bottom, left]
padding = { 2, 2, 2, 2 }, -- extra window padding [top, right, bottom, left]
},
layout = {
height = { min = 4, max = 25 }, -- min and max height of the columns
width = { min = 20, max = 50 }, -- min and max width of the columns
spacing = 3, -- spacing between columns
},
}
```

> 💡 if you don't want to use icons or a patched font, you can use the settings below
## 🪄 Setup

With the default settings, **WhichKey** will work out of the box for most builtin keybindings,
but the real power comes from documenting and organizing your own keybindings.

To document and/or setup your own mappings, you need to call the `register` method

```lua
local wk = require("which-key")
wk.register(mappings, opts)
```

Default options for `opts`

```lua
-- settings without a patched font or icons
{
fold_open = "v", -- icon used for open folds
fold_closed = ">", -- icon used for closed folds
indent_lines = false, -- add an indent guide below the fold icons
signs = {
-- icons / text used for a diagnostic
error = "error",
warning = "warn",
hint = "hint",
information = "info"
},
use_lsp_diagnostic_signs = false -- enabling this will use the signs defined in your lsp client
mode = "n", -- NORMAL mode
-- prefix: use "<leader>f" for example for mapping everything related to finding files
-- the prefix is prepended to every mapping part of `mappings`
prefix = "",
buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings
silent = true, -- use `silent` when creating keymaps
noremap = true, -- use `noremap` when creating keymaps
nowait = false, -- use `nowait` when creating keymaps
}
```

## 🚀 Usage
### Mappings

### Commands
Group names use the special `name` key in the tables. There's multiple ways to define the mappings. See some examples below:

Trouble comes with the following commands:
```lua
-- As an example, we will the following mappings:
-- 1. <leader>fn new file
-- 2. <leader>fr show recent files
-- 2. <leader>ff find files
local wk = require("which-key")

-- method 1
wk.register({
f = {
name = "+file",
f = { "<cmd>Telescope find_files<cr>", "Find File" },
r = { "<cmd>Telescope oldfiles<cr>", "Open Recent File" },
n = { "<cmd>enew<cr>", "New File" },
},
}, { prefix = "<leader>" })

-- method 2
wk.register({
["<leader>"] = {
f = {
name = "+file",
f = { "<cmd>Telescope find_files<cr>", "Find File" },
r = { "<cmd>Telescope oldfiles<cr>", "Open Recent File" },
n = { "<cmd>enew<cr>", "New File" },
},
},
})

-- method 3
wk.register({
["<leader>f"] = {
name = "+file",
f = { "<cmd>Telescope find_files<cr>", "Find File" },
r = { "<cmd>Telescope oldfiles<cr>", "Open Recent File" },
n = { "<cmd>enew<cr>", "New File" },
},
})

-- method 4
wk.register({
["<leader>f"] = { name = "+file" },
["<leader>ff"] = { "<cmd>Telescope find_files<cr>", "Find File" },
["<leader>fr"] = { "<cmd>Telescope oldfiles<cr>", "Open Recent File" },
["<leader>fn"] = { "<cmd>enew<cr>", "New File" },
})
```

* **LspTroubleOpen**: open the list
* **LspTroubleWorkspaceOpen**: set mode to "workspace" and open the list
* **LspTroubleDocumentOpen**: set mode to "document" and open the list
* **LspTroubleClose**: close the list
* **LspTroubleToggle**: toggle the list
* **LspTroubleWorkspaceToggle**: set mode to "workspace" and toggle the list (remains open if mode changes)
* **LspTroubleDocumentToggle**: set mode to "document" and toggle the list (remains open if mode changes)
* **LspTroubleRefresh**: manually refresh
If you just want to add help for the mapping, without creating it, you can do the following:

Example keybinding of `<leader>xx` that toggles the trouble list:
```lua
-- only pass one value in the mapping array to just add the help
wk.register({
f = {
name = "+file",
f = { "Find File" },
r = { "Open Recent File" },
},
}, { prefix = "<leader>" })

-- or just pass a string
wk.register({
f = {
name = "+file",
f = "Find File",
r = "Open Recent File",
},
}, { prefix = "<leader>" })
```

```vim
-- Vim Script
nnoremap <leader>xx <cmd>LspTroubleToggle<cr>
You can also pass specific options to some keybinding

```lua
wk.register({
f = {
name = "+file",
f = { "Find File", noremap = false, buffer = 123 },
r = { "Open Recent File" },
},
}, { prefix = "<leader>" })
```

Ignore some keybindings in **WhichKey** by setting their label to `which_key_ignore`

```lua
-- Lua
vim.api.nvim_set_keymap("n", "<leader>xx", "<cmd>LspTroubleToggle<cr>",
{silent = true, noremap = true}
)
wk.register({
["<leader>0"] = "which_key_ignore",
["<leader>1"] = "which_key_ignore",
})
```

## 🚀 Usage

When the **WhichKey** popup is open, you can use the following keybindings (they are also displayed at the bottom of the screen):

* hit one of the keys to open a group or execute a key binding
* `<esc>` to cancel and close the popup
* `<bs>` go up one level
* `<c-d>` scroll down
* `<c-u>` scroll up

Apart from the automatic opening, you can also manually open **WhichKey** for a certain `prefix`:

```vim
:WhichKey " show all mappings
:WhichKey <leader> " show all <leader> mappings
:WhichKey <leader> v " show all <leader> mappings for VISUAL mode
```

## 🔥 Plugins

Three builtin plugins are included with **WhichKey**.

### Marks

Shows a list of your buffer local and global marks when you hit \` or '

### Registers

Shows a list of your buffer local and global registers when you hit " in *NORMAL* mode, or `<c-r>` in *INSERT* mode.

### Presets

Builtin keybinding help for `motions`, `text-objects`, `operators`, `windows`, `nav`, `z` and `g`

## 🎨 Colors

The table below shows all the highlight groups defined for LSP Trouble with their default link.

| Highlight Group | Defaults to |
| --------------------------- | -------------------------------- |
| *LspTroubleCount* | TabLineSel |
| *LspTroubleError* | LspDiagnosticsDefaultError |
| *LspTroubleNormal* | Normal |
| *LspTroubleTextInformation* | LspTroubleText |
| *LspTroubleSignWarning* | LspDiagnosticsSignWarning |
| *LspTroubleLocation* | LineNr |
| *LspTroubleWarning* | LspDiagnosticsDefaultWarning |
| *LspTroublePreview* | Search |
| *LspTroubleTextError* | LspTroubleText |
| *LspTroubleSignInformation* | LspDiagnosticsSignInformation |
| *LspTroubleIndent* | LineNr |
| *LspTroubleSource* | Comment |
| *LspTroubleSignHint* | LspDiagnosticsSignHint |
| *LspTroubleFoldIcon* | CursorLineNr |
| *LspTroubleTextWarning* | LspTroubleText |
| *LspTroubleCode* | Comment |
| *LspTroubleInformation* | LspDiagnosticsDefaultInformation |
| *LspTroubleSignError* | LspDiagnosticsSignError |
| *LspTroubleFile* | Directory |
| *LspTroubleHint* | LspDiagnosticsDefaultHint |
| *LspTroubleTextHint* | LspTroubleText |
| *LspTroubleText* | Normal |



# Todo

* [x] hook into all groups
* [x] show mappings without keymap (zz etc)
* [x] plugin support for marks, registers, text objects
* [x] `<bs>` to go up a level
* [x] config modes
* [x] update buf only
* [x] + thingy for groups
* [x] text objects
* [x] get label from global when not found for buffer
* [x] operators & motions
* [x] show window after timeout?
* [x] make plugins a list of key value with config in value
* [x] cleanup text objects text
* [x] buf local mappings seems to interfere with global mappings (push K in help)
* [x] fix help in visual mode
* [x] Plug>whichkey nop
* [ ] preset plugin
* [x] command should auto stuff
* [x] timeoutlen is always respected and should still work when zero
| Highlight Group | Defaults to | Description |
| ------------------- | ----------- | ------------------------------------------- |
| *WhichKey* | Function | the key |
| *WhichKeyGroup* | Keyword | a group |
| *WhichKeySeparator* | DiffAdded | the separator between the key and its label |
| *WhichKeyDesc* | Identifier | the label of the key |
| *WhichKeyFloat* | NormalFloat | Normal in the popup window |
| *WhichKeyValue* | Comment | used by plugins that provide values |
Loading

0 comments on commit 601dbf8

Please sign in to comment.