linrongbin16 / fzfx.nvim

A Neovim fuzzy finder that updates on every keystroke.
https://linrongbin16.github.io/fzfx.nvim/
MIT License
124 stars 5 forks source link
lua neovim neovim-plugin plugin

fzfx.nvim

require commons.nvim luarocks ci.yml codecov

A Neovim fuzzy finder that updates on every keystroke.

https://github.com/linrongbin16/fzfx.nvim/assets/6496887/b5e2b0dc-4dd6-4c18-b1da-f54419efbba3

Search require("fzfx with rg's -g *spec.lua -F option.

šŸ“– Table of contents

āœØ Features

Please see Demo for more use cases.

āœ… Requirements

[!NOTE]

This plugin keeps up with the latest Neovim stable version, supports until the last legacy version, while earlier versions are dropped to reduce maintenance effort.

For example, at the time of writing (2024-06-11), stable is 0.10, last legacy is 0.9, nightly is 0.11, thus this plugin supports 0.9+.

Windows

Besides those rust-written commands mentioned above (rg/fd/bat), Windows users will have to install the linux shell environment and core utils, since basic shell commands such as echo, mkdir are internally required.

Click here to see how to install linux commands
There're many ways to install portable linux shell and core utils on Windows, personally I would recommend below two methods: #### [Git for Windows](https://git-scm.com/download/win) Install with the below 3 options: - In **Select Components**, select **Associate .sh files to be run with Bash**. install-windows-git-step1.jpg - In **Adjusting your PATH environment**, select **Use Git and optional Unix tools from the Command Prompt**. install-windows-git-step2.jpg - In **Configuring the terminal emulator to use with Git Bash**, select **Use Windows's default console window**. install-windows-git-step3.jpg After this step, **git.exe** and builtin linux commands(such as **echo.exe**, **ls.exe**, **curl.exe**) will be available in `%PATH%`. #### [scoop](https://scoop.sh/) Run below powershell commands: ```powershell # scoop Set-ExecutionPolicy RemoteSigned -Scope CurrentUser irm get.scoop.sh | iex scoop bucket add extras scoop install git # git, bash, sh scoop install mingw # echo, grep, find, curl, ls, cat scoop install coreutils # echo, grep, find, curl, ls, cat ``` #### Fix conflicts between embedded commands from `C:\Windows\System32` and linux commands Windows actually already provide some builtin commands (`find.exe`, `bash.exe`) in `C:\Windows\System32` (or `%SystemRoot%\system32`), but they are not the linux commands they are named after, while could override above installations. To fix it, we need to prioritize (move up) the git or scoop environment variables in `%PATH%`. windows-path

šŸ“¦ Install

[!NOTE]

You can specify the plugin version/tag (i.e. v5.*) to avoid break changes between major versions!

With lazy.nvim ```lua require("lazy").setup({ -- optional for icons { "nvim-tree/nvim-web-devicons" }, -- optional for the 'fzf' command { "junegunn/fzf", build = function() vim.fn["fzf#install"]() end, }, { "linrongbin16/fzfx.nvim", dependencies = { "nvim-tree/nvim-web-devicons", 'junegunn/fzf' }, -- specify version to avoid break changes -- version = 'v5.*', config = function() require("fzfx").setup() end, }, }) ```
With packer.nvim ```lua return require("packer").startup(function(use) -- optional for icons use({ "nvim-tree/nvim-web-devicons" }) -- optional for the 'fzf' command use({ "junegunn/fzf", run = function() vim.fn["fzf#install"]() end, }) use({ "linrongbin16/fzfx.nvim", -- specify version to avoid break changes -- version = 'v5.0.0', config = function() require("fzfx").setup() end, }) end) ```
With vim-plug ```vim call plug#begin() " optional for icons Plug 'nvim-tree/nvim-web-devicons' " optional for the 'fzf' command Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } " specify version to avoid break changes Plug 'linrongbin16/fzfx.nvim' ", { 'tag': 'v5.0.0' } call plug#end() lua require('fzfx').setup() ```

šŸš€ Usage

There're multiple commands provided, named with prefix Fzfx. The sub commands indicates the user query's input method, (i.e. the variants) named with below conventions:

[!NOTE]

The args sub command can be omitted, for example :FzfxFiles<CR> is equivalent to :FzfxFiles args<CR>.

To specify query text, for example asdf, you will have to type :FzfxFiles args asdf<CR>.

Below keys are binded by default:

Files & Buffers

Name Details
FzfxFiles
Find files.
  1. Use ctrl-q to send selected lines to quickfix window and quit.
  2. Unrestricted variant is named with unres_ suffix.
Variant Mode Select Keys Preview Keys
(unres_)args N Yes Yes
(unres_)visual V
(unres_)cword N
(unres_)put N
(unres_)resume N
FzfxBuffers
Find buffers.
  1. Use ctrl-q to send selected lines to quickfix window and quit.
Variant Mode Select Keys Preview Keys
args N Yes Yes
visual V
cword N
put N
resume N
FzfxGFiles
Find git files.
  1. Use ctrl-q to send selected lines to quickfix window and quit.
  2. Current directory (only) variant is named with cwd_ suffix.
Variant Mode Select Keys Preview Keys
(cwd_)args N Yes Yes
(cwd_)visual V
(cwd_)cword N
(cwd_)put N
(cwd_)resume N

Grep

Name Details
FzfxLiveGrep
Live grep.
  1. Use ctrl-q to send selected lines to quickfix window and quit.
  2. Use -- flag to pass raw options to search command (rg/grep).
  3. Unrestricted variant is named with unres_ suffix.
  4. Current buffer (only) variant is named with buf_ suffix.
Variant Mode Select Keys Preview Keys
(unres_/buf_)args N Yes Yes
(unres_/buf_)visual V
(unres_/buf_)cword N
(unres_/buf_)put N
(unres_/buf_)resume N
FzfxBufLiveGrep
Live grep only on current buffer.
  1. This command has the same functionality with FzfxLiveGrep currently buffer variant (buf_), while the file name is removed for better user view.
  2. Use ctrl-q to send selected lines to quickfix window and quit.
  3. Use -- flag to pass raw options to search command (rg/grep).
Variant Mode Select Keys Preview Keys
args N Yes Yes
visual V
cword N
put N
resume N
FzfxGLiveGrep
Live grep with git grep.
  1. Use ctrl-q to send selected lines to quickfix window and quit.
  2. Use -- flag to pass raw options to search command (git grep).
Variant Mode Select Keys Preview Keys
args N Yes Yes
visual V
cword N
put N
resume N

Git

Name Details
FzfxGStatus
Search git status (changed files).
  1. Use ctrl-q to send selected lines to quickfix window and quit.
  2. Current directory (only) variant is named with cwd_ suffix.
Variant Mode Select Keys Preview Keys
(cwd_)args N Yes Yes
(cwd_)visual V
(cwd_)cword N
(cwd_)put N
(cwd_)resume N
FzfxGBranches
Search git branches.
  1. Use enter to checkout branch.
  2. Remote branch variant is named with remote_ suffix.
Variant Mode Select Keys Preview Keys
(remote_)args N No Yes
(remote_)visual V
(remote_)cword N
(remote_)put N
(remote_)resume N
FzfxGCommits
Search git commits.
  1. Use enter to copy git commit SHA.
  2. Current buffer variant is named with buf_ suffix.
Variant Mode Select Keys Preview Keys
(buf_)args N No Yes
(buf_)visual V
(buf_)cword N
(buf_)put N
(buf_)resume N
FzfxGBlame
Search git blame.
  1. Use enter to copy git commit SHA.
Variant Mode Select Keys Preview Keys
args N No Yes
visual V
cword N
put N
resume N

Lsp & Diagnostics

Name Details
FzfxLspDefinitions
Search definitions.
  1. The args variant always use cursor word as query content (not command arguments), because the scenario is navigating symbols, i.e. go to definitions.
  2. Use protocol textDocument/definition.
Variant Mode Select Keys Preview Keys
args N Yes Yes
FzfxLspTypeDefinitions
Search type definitions.
  1. The args variant always use cursor word as query content (not command arguments), because the scenario is navigating symbols, i.e. go to type definitions.
  2. Use protocol textDocument/typeDefinition.
Variant Mode Select Keys Preview Keys
args N Yes Yes
FzfxLspImplementations
Search implementations.
  1. The args variant always use cursor word as query content (not command arguments), because the scenario is navigating symbols, i.e. go to implementations.
  2. Use protocol textDocument/implementation.
Variant Mode Select Keys Preview Keys
args N Yes Yes
FzfxLspReferences
Search references.
  1. The args variant always use cursor word as query content (not command arguments), because the scenario is navigating symbols, i.e. go to references.
  2. Use protocol textDocument/references.
Variant Mode Select Keys Preview Keys
args N Yes Yes
FzfxLspIncomingCalls
Search incoming calls.
  1. The args variant always use cursor word as query content (not command arguments), because the scenario is navigating symbols, i.e. go to incoming calls.
  2. Use protocol callHierarchy/incomingCalls.
Variant Mode Select Keys Preview Keys
args N Yes Yes
FzfxLspOutgoingCalls
Search outgoing calls.
  1. The args variant always use cursor word as query content (not command arguments), because the scenario is navigating symbols, i.e. go to outgoing calls.
  2. Use protocol callHierarchy/outgoingCalls.
Variant Mode Select Keys Preview Keys
args N Yes Yes
FzfxLspDiagnostics
Search diagnostics.
  1. Use ctrl-q to send selected lines to quickfix window and quit.
  2. Current buffer (only) variant is named with buf_ suffix.
Variant Mode Select Keys Preview Keys
(buf_)args N Yes Yes
(buf_)visual V
(buf_)cword N
(buf_)put N
(buf_)resume N

Vim

Name Details
FzfxCommands
Search vim commands.
  1. Use enter to input command.
  2. Ex (builtin) commands variant is named with ex_ suffix.
  3. User commands variant is named with user_ suffix.
Variant Mode Select Keys Preview Keys
(ex_/user_)args N No Yes
(ex_/user_)visual V
(ex_/user_)cword N
(ex_/user_)put N
(ex_/user_)resume N
FzfxKeyMaps
Search vim key mappings.
  1. Use enter to execute key mapping.
  2. Normal mode variant is named with n_mode_ suffix.
  3. Insert mode variant is named with i_mode_ suffix.
  4. Visual/select mode variant is named with v_mode_ suffix.
Variant Mode Select Keys Preview Keys
(n_mode_/i_mode_/v_mode_)args N No Yes
(n_mode_/i_mode_/v_mode_)visual V
(n_mode_/i_mode_/v_mode_)cword N
(n_mode_/i_mode_/v_mode_)put N
(n_mode_/i_mode_/v_mode_)resume N
FzfxMarks
Search vim marks.
  1. Use ctrl-q to send selected lines to quickfix window and quit.
Variant Mode Select Keys Preview Keys
args N No Yes
visual V
cword N
put N
resume N

Misc

Name Details
FzfxFileExplorer
Navigate around file explorer.
  1. Include hidden variant is named with hidden_ suffix.
Variant Mode Select Keys Preview Keys
(hidden_)args N Yes Yes
(hidden_)visual V
(hidden_)cword N
(hidden_)put N
(hidden_)resume N

šŸ“Œ Recommended Key Mappings

Click here to see vim scripts
```vim " ======== files ======== " by args nnoremap f :\FzfxFiles " by visual select xnoremap f :\FzfxFiles visual " by cursor word nnoremap wf :\FzfxFiles cword " by yank text nnoremap pf :\FzfxFiles put " by resume nnoremap rf :\FzfxFiles resume " ======== live grep ======== " by args nnoremap l :\FzfxLiveGrep " by visual select xnoremap l :\FzfxLiveGrep visual " by cursor word nnoremap wl :\FzfxLiveGrep cword " by yank text nnoremap pl :\FzfxLiveGrep put " by resume nnoremap rl :\FzfxLiveGrep resume " ======== buffers ======== " by args nnoremap bf :\FzfxBuffers " ======== git files ======== " by args nnoremap gf :\FzfxGFiles " ======== git live grep ======== " by args nnoremap gl :\FzfxGLiveGrep " by visual select xnoremap gl :\FzfxGLiveGrep visual " by cursor word nnoremap wgl :\FzfxGLiveGrep cword " by yank text nnoremap pgl :\FzfxGLiveGrep put " by resume nnoremap rgl :\FzfxGLiveGrep resume " ======== git changed files (status) ======== " by args nnoremap gs :\FzfxGStatus " ======== git branches ======== " by args nnoremap br :\FzfxGBranches " ======== git commits ======== " by args nnoremap gc :\FzfxGCommits " ======== git blame ======== " by args nnoremap gb :\FzfxGBlame " ======== lsp diagnostics ======== " by args nnoremap dg :\FzfxLspDiagnostics " ======== lsp locations ======== " lsp definitions nnoremap gd :\FzfxLspDefinitions " lsp type definitions nnoremap gt :\FzfxLspTypeDefinitions " lsp references nnoremap gr :\FzfxLspReferences " lsp implementations nnoremap gi :\FzfxLspImplementations " lsp incoming calls nnoremap gI :\FzfxLspIncomingCalls " lsp outgoing calls nnoremap gO :\FzfxLspOutgoingCalls " ======== vim commands ======== " by args nnoremap cm :\FzfxCommands " ======== vim key maps ======== " by args nnoremap km :\FzfxKeyMaps " ======== vim marks ======== " by args nnoremap mk :\FzfxMarks " ======== file explorer ======== " by args nnoremap xp :\FzfxFileExplorer ```
Click here to see lua scripts
```lua -- ======== files ======== -- by args vim.keymap.set( "n", "f", "FzfxFiles", { silent = true, noremap = true, desc = "Find files" } ) -- by visual select vim.keymap.set( "x", "f", "FzfxFiles visual", { silent = true, noremap = true, desc = "Find files" } ) -- by cursor word vim.keymap.set( "n", "wf", "FzfxFiles cword", { silent = true, noremap = true, desc = "Find files by cursor word" } ) -- by yank text vim.keymap.set( "n", "pf", "FzfxFiles put", { silent = true, noremap = true, desc = "Find files by yank text" } ) -- by resume vim.keymap.set( "n", "rf", "FzfxFiles resume", { silent = true, noremap = true, desc = "Find files by resume last" } ) -- ======== live grep ======== -- live grep vim.keymap.set( "n", "l", "FzfxLiveGrep", { silent = true, noremap = true, desc = "Live grep" } ) -- by visual select vim.keymap.set( "x", "l", "FzfxLiveGrep visual", { silent = true, noremap = true, desc = "Live grep" } ) -- by cursor word vim.keymap.set( "n", "wl", "FzfxLiveGrep cword", { silent = true, noremap = true, desc = "Live grep by cursor word" } ) -- by yank text vim.keymap.set( "n", "pl", "FzfxLiveGrep put", { silent = true, noremap = true, desc = "Live grep by yank text" } ) -- by resume vim.keymap.set( "n", "rl", "FzfxLiveGrep resume", { silent = true, noremap = true, desc = "Live grep by resume last" } ) -- ======== buffers ======== -- by args vim.keymap.set( "n", "bf", "FzfxBuffers", { silent = true, noremap = true, desc = "Find buffers" } ) -- ======== git files ======== -- by args vim.keymap.set( "n", "gf", "FzfxGFiles", { silent = true, noremap = true, desc = "Find git files" } ) -- ======== git live grep ======== -- by args vim.keymap.set( "n", "gl", "FzfxGLiveGrep", { silent = true, noremap = true, desc = "Git live grep" } ) -- by visual select vim.keymap.set( "x", "gl", "FzfxGLiveGrep visual", { silent = true, noremap = true, desc = "Git live grep" } ) -- by cursor word vim.keymap.set( "n", "wgl", "FzfxGLiveGrep cword", { silent = true, noremap = true, desc = "Git live grep by cursor word" } ) -- by yank text vim.keymap.set( "n", "pgl", "FzfxGLiveGrep put", { silent = true, noremap = true, desc = "Git live grep by yank text" } ) -- by resume vim.keymap.set( "n", "rgl", "FzfxGLiveGrep resume", { silent = true, noremap = true, desc = "Git live grep by resume last" } ) -- ======== git changed files (status) ======== -- by args vim.keymap.set( "n", "gs", "FzfxGStatus", { silent = true, noremap = true, desc = "Find git changed files (status)" } ) -- ======== git branches ======== -- by args vim.keymap.set( "n", "br", "FzfxGBranches", { silent = true, noremap = true, desc = "Search git branches" } ) -- ======== git commits ======== -- by args vim.keymap.set( "n", "gc", "FzfxGCommits", { silent = true, noremap = true, desc = "Search git commits" } ) -- ======== git blame ======== -- by args vim.keymap.set( "n", "gb", "FzfxGBlame", { silent = true, noremap = true, desc = "Search git blame" } ) -- ======== lsp diagnostics ======== -- by args vim.keymap.set( "n", "dg", "FzfxLspDiagnostics", { silent = true, noremap = true, desc = "Search lsp diagnostics" } ) -- ======== lsp symbols ======== -- lsp definitions vim.keymap.set( "n", "gd", "FzfxLspDefinitions", { silent = true, noremap = true, desc = "Goto lsp definitions" } ) -- lsp type definitions vim.keymap.set( "n", "gt", "FzfxLspTypeDefinitions", { silent = true, noremap = true, desc = "Goto lsp type definitions" } ) -- lsp references vim.keymap.set( "n", "gr", "FzfxLspReferences", { silent = true, noremap = true, desc = "Goto lsp references" } ) -- lsp implementations vim.keymap.set( "n", "gi", "FzfxLspImplementations", { silent = true, noremap = true, desc = "Goto lsp implementations" } ) -- lsp incoming calls vim.keymap.set( "n", "gI", "FzfxLspIncomingCalls", { silent = true, noremap = true, desc = "Goto lsp incoming calls" } ) -- lsp outgoing calls vim.keymap.set( "n", "gO", "FzfxLspOutgoingCalls", { silent = true, noremap = true, desc = "Goto lsp outgoing calls" } ) -- ======== vim commands ======== -- by args vim.keymap.set( "n", "cm", "FzfxCommands", { silent = true, noremap = true, desc = "Search vim commands" } ) -- ======== vim key maps ======== -- by args vim.keymap.set( "n", "km", "FzfxKeyMaps", { silent = true, noremap = true, desc = "Search vim keymaps" } ) -- ======== vim marks ======== -- by args vim.keymap.set( "n", "mk", "FzfxMarks", { silent = true, noremap = true, desc = "Search vim marks" } ) -- ======== file explorer ======== -- by args vim.keymap.set( "n", "xp", "FzfxFileExplorer", { silent = true, noremap = true, desc = "File explorer" } ) ```

šŸ”§ Configuration

To configure options, please use:

require('fzfx').setup(opts)

The opts is an optional lua table that override the default options.

For complete default options, please see config.lua.

For advanced configurations, please check Advanced Configuration.

Feature Flags

To enable/disable some features, please define below global variables before setup this plugin:

Create Your Own Command

Here's a minimal example that implement the ls -1 like FzfxLs command:

https://github.com/linrongbin16/fzfx.nvim/assets/6496887/c704e5b2-d82a-45f2-8920-adeec5d3e7c2

Click here to see how to configure ```lua require("fzfx").setup() require("fzfx").register("ls", { --- @type CommandConfig command = { name = "FzfxLs", desc = "File Explorer (ls -1)", }, variants = { { name = "args", feed = "args", default_provider = "filter_hiddens", }, { name = "hidden_args", feed = "args", default_provider = "include_hiddens", }, }, --- @type table providers = { filter_hiddens = { key = "ctrl-h", provider = { "ls", "--color=always", "-1" }, }, include_hiddens = { key = "ctrl-u", provider = { "ls", "--color=always", "-1a" }, }, }, --- @type table previewers = { filter_hiddens = { previewer = function(line) -- each line is either a folder or a file return vim.fn.isdirectory(line) > 0 and { "ls", "--color=always", "-lha", line } or { "cat", line } end, previewer_type = "command_list", }, include_hiddens = { previewer = function(line) return vim.fn.isdirectory(line) > 0 and { "ls", "--color=always", "-lha", line } or { "cat", line } end, previewer_type = "command_list", }, }, actions = { ["esc"] = function(lines) -- do nothing end, ["enter"] = function(lines) for _, line in ipairs(lines) do vim.cmd(string.format([[edit %s]], line)) end end, }, fzf_opts = { "--multi", { "--prompt", "Ls > " }, }, }) ```

First setup this plugin, then use require("fzfx").register(name, opts}) api to create your own searching command.

For detailed explanation of each components, please see A Generic Schema for Creating FZF Command and schema.lua.

API References

To help easier customizing/integrating, fzfx provides below modules and APIs.

It's highly recommended to use these APIs when you're creating a new searching command, rather than start from scratch, since they are usually robust and take various situations into consideration.

Please see API References for more details.

šŸŖ² Known Issues

Please see Known Issues if you encountered any issue.

šŸ€ Alternatives

āœļø Development

To develop the project and make PR, please setup with:

To run unit tests, please install below dependencies:

Then test with vusted ./spec.

šŸŽ Contribute

Please open issue/PR for anything about fzfx.nvim.

Like fzfx.nvim? Consider

Github Sponsor Wechat Pay Alipay