Awesome
<a name="readme-top"></a>
<br /> <div align="center"> <a href="https://github.com/Cassin01/wf.nvim"> <!-- <img src=".github/images/logo.png" alt="Logo" width="80" height="80"> --> <img src=".github/images/logo_white.png" alt="Logo" width="200" height="200"> </a> <!-- <h3 align="center">wf.nvim</h3> --> <p align="center"> <!-- A which-key with a fuzzy-find. --> <br /> <a href="https://github.com/Cassin01/wf.nvim/blob/main/doc/wf.txt"><strong>Explore the docs »</strong></a> <br /> <br /> <a href="https://youtu.be/S3aKshSPyiQ">View Demo</a> · <a href="https://github.com/Cassin01/wf.nvim/issues">Report Bug</a> · <a href="https://github.com/Cassin01/wf.nvim/issues">Request Feature</a> </p> </div> <!-- TABLE OF CONTENTS --> <!-- <details> --> <summary>Table of Contents</summary> <ol> <li> <a href="#about-the-project">About The Project</a> </li> <li><a href="#installation">Installation</a></li> <li><a href="#getting-started">Getting started</a></li> <li><a href="#configuration">Configuration</a></li> <li><a href="#key-bindings-assignments">Default Shortcut / Key Bindings Assignments</a></li> <li><a href="#documentation">Documentation</a></li> <li><a href="#how-to-use-as-a-picker">How to use as a picker</a></li> <li><a href="#contributing">Contributing</a></li> <li><a href="#license">License</a></li> <li><a href="#credits">Credits</a></li> </ol> <!-- </details> --> <!-- ABOUT THE PROJECT -->About The Project
<div align="center"> <!-- > Drag your video (<10MB) here to host it for free on GitHub. --> <!-- [![Product Name Screen Shot][product-screenshot]](https://github.com/Cassin01/wf.nvim) --> </div> <div align="center"> <!-- > Videos don't work on GitHub mobile, so a GIF alternative can help users. -->The video link for mobile users
</div>wf.nvim
is a new which-key like plugin for Neovim.
✨ Features
- Built-in fuzzy-finder
- Does not provide a default global keymap
- Using
nvim_set_keymap
's "desc" feature (see:help nvim_set_keymap
) - for Neovim 0.7 and higher, it uses the desc as key description
- Skip duplicate characters (
skip_front_duplication
,skip_back_duplication
) - Builtin pickers:
which-key
: displays key mappings to invokemark
: displays marks to movebookmark
: displays file paths to openbuffer
: displays buffers to focusregister
: displays the contents of registers
The difference with which-key.nvim
The display of wf.nvim
is displayed in a row at the bottom right like helix. Instead of displaying multiple columns at the bottom like spacemacs style. This has improved the display speed of multibyte characters in particular.
Pros
- The layout does not collapse even if multibyte characters are included.
- You can use the builtin fuzzy finder to find forgotten shortcuts.
- Three themes(default, space, chad) are offered.
- Fits any color scheme.
- The colors change to match the color scheme.
- Stress-free selection even when long letters are available as options.
- See
skip_front_duplication
andskip_back_duplication
at the document.
- See
- Modal selection is made possible by adopting an event-driven architecture instead of waiting for a key with a while loop.
Cons
- Slower processing speed for larger number of runtime process
Installation
<!-- <div align="center"> --> <table> <thead> <tr> <th>Package manager</th> <th>Snippet</th> </tr> </thead> <tbody> <tr> <td> </td> <td>-- stable version
use {"Cassin01/wf.nvim", tag = "*", config = function() require("wf").setup() end}
-- dev version
use {"Cassin01/wf.nvim", config = function() require("wf").setup() end}
</td>
</tr>
<tr>
<td>
</td>
<td>
call plug#begin()
-- stable version
Plug "Cassin01/wf.nvim", { "tag": "*" }
-- dev version
Plug "Cassin01/wf.nvim"
call plug#end()
lua << EOF
require("wf").setup()
EOF
</td>
</tr>
<tr>
<td>
</td>
<td>
-- stable version
require("lazy").setup({{"Cassin01/wf.nvim", version = "*", config = function() require("wf").setup() end}})
-- dev version
require("lazy").setup({{"Cassin01/wf.nvim", config = function() require("wf").setup() end}})
</td>
</tr>
</tbody>
</table>
<!-- </div> -->
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Getting started
<!-- There is no required dependencies on `wf.nvim` but -->Neovim >= 0.9.0 and
nvim-web-devicons is recommended
for enjoying all the features of wf.nvim
.
local which_key = require("wf.builtin.which_key")
local register = require("wf.builtin.register")
local bookmark = require("wf.builtin.bookmark")
local buffer = require("wf.builtin.buffer")
local mark = require("wf.builtin.mark")
-- Register
vim.keymap.set(
"n",
"<Space>wr",
-- register(opts?: table) -> function
-- opts?: option
register(),
{ noremap = true, silent = true, desc = "[wf.nvim] register" }
)
-- Bookmark
vim.keymap.set(
"n",
"<Space>wbo",
-- bookmark(bookmark_dirs: table, opts?: table) -> function
-- bookmark_dirs: directory or file paths
-- opts?: option
bookmark({
nvim = "~/.config/nvim",
zsh = "~/.zshrc",
}),
{ noremap = true, silent = true, desc = "[wf.nvim] bookmark" }
)
-- Buffer
vim.keymap.set(
"n",
"<Space>wbu",
-- buffer(opts?: table) -> function
-- opts?: option
buffer(),
{noremap = true, silent = true, desc = "[wf.nvim] buffer"}
)
-- Mark
vim.keymap.set(
"n",
"'",
-- mark(opts?: table) -> function
-- opts?: option
mark(),
{ nowait = true, noremap = true, silent = true, desc = "[wf.nvim] mark"}
)
-- Which Key
vim.keymap.set(
"n",
"<Leader>",
-- mark(opts?: table) -> function
-- opts?: option
which_key({ text_insert_in_advance = "<Leader>" }),
{ noremap = true, silent = true, desc = "[wf.nvim] which-key /", }
)
If you are concerned about the lag between pressing the shortcut that activates which-key
and the actual activation of which-key
, you can put the nowait
option in the keymap. (Not recommended.)
However, in order for the key to be invoked nowait, the shortcut to invoke which-key
must be at the end of the init.lua
file.
Below is an example of using timeout
to delay the registration of the shortcut that activates which-key
.
-- set keymaps with `nowait`
-- see `:h :map-nowait`
-- a timer to call a callback after a specified number of milliseconds.
local function timeout(ms, callback)
local uv = vim.loop
local timer = uv.new_timer()
local _callback = vim.schedule_wrap(function()
uv.timer_stop(timer)
uv.close(timer)
callback()
end)
uv.timer_start(timer, ms, 0, _callback)
end
timeout(100, function()
vim.keymap.set(
"n",
"<Leader>",
which_key({ text_insert_in_advance = "<Leader>" }),
{ noremap = true, silent = true, desc = "[wf.nvim] which-key /", }
)
end)
vim.api.nvim_create_autocmd({"BufEnter", "BufAdd"}, {
group = vim.api.nvim_create_augroup("my_wf", { clear = true }),
callback = function()
timeout(100, function()
vim.keymap.set(
"n",
"<Leader>",
which_key({ text_insert_in_advance = "<Leader>" }),
{ noremap = true, silent = true, desc = "[wf.nvim] which-key /", buffer = true })
end)
end
})
<!-- </details> -->
<!-- > Describe how to use the plugin the simplest way -->
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Configuration
<!-- > The configuration list sometimes become cumbersome, making it folded by default reduce the noise of the README file. --> <!-- <details> --> <!-- <summary>Click to unfold the full list of options with their default values</summary> --> <!-- > **Note**: The options are also available in Neovim by calling `:h wf.options` -->require("wf").setup({
theme = "default",
-- you can copy the full list from lua/wf/setup/init.lua
})
<!-- </details> -->
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Key Bindings Assignments
The default key assignments are shown in the table below.
Mode | Key | Action |
---|---|---|
Normal, Insert | <c-t> | Toggle the which-key with the fuzzy-find |
Normal | <esc> | Close wf.nvim |
Normal | <c-c> | Close wf.nvim |
How to use as a picker
The core concept of wf.nvim
is to extend the functionality of which-key so that it can be used as a picker rather than just a shortcut completion.
To realize this concept, wf.nvim
can be used as a picker to select an item from arbitrary items like vim.ui.select({items}, {opts}, {on_choice})
, i.e. wf.select({items}, {opts}, {on_choice})
.
Example:
require("wf").select({happy = "😊", sad = "😥"}, {
title = "Select your feelings:", behavior = {
skip_front_duplication = true,
skip_back_duplication = true,
},
}, function(text, key)
-- You feel happy😊.
vim.notify("You feel " .. key .. text .. ".")
end)
end
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Documentation
You can find guides for the plugin on the document.
<p align="right">(<a href="#readme-top">back to top</a>)</p>Tips
Holding specific key pattern on which_key
<!-- It may be a bit arrogant to call it tips, but here is my init.lua setup. -->Below is an example of using keys_group_dict
. keys_group_dict
is a list of prefix patterns.
Keys with that pattern can be grouped together when displayed.
-- setup table for prefixes
---------------------------------------
if _G.__key_prefixes == nil then
_G.__key_prefixes = {
n = {},
i = {},
}
end
-- utility function for setting keymaps
---------------------------------------
local function nmaps(prefix, group, tbl)
local sign = "[" .. group .. "] "
table.insert(_G.__key_prefixes["n"], prefix, sign)
local set = function(key, cmd, desc, opt)
local _opt = opt or {}
_opt["desc"] = sign .. desc
_opt["noremap"] = true
vim.keymap.set("n", prefix .. key, cmd, _opt)
end
for _, v in ipairs(tbl) do
set(unpack(v))
end
end
-- set keymap for each plugins
---------------------------------------
-- lambdalisue/fern.vim
nmaps("<space>n", "fern",
{{"p", "<cmd>Fern . -drawer -toggle<cr>", "open fern on a current working directory"},
{"d", "<cmd>Fern %:h -drawer -toggle<cr>", "open fern on a parent directory of a current buffer"}})
-- nvim-telescope/telescope.nvim
nmaps("<space>t", "telescope"
{{"f", "<cmd>Telescope find_files<cr>", "find files"},
{"g", "<cmd>Telescope live_grep<cr>", "live grep"},
{"b", "<cmd>Telescope buffers<cr>", "buffers"},
{"h", "<cmd>Telescope help_tags<cr>", "help tags"},
{"t", "<cmd>Telescope<cr>", "telescope"},
{"o", "<cmd>Telescope oldfiles<cr>", "old files"},
{"r", "<cmd>Telescope file_browser<cr>", "file_browser"}})
-- set keymap for calling which-key
---------------------------------------
vim.set.keymap("n", "<Space>",
which_key({text_insert_in_advance="<space>", key_group_dict=_G.__key_prefixes["n"]}),
{noremap = true, silent = tre, desc = "which-key space", nowait = true})
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- CONTRIBUTING -->
Contributing
Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
Development flow basically follows git-flow.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Generate document, format codes and test codes (
make push
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
License
Distributed under the MIT License. See LICENSE.txt
for more information.