E(x)tended commands missing in fzf.vim.
FzfxLiveGrep-v2.mp4
This is the next generation of fzfx.vim, a brand new fzf plugin for Neovim, build from scratch, focused on user friendly, customization and performance.
- Feature
- Requirement
- Install
- Commands
- Recommended Key Mappings
- Configuration
- Break Changes
- Credit
- Development
- Contribute
- Icons & colors.
- Windows support.
- Lua support: preview lua function defined commands and key mappings (todo).
- Fully dynamic parsing user query and selection, a typical use case is passing raw rg options via
--
flag (see demo). - Multiple variants to avoid manual input:
- Search by visual select.
- Search by cursor word.
- Search by yank text.
- Easily switch on data sources:
- Whether to search hidden or ignored files.
- Local or remote git branches.
- All diagnostics on workspace or only on current buffer (todo).
- Maximized configuration.
- ...
Actually all above features are built on an engine that support fully dynamic runtime & pipeline control, it allows you to do almost anything you want, please see Configuration and Wiki.
- Neovim ≥ 0.5.
- Nerd fonts (optional for icons).
- rg (optional for live grep, by default use grep).
- fd (optional for files, by default use find).
- bat (optional for preview files, e.g. the right side of live grep, files, by default use cat).
- git (optional for git commands).
- Neovim ≥ 0.6 (optional for lsp diagnostics commands).
Note:
grep
,find
andcat
are unix/linux builtin commands, while on Windows we don't have a builtin shell environment, so installrg
,fd
andbat
should be a better choice. Also see Windows for how to install linux commands on Windows.
Click here to see how to install linux commands on Windows
There're many ways to install portable linux shell and builtin commands on Windows, but personally I would recommend below two methods.
Install with the below 3 options:
-
In Select Components, select Associate .sh files to be run with Bash.
-
In Adjusting your PATH environment, select Use Git and optional Unix tools from the Command Prompt.
-
In Configuring the terminal emulator to use with Git Bash, select Use Windows's default console window.
After this step, git.exe and builtin linux commands(such as sh.exe, grep.exe, find.exe, sleep.exe, cd.exe, ls.exe) will be available in %PATH%
.
Run below powershell commands:
# scoop
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex
scoop bucket add extras
scoop install git
scoop install mingw
scoop install coreutils
scoop install sleep
scoop install grep
scoop install findutils
Windows actually already provide some commands (find.exe
, bash.exe
) in C:\Windows\System32
(or %SystemRoot%\system32
), which could override our installations. To fix this issue, we could prioritize the git or scoop environment variables in %PATH%
.
![windows-path](https://private-user-images.githubusercontent.com/6496887/261863800-5296429b-daae-40f6-be16-6c065ef7bf05.jpg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUwMzMzMjQsIm5iZiI6MTcyNTAzMzAyNCwicGF0aCI6Ii82NDk2ODg3LzI2MTg2MzgwMC01Mjk2NDI5Yi1kYWFlLTQwZjYtYmUxNi02YzA2NWVmN2JmMDUuanBnP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgzMCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MzBUMTU1MDI0WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NDIxYzI4NTgxMmY5MWI1NDQ3OWNlMDM1YjcwNjY4OGQ1OThhYzhmM2NjNjAwZTMyNjFjNTNhMDc5Njg5OTI4NCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.F8amej_9zTjShj-rtZAHzachV_9VYu2fckpZ5HzTV6I)
Click here to see how whitespace affect escaping characters on path
This plugin internally extends nvim
, fzf
and lua scripts to full path when launching command.
But when there're whitespaces on the path, launching correct shell command becomes quite difficult, since it will seriously affected escaping characters. Here're two typical cases:
-
C:\Program Files\Neovim\bin\nvim.exe
-nvim.exe
installed inC:\Program Files
directory.Please add executables (
nvim.exe
,fzf.exe
) to%PATH%
($env:PATH
in PowerShell), and set theenv
configuration:require("fzfx").setup({ env = { nvim = 'nvim', fzf = 'fzf', } })
This will help fzfx.nvim avoid the shell command issue.
-
C:\Users\Lin Rongbin\opt\Neovim\bin\nvim.exe
or/Users/linrongbin/Library/Application\ Support/Neovim/bin/nvim
-Lin Rongbin
(user name) orApplication Support
(macOS application) contains whitespace.We still cannot handle the 2nd case for now, please always try to avoid whitespaces in path.
Here's an example of searching files command (macOS):
/opt/homebrew/bin/nvim -n --clean --headless -l /Users/linrongbin/.local/share/nvim/lazy/fzfx.nvim/bin/files/provider.lua /tmp/nvim.linrongbin/3NXwys/0
Here's an example of launching fzf command (Windows 10):
C:/Users/linrongbin/github/junegunn/fzf/bin/fzf --query "" --header ":: Press \27[38;2;255;121;198mCTRL-U\27[0m to unrestricted mode" --prompt "~/g/l/fzfx.nvim > " --bind "start:unbind(ctrl-r)" --bind "ctrl-u:unbind(ctrl-u)+execute-silent(C:\\Users\\linrongbin\\scoop\\apps\\neovim\\current\\bin\\nvim.exe -n --clean --headless -l C:\\Users\\linrongbin\\github\\linrongbin16\\fzfx.nvim\\bin\\rpc\\client.lua 1)+change-header(:: Press \27[38;2;255;121;198mCTRL-R\27[0m to restricted mode)+rebind(ctrl-r)+reload(C:\\Users\\linrongbin\\scoop\\apps\\neovim\\current\\bin\\nvim.exe -n --clean --headless -l C:\\Users\\linrongbin\\github\\linrongbin16\\fzfx.nvim\\bin\\files\\provider.lua C:\\Users\\linrongbin\\AppData\\Local\\nvim-data\\fzfx.nvim\\switch_files_provider)" --bind "ctrl-r:unbind(ctrl-r)+execute-silent(C:\\Users\\linrongbin\\scoop\\apps\\neovim\\current\\bin\\nvim.exe -n --clean --headless -l C:\\Users\\linrongbin\\github\\linrongbin16\\fzfx.nvim\\bin\\rpc\\client.lua 1)+change-header(:: Press \27[38;2;255;121;198mCTRL-U\27[0m to unrestricted mode)+rebind(ctrl-u)+reload(C:\\Users\\linrongbin\\scoop\\apps\\neovim\\current\\bin\\nvim.exe -n --clean --headless -l C:\\Users\\linrongbin\\github\\linrongbin16\\fzfx.nvim\\bin\\files\\provider.lua C:\\Users\\linrongbin\\AppData\\Local\\nvim-data\\fzfx.nvim\\switch_files_provider)" --preview "C:\\Users\\linrongbin\\scoop\\apps\\neovim\\current\\bin\\nvim.exe -n --clean --headless -l C:\\Users\\linrongbin\\github\\linrongbin16\\fzfx.nvim\\bin\\files\\previewer.lua {}" --bind "ctrl-l:toggle-preview" --expect "enter" --expect "double-click" >C:\\Users\\LINRON~1\\AppData\\Local\\Temp\\nvim.0\\JSmP06\\2
If the path contains whitespace, that will make all lua scripts contains whitespace, thus the shell command cannot being correctly evaluated.
call plug#begin()
" optional for icons
Plug 'nvim-tree/nvim-web-devicons'
" mandatory
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'linrongbin16/fzfx.nvim'
call plug#end()
lua require('fzfx').setup()
return require('packer').startup(function(use)
-- optional for icons
use { "nvim-tree/nvim-web-devicons" }
-- mandatory
use { "junegunn/fzf", run = ":call fzf#install()" }
use {
"linrongbin16/fzfx.nvim",
config = function()
require("fzfx").setup()
end
}
end)
require("lazy").setup({
-- optional for icons
{ "nvim-tree/nvim-web-devicons" },
-- mandatory
{ "junegunn/fzf", build = ":call fzf#install()" },
{
"linrongbin16/fzfx.nvim",
dependencies = { "junegunn/fzf" },
config = function()
require("fzfx").setup()
end
},
})
Commands are named following below rules:
- All commands are named with prefix
Fzfx
. - The main command name has no suffix.
- The unrestricted variant is named with
U
suffix. - The visual select variant is named with
V
suffix. - The cursor word variant is named with
W
suffix. - The yank text variant is named with
P
suffix (just like press thep
key). - The current buffer only variant is named with
B
suffix.
Especially for git commands:
- The remote git branch variant is named with
R
suffix. - The git files in current directory variant is named with
C
suffix.
Note: command names can be configured, see Configuration.
- Preview keys
alt-p
: toggle preview.ctrl-f
: preview half page down.ctrl-b
: preview half page up.
- Multi keys
ctrl-e
: toggle select.ctrl-a
: toggle select all.
Note: builtin keys can be configured, see Configuration.
Group | Command | Mode | Multi Key? | Preview Key? | Special Feature |
---|---|---|---|---|---|
Files | FzfxFiles(U) | N | Yes | Yes | |
FzfxFiles(U)V | V | ||||
FzfxFiles(U)W | N | ||||
FzfxFiles(U)P | N | ||||
Live Grep | FzfxLiveGrep(U) | N | Yes | Yes | 1. Use `--` to pass raw options to search command (grep, rg) |
FzfxLiveGrep(U)V | V | ||||
FzfxLiveGrep(U)W | N | ||||
FzfxLiveGrep(U)P | N | ||||
Buffers | FzfxBuffers | N | Yes | Yes | |
FzfxBuffersV | V | ||||
FzfxBuffersW | N | ||||
FzfxBuffersP | N | ||||
Git Files | FzfxGFiles | N | Yes | Yes | |
FzfxGFilesV | V | ||||
FzfxGFilesW | N | ||||
FzfxGFilesP | N | ||||
Git Branches | FzfxGBranches(R) | N | No | Yes | 1. Use `enter` to checkout branch |
FzfxGBranches(R)V | V | ||||
FzfxGBranches(R)W | N | ||||
FzfxGBranches(R)P | N | ||||
Git Commits | FzfxGCommits(B) | N | No | Yes | 1. Use `enter` to copy commit SHA |
FzfxGCommits(B)V | V | ||||
FzfxGCommits(B)W | N | ||||
FzfxGCommits(B)P | N | ||||
Git Blame | FzfxGBlame | N | No | Yes | 1. Use `enter` to copy commit SHA |
FzfxGBlameV | V | ||||
FzfxGBlameW | N | ||||
FzfxGBlameP | N | ||||
Lsp Diagnostics | FzfxLspDiagnostics(B) | N | Yes | Yes | |
FzfxLspDiagnostics(B)V | V | ||||
FzfxLspDiagnostics(B)W | N | ||||
FzfxLspDiagnostics(B)P | N | ||||
Lsp Definitions | FzfxLspDefinitions | N | Yes | Yes |
Click here to see vimscripts
" ======== files ========
" find files
nnoremap <space>f :\<C-U>FzfxFiles<CR>
" by visual select
xnoremap <space>f :\<C-U>FzfxFilesV<CR>
" by cursor word
nnoremap <space>wf :\<C-U>FzfxFilesW<CR>
" by yank text
nnoremap <space>pf :\<C-U>FzfxFilesP<CR>
" ======== live grep ========
" live grep
nnoremap <space>l :\<C-U>FzfxLiveGrep<CR>
" by visual select
xnoremap <space>l :\<C-U>FzfxLiveGrepV<CR>
" by cursor word
nnoremap <space>wl :\<C-U>FzfxLiveGrepW<CR>
" by yank text
nnoremap <space>pl :\<C-U>FzfxLiveGrepP<CR>
" ======== buffers ========
" buffers
nnoremap <space>bf :\<C-U>FzfxBuffers<CR>
" by visual select
xnoremap <space>bf :\<C-U>FzfxBuffersV<CR>
" by cursor word
nnoremap <space>wbf :\<C-U>FzfxBuffersW<CR>
" by yank text
nnoremap <space>pbf :\<C-U>FzfxBuffersP<CR>
" ======== git files ========
" git files
nnoremap <space>gf :\<C-U>FzfxGFiles<CR>
" by visual select
xnoremap <space>gf :\<C-U>FzfxGFilesV<CR>
" by cursor word
nnoremap <space>wgf :\<C-U>FzfxGFilesW<CR>
" by yank text
nnoremap <space>pgf :\<C-U>FzfxGFilesP<CR>
" ======== git branches ========
" git branches
nnoremap <space>br :\<C-U>FzfxGBranches<CR>
" by visual select
xnoremap <space>br :\<C-U>FzfxGBranchesV<CR>
" by cursor word
nnoremap <space>wbr :\<C-U>FzfxGBranchesW<CR>
" by yank text
nnoremap <space>pbr :\<C-U>FzfxGBranchesP<CR>
" ======== git commits ========
" git commits
nnoremap <space>gc :\<C-U>FzfxGCommits<CR>
" by visual select
xnoremap <space>gc :\<C-U>FzfxGCommitsV<CR>
" by cursor word
nnoremap <space>wgc :\<C-U>FzfxGCommitsW<CR>
" by yank text
nnoremap <space>pgc :\<C-U>FzfxGCommitsP<CR>
" ======== git blame ========
" git blame
nnoremap <space>gb :\<C-U>FzfxGBlame<CR>
" by visual select
xnoremap <space>gb :\<C-U>FzfxGBlameV<CR>
" by cursor word
nnoremap <space>wgb :\<C-U>FzfxGBlameW<CR>
" by yank text
nnoremap <space>pgb :\<C-U>FzfxGBlameP<CR>
" ======== lsp diagnostics ========
" lsp diagnostics
nnoremap <space>dg :\<C-U>FzfxLspDiagnostics<CR>
" by visual select
xnoremap <space>dg :\<C-U>FzfxLspDiagnosticsV<CR>
" by cursor word
nnoremap <space>wdg :\<C-U>FzfxLspDiagnosticsW<CR>
" by yank text
nnoremap <space>pdg :\<C-U>FzfxLspDiagnosticsP<CR>
" ======== lsp definitions ========
" lsp definitions
nnoremap gd :\<C-U>FzfxLspDefinitions<CR>
Click here to see lua scripts
-- ======== files ========
-- find files
vim.keymap.set('n', '<space>f', '<cmd>FzfxFiles<cr>',
{silent=true, noremap=true, desc="Find files"})
-- by visual select
vim.keymap.set('x', '<space>f', '<cmd>FzfxFilesV<CR>',
{silent=true, noremap=true, desc="Find files"})
-- by cursor word
vim.keymap.set('n', '<space>wf', '<cmd>FzfxFilesW<cr>',
{silent=true, noremap=true, desc="Find files by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pf', '<cmd>FzfxFilesP<cr>',
{silent=true, noremap=true, desc="Find files by yank text"})
-- ======== live grep ========
-- live grep
vim.keymap.set('n', '<space>l',
'<cmd>FzfxLiveGrep<cr>',
{silent=true, noremap=true, desc="Live grep"})
-- by visual select
vim.keymap.set('x', '<space>l',
"<cmd>FzfxLiveGrepV<cr>",
{silent=true, noremap=true, desc="Live grep"})
-- by cursor word
vim.keymap.set('n', '<space>wl',
'<cmd>FzfxLiveGrepW<cr>',
{silent=true, noremap=true, desc="Live grep by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pl',
'<cmd>FzfxLiveGrepP<cr>',
{silent=true, noremap=true, desc="Live grep by cursor word"})
-- ======== buffers ========
-- buffers
vim.keymap.set('n', '<space>bf',
'<cmd>FzfxBuffers<cr>',
{silent=true, noremap=true, desc="Find buffers"})
-- by visual select
vim.keymap.set('x', '<space>bf',
"<cmd>FzfxBuffersV<cr>",
{silent=true, noremap=true, desc="Find buffers"})
-- by cursor word
vim.keymap.set('n', '<space>wbf',
'<cmd>FzfxBuffersW<cr>',
{silent=true, noremap=true, desc="Find buffers by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pbf',
'<cmd>FzfxBuffersP<cr>',
{silent=true, noremap=true, desc="Find buffers by yank text"})
-- ======== git files ========
-- git files
vim.keymap.set('n', '<space>gf',
'<cmd>FzfxGFiles<cr>',
{silent=true, noremap=true, desc="Find git files"})
-- by visual select
vim.keymap.set('x', '<space>gf',
"<cmd>FzfxGFilesV<cr>",
{silent=true, noremap=true, desc="Find git files"})
-- by cursor word
vim.keymap.set('n', '<space>wgf',
'<cmd>FzfxGFilesW<cr>',
{silent=true, noremap=true, desc="Find git files by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pgf',
'<cmd>FzfxGFilesP<cr>',
{silent=true, noremap=true, desc="Find git files by yank text"})
-- ======== git branches ========
-- git branches
vim.keymap.set('n', '<space>br', '<cmd>FzfxGBranches<cr>',
{silent=true, noremap=true, desc="Search git branches"})
-- by visual select
vim.keymap.set('x', '<space>br', '<cmd>FzfxGBranchesV<CR>',
{silent=true, noremap=true, desc="Search git branches"})
-- by cursor word
vim.keymap.set('n', '<space>wbr', '<cmd>FzfxGBranchesW<cr>',
{silent=true, noremap=true, desc="Search git branches by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pbr', '<cmd>FzfxGBranchesP<cr>',
{silent=true, noremap=true, desc="Search git branches by yank text"})
-- ======== git commits ========
-- git commits
vim.keymap.set('n', '<space>gc', '<cmd>FzfxGCommits<cr>',
{silent=true, noremap=true, desc="Search git commits"})
-- by visual select
vim.keymap.set('x', '<space>gc', '<cmd>FzfxGCommitsV<CR>',
{silent=true, noremap=true, desc="Search git commits"})
-- by cursor word
vim.keymap.set('n', '<space>wgc', '<cmd>FzfxGCommitsW<cr>',
{silent=true, noremap=true, desc="Search git commits by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pgc', '<cmd>FzfxGCommitsP<cr>',
{silent=true, noremap=true, desc="Search git commits by yank text"})
-- ======== git blame ========
-- git blame
vim.keymap.set('n', '<space>gb',
'<cmd>FzfxGBlame<cr>',
{silent=true, noremap=true, desc="Search git blame"})
-- by visual select
vim.keymap.set('x', '<space>gb',
"<cmd>FzfxGBlameV<cr>",
{silent=true, noremap=true, desc="Search git blame"})
-- by cursor word
vim.keymap.set('n', '<space>wgb',
'<cmd>FzfxGBlameW<cr>',
{silent=true, noremap=true, desc="Search git blame by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pgb',
'<cmd>FzfxGBlameP<cr>',
{silent=true, noremap=true, desc="Search git blame by yank text"})
-- ======== lsp diagnostics ========
-- lsp diagnostics
vim.keymap.set('n', '<space>dg', '<cmd>FzfxLspDiagnostics<cr>',
{silent=true, noremap=true, desc="Search lsp diagnostics"})
-- by visual select
vim.keymap.set('x', '<space>dg', '<cmd>FzfxLspDiagnosticsV<CR>',
{silent=true, noremap=true, desc="Search lsp diagnostics"})
-- by cursor word
vim.keymap.set('n', '<space>wdg', '<cmd>FzfxLspDiagnosticsW<cr>',
{silent=true, noremap=true, desc="Search lsp diagnostics by cursor word"})
-- by yank text
vim.keymap.set('n', '<space>pdg', '<cmd>FzfxLspDiagnosticsP<cr>',
{silent=true, noremap=true, desc="Search lsp diagnostics by yank text"})
-- ======== lsp definitions ========
-- lsp definitions
vim.keymap.set('n', 'gd', '<cmd>FzfxLspDefinitions<cr>',
{silent=true, noremap=true, desc="Search lsp definitions"})
For complete options and default configurations, please check config.lua.
If you have encounter some breaks on configuration, please see Break Changes.
To create your own commands, please see A General Schema for Creating FZF Command and schema.lua.
- 2023-08-17
- Re-bind keys 'ctrl-e'(select), 'ctrl-a'(select-all) to 'toggle', 'toggle-all'.
- Remove default bind keys 'ctrl-d'(deselect), 'alt-a'(deselect-all).
- Re-bind key 'ctrl-x' (delete buffer on
FzfxBuffers
) to 'ctrl-d'. - Re-bind key 'ctrl-l' (toggle-preview) to 'alt-p'.
- 2023-08-19
- Refactor configs schema for better structure.
- 2023-08-28
- Deprecate 'git_commits' (
FzfxGCommits
) configs, notify user migrate to new schema.
- Deprecate 'git_commits' (
- 2023-08-30
- Deprecate 'buffers' (
FzfxBuffers
) configs, notify user migrate to new schema.
- Deprecate 'buffers' (
- 2023-09-11
- Deprecate 'git_branches' (
FzfxGBranches
) configs, notify user migrate to new schema.
- Deprecate 'git_branches' (
- 2023-09-12
- Deprecate 'git_files' (
FzfxGFiles
) configs, notify user migrate to new schema.
- Deprecate 'git_files' (
To develop the project and make PR, please setup with:
To run unit tests, please install below dependencies:
Then test with vusted --shuffle ./test
.
Please open issue/PR for anything about fzfx.nvim.
Like fzfx.nvim? Consider