feat: allow users to configure the window keymaps
All checks were successful
CI / StyLua (pull_request) Successful in 31s
CI / Luacheck (pull_request) Successful in 52s
CI / Cargo Format (pull_request) Successful in 49s
Conventional Tools Commitlint / Commitlint (pull_request) Successful in 13s
CI / Build and test (pull_request) Successful in 2m50s
CI / StyLua (push) Successful in 44s
CI / Luacheck (push) Successful in 1m4s
CI / Cargo Format (push) Successful in 1m12s
Conventional Tools Commitlint / Commitlint (push) Successful in 17s
CI / Build and test (push) Successful in 6m4s

Summary:

Now you can use the setup configuration to overwrite and override the keymaps
in the ivy window. Each of the actions have now been givin a "key", you can use
the keys to run action on keymaps defined in the config. They will all be
registered in the buffer and run when pressed.

The readme has been updated to document how do this.

Test Plan:

We have the tests that still run. It has been tested manually and gone though
QA before getting merged.
This commit is contained in:
Ade Attwood 2024-10-27 09:19:50 +00:00
parent cfa7e29ae4
commit 6e45d75a1e
3 changed files with 81 additions and 51 deletions

View file

@ -76,6 +76,23 @@ require("ivy").setup {
-- default one. -- default one.
{ "ivy.backends.files", { keymap = "<C-p>" } }, { "ivy.backends.files", { keymap = "<C-p>" } },
}, },
-- Set mappings of your own, you can use the action `key` to define the
-- action you want.
mappings = {
["<CR>"] = "complete"
}
}
```
When defining config overrides in the setup function, this will overwrite any
default config, not merge it. To merge the configuration you can use the
`vim.tbl_extend` use the default configuration and add any extra.
```lua
require("ivy").setup {
mappings = vim.tbl_extend("force", config:get { "mappings" }, {
["<esc>"] = "destroy",
}),
} }
``` ```
@ -129,43 +146,31 @@ show. It will also provide functionality when actions are taken. The Command
and Key Map are the default options provided by the backend, they can be and Key Map are the default options provided by the backend, they can be
customized when you register it. customized when you register it.
| Module | Command | Key Map | Description | | Module | Command | Default Key Map | Description |
| ------------------------------------ | ------------------ | ----------- | ----------------------------------------------------------- | | ------------------------------------ | ------------------ | --------------- | ----------------------------------------------------------- |
| `ivy.backends.files` | IvyFd | \<leader\>p | Find files in your project with a custom rust file finder | | `ivy.backends.files` | IvyFd | \<leader\>p | Find files in your project with a custom rust file finder |
| `ivy.backends.ag` | IvyAg | \<leader\>/ | Find content in files using the silver searcher | | `ivy.backends.ag` | IvyAg | \<leader\>/ | Find content in files using the silver searcher |
| `ivy.backends.rg` | IvyRg | \<leader\>/ | Find content in files using ripgrep cli tool | | `ivy.backends.rg` | IvyRg | \<leader\>/ | Find content in files using ripgrep cli tool |
| `ivy.backends.buffers` | IvyBuffers | \<leader\>b | Search though open buffers | | `ivy.backends.buffers` | IvyBuffers | \<leader\>b | Search though open buffers |
| `ivy.backends.lines` | IvyLines | | Search the lines in the current buffer | | `ivy.backends.lines` | IvyLines | | Search the lines in the current buffer |
| `ivy.backends.lsp-workspace-symbols` | IvyWorkspaceSymbol | | Search for workspace symbols using the lsp workspace/symbol | | `ivy.backends.lsp-workspace-symbols` | IvyWorkspaceSymbol | | Search for workspace symbols using the lsp workspace/symbol |
### Actions ### Actions
Action can be run on selected candidates provide functionality Action can be run on selected candidates provide functionality
| Action | Key Map | Description | | Action | Key | Default Key Map | Description |
| ------------------- | --------- | ---------------------------------------------------------------- | | ------------------- | --------------------- | --------------- | ---------------------------------------------------------------- |
| Complete | \<CR\> | Run the completion function, usually this will be opening a file | | Complete | `complete` | \<CR\> | Run the completion function, usually this will be opening a file |
| Vertical Split | \<C-v\> | Run the completion function in a new vertical split | | Vertical Split | `vsplit` | \<C-v\> | Run the completion function in a new vertical split |
| Split | \<C-s\> | Run the completion function in a new split | | Split | `split` | \<C-s\> | Run the completion function in a new split |
| Destroy | \<C-c\> | Close the results window | | Destroy | `destroy` | \<C-c\> | Close the results window |
| Clear | \<C-u\> | Clear the results window | | Clear | `clear` | \<C-u\> | Clear the results window |
| Delete word | \<C-w\> | Delete the word under the cursor | | Delete word | `delete_word` | \<C-w\> | Delete the word under the cursor |
| Next | \<C-n\> | Move to the next candidate | | Next | `next` | \<C-n\> | Move to the next candidate |
| Previous | \<C-p\> | Move to the previous candidate | | Previous | `previous` | \<C-p\> | Move to the previous candidate |
| Next Checkpoint | \<C-M-n\> | Move to the next candidate and keep Ivy open and focussed | | Next Checkpoint | `next_checkpoint` | \<C-M-n\> | Move to the next candidate and keep Ivy open and focussed |
| Previous Checkpoint | \<C-M-n\> | Move to the previous candidate and keep Ivy open and focussed | | Previous Checkpoint | `previous_checkpoint` | \<C-M-n\> | Move to the previous candidate and keep Ivy open and focussed |
Add your own keymaps for an action by adding a `ftplugin/ivy.lua` file in your config.
Just add a simple keymap like this:
```lua
vim.api.nvim_set_keymap(
"n",
"<esc>",
"<cmd>lua vim.ivy.destroy()<CR>",
{ noremap = true, silent = true, nowait = true }
)
```
## API ## API

View file

@ -28,6 +28,21 @@ config.default_config = {
"ivy.backends.rg", "ivy.backends.rg",
"ivy.backends.lsp-workspace-symbols", "ivy.backends.lsp-workspace-symbols",
}, },
mappings = {
["<C-c>"] = "destroy",
["<C-u>"] = "clear",
["<C-n>"] = "next",
["<C-p>"] = "previous",
["<C-M-n>"] = "next_checkpoint",
["<C-M-p>"] = "previous_checkpoint",
["<CR>"] = "complete",
["<C-v>"] = "vsplit",
["<C-s>"] = "split",
["<BS>"] = "backspace",
["<Left>"] = "left",
["<Right>"] = "right",
["<C-w>"] = "delete_word",
},
} }
return setmetatable(config, config_mt) return setmetatable(config, config_mt)

View file

@ -1,3 +1,5 @@
local config = require "ivy.config"
-- Constent options that will be used for the keymaps -- Constent options that will be used for the keymaps
local opts = { noremap = true, silent = true, nowait = true } local opts = { noremap = true, silent = true, nowait = true }
@ -37,6 +39,24 @@ local function call_gc(items)
end end
end end
local callbacks = {
destroy = "<cmd>lua vim.ivy.destroy()<CR>",
clear = "<cmd>lua vim.ivy.search('')<CR>",
next = "<cmd>lua vim.ivy.next()<CR>",
previous = "<cmd>lua vim.ivy.previous()<CR>",
next_checkpoint = "<cmd>lua vim.ivy.next(); vim.ivy.checkpoint()<CR>",
previous_checkpoint = "<cmd>lua vim.ivy.previous(); vim.ivy.checkpoint()<CR>",
complete = "<cmd>lua vim.ivy.complete(vim.ivy.action.EDIT)<CR>",
vsplit = "<cmd>lua vim.ivy.complete(vim.ivy.action.VSPLIT)<CR>",
split = "<cmd>lua vim.ivy.complete(vim.ivy.action.SPLIT)<CR>",
backspace = "<cmd>lua vim.ivy.input('BACKSPACE')<CR>",
left = "<cmd>lua vim.ivy.input('LEFT')<CR>",
right = "<cmd>lua vim.ivy.input('RIGHT')<CR>",
delete_word = "<cmd>lua vim.ivy.input('DELETE_WORD')<CR>",
}
local window = {} local window = {}
window.index = 0 window.index = 0
@ -75,25 +95,15 @@ window.make_buffer = function()
vim.api.nvim_buf_set_keymap(window.buffer, "n", chars[index], "<cmd>lua vim.ivy.input('" .. char .. "')<CR>", opts) vim.api.nvim_buf_set_keymap(window.buffer, "n", chars[index], "<cmd>lua vim.ivy.input('" .. char .. "')<CR>", opts)
end end
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-c>", "<cmd>lua vim.ivy.destroy()<CR>", opts) local mappings = config:get { "mappings" }
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-u>", "<cmd>lua vim.ivy.search('')<CR>", opts) assert(mappings, "The mappings key is missing from the config, something has gone horribly wrong")
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-n>", "<cmd>lua vim.ivy.next()<CR>", opts) for key, value in pairs(mappings) do
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-p>", "<cmd>lua vim.ivy.previous()<CR>", opts) if callbacks[value] == nil then
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-M-n>", "<cmd>lua vim.ivy.next(); vim.ivy.checkpoint()<CR>", opts) error("The mapping '" .. value .. "' is not a valid ivy callback")
vim.api.nvim_buf_set_keymap( end
window.buffer,
"n", vim.api.nvim_buf_set_keymap(window.buffer, "n", key, callbacks[value], opts)
"<C-M-p>", end
"<cmd>lua vim.ivy.previous(); vim.ivy.checkpoint()<CR>",
opts
)
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<CR>", "<cmd>lua vim.ivy.complete(vim.ivy.action.EDIT)<CR>", opts)
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-v>", "<cmd>lua vim.ivy.complete(vim.ivy.action.VSPLIT)<CR>", opts)
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-s>", "<cmd>lua vim.ivy.complete(vim.ivy.action.SPLIT)<CR>", opts)
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<BS>", "<cmd>lua vim.ivy.input('BACKSPACE')<CR>", opts)
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<Left>", "<cmd>lua vim.ivy.input('LEFT')<CR>", opts)
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<Right>", "<cmd>lua vim.ivy.input('RIGHT')<CR>", opts)
vim.api.nvim_buf_set_keymap(window.buffer, "n", "<C-w>", "<cmd>lua vim.ivy.input('DELETE_WORD')<CR>", opts)
end end
window.get_current_selection = function() window.get_current_selection = function()