1 Commits

Author SHA1 Message Date
Junegunn Choi
db71151970 Add g:fzf_grep_preview_window for enabling Ag/grep preview
Close #225
2016-11-14 02:44:14 +09:00
16 changed files with 639 additions and 2158 deletions

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
*.sh text eol=lf

1
.github/FUNDING.yml vendored
View File

@@ -1 +0,0 @@
github: junegunn

29
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,29 @@
<!-- Check all that apply [x] -->
- Category
- [ ] Question
- [ ] Bug
- [ ] Suggestion
- OS
- [ ] Linux
- [ ] Mac OS X
- [ ] Windows
- [ ] Etc.
- Vim
- [ ] Vim
- [ ] Neovim
<!--
Before submitting
=================
- Make sure that you have the latest version of fzf and fzf.vim
- Check if your problem is reproducible with a minimal configuration
Start Vim with a minimal configuration
======================================
vim -Nu <(curl https://gist.githubusercontent.com/junegunn/6936bf79fedd3a079aeb1dd2f3c81ef5/raw/vimrc)
-->

View File

@@ -1,49 +0,0 @@
---
name: Issue Template
description: Report a problem or bug related to fzf.vim to help us improve
body:
- type: markdown
attributes:
value: |
Check the version of fzf used by running
```vim
:echo system(fzf#exec() .. ' --version')
```
If you don't have the latest version, run the following code to download it
```vim
:call fzf#install()
```
- type: checkboxes
attributes:
label: Checklist
options:
- label: I have fzf 0.54.0 or later
required: true
- label: I have searched through the existing issues
required: true
- type: input
attributes:
label: Output of `:echo system(fzf#exec() .. ' --version')`
validations:
required: true
- type: checkboxes
attributes:
label: OS
options:
- label: Linux
- label: macOS
- label: Windows
- label: Etc.
- type: textarea
attributes:
label: Problem / Steps to reproduce
validations:
required: true

21
LICENSE
View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 Junegunn Choi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

465
README.md
View File

@@ -1,17 +1,3 @@
<div align="center" markdown="1">
<sup>Special thanks to:</sup>
<br>
<a href="https://tuple.app/fzf.vim">
<img alt="Tuple's sponsorship image" src="https://raw.githubusercontent.com/junegunn/i/master/tuple.png" width="400">
</a>
### [Tuple, the premier screen sharing app for developers](https://tuple.app/fzf.vim)
[Available for MacOS & Windows](https://tuple.app/fzf.vim)<br>
</div>
---
fzf :heart: vim fzf :heart: vim
=============== ===============
@@ -20,12 +6,16 @@ Things you can do with [fzf][fzf] and Vim.
Rationale Rationale
--------- ---------
[fzf][fzf] itself is not a Vim plugin, and the official repository only [fzf][fzf] in itself is not a Vim plugin, and the official repository only
provides the [basic wrapper function][run] for Vim. It's up to the users to provides the [basic wrapper function][run] for Vim and it's up to the users to
write their own Vim commands with it. However, I've learned that many users of write their own Vim commands with it. However, I've learned that many users of
fzf are not familiar with Vimscript and are looking for the "default" fzf are not familiar with Vimscript and are looking for the "default"
implementation of the features they can find in the alternative Vim plugins. implementation of the features they can find in the alternative Vim plugins.
This repository is a bundle of fzf-based commands and mappings extracted from
my [.vimrc][vimrc] to address such needs. They are *not* designed to be
flexible or configurable, and there's no guarantee of backward-compatibility.
Why you should use fzf on Vim Why you should use fzf on Vim
----------------------------- -----------------------------
@@ -37,82 +27,60 @@ is small, which is the case for many of the commands provided here.
Nevertheless I wrote them anyway since it's really easy to implement custom Nevertheless I wrote them anyway since it's really easy to implement custom
selector with fzf. selector with fzf.
fzf is an independent command-line program and thus requires an external
terminal emulator when on GVim. You may or may not like the experience. Also
note that fzf currently does not compile on Windows.
Installation Installation
------------ ------------
fzf.vim depends on the basic Vim plugin of [the main fzf Using [vim-plug](https://github.com/junegunn/vim-plug):
repository][fzf-main], which means you need to **set up both "fzf" and
"fzf.vim" on Vim**. To learn more about fzf/Vim integration, see
[README-VIM][README-VIM].
[fzf-main]: https://github.com/junegunn/fzf
[README-VIM]: https://github.com/junegunn/fzf/blob/master/README-VIM.md
### Using [vim-plug](https://github.com/junegunn/vim-plug)
```vim ```vim
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim' Plug 'junegunn/fzf.vim'
``` ```
`fzf#install()` makes sure that you have the latest binary, but it's optional, - `dir` and `do` options are not mandatory
so you can omit it if you use a plugin manager that doesn't support hooks. - Use `./install --bin` instead if you don't need fzf outside of Vim
- If you installed fzf using Homebrew, the following should suffice:
### Dependencies - `Plug '/usr/local/opt/fzf' | Plug 'junegunn/fzf.vim'`
- Make sure to use Vim 7.4 or above
- [fzf][fzf-main] 0.54.0 or above
- For syntax-highlighted preview, install [bat](https://github.com/sharkdp/bat)
- If [delta](https://github.com/dandavison/delta) is available, `GF?`,
`Commits` and `BCommits` will use it to format `git diff` output.
- `Ag` requires [The Silver Searcher (ag)][ag]
- `Rg` requires [ripgrep (rg)][rg]
- `Tags` and `Helptags` require Perl
- `Tags PREFIX` requires `readtags` command from [Universal Ctags](https://ctags.io/)
```sh
# Installing dependencies using Homebrew
brew install fzf bat ripgrep the_silver_searcher perl universal-ctags
```
Commands Commands
-------- --------
| Command | List | | Command | List |
| --- | --- | | --- | --- |
| `:Files [PATH]` | Files (runs `$FZF_DEFAULT_COMMAND` if defined) | | `Files [PATH]` | Files (similar to `:FZF`) |
| `:GFiles [OPTS]` | Git files (`git ls-files`) | | `GFiles [OPTS]` | Git files (`git ls-files`) |
| `:GFiles?` | Git files (`git status`) | | `GFiles?` | Git files (`git status`) |
| `:Buffers` | Open buffers | | `Buffers` | Open buffers |
| `:Colors` | Color schemes | | `Colors` | Color schemes |
| `:Ag [PATTERN]` | [ag][ag] search result (`ALT-A` to select all, `ALT-D` to deselect all) | | `Ag [PATTERN]` | [ag][ag] search result (`ALT-A` to select all, `ALT-D` to deselect all) |
| `:Rg [PATTERN]` | [rg][rg] search result (`ALT-A` to select all, `ALT-D` to deselect all) | | `Lines [QUERY]` | Lines in loaded buffers |
| `:RG [PATTERN]` | [rg][rg] search result; relaunch ripgrep on every keystroke | | `BLines [QUERY]` | Lines in the current buffer |
| `:Lines [QUERY]` | Lines in loaded buffers | | `Tags [QUERY]` | Tags in the project (`ctags -R`) |
| `:BLines [QUERY]` | Lines in the current buffer | | `BTags [QUERY]` | Tags in the current buffer |
| `:Tags [PREFIX]` | Tags in the project (`ctags -R`) | | `Marks` | Marks |
| `:BTags [QUERY]` | Tags in the current buffer | | `Windows` | Windows |
| `:Changes` | Changelist across all open buffers | | `Locate PATTERN` | `locate` command output |
| `:Marks` | Marks | | `History` | `v:oldfiles` and open buffers |
| `:BMarks` | Marks in the current buffer | | `History:` | Command history |
| `:Jumps` | Jumps | | `History/` | Search history |
| `:Windows` | Windows | | `Snippets` | Snippets ([UltiSnips][us]) |
| `:Locate PATTERN` | `locate` command output | | `Commits` | Git commits (requires [fugitive.vim][f]) |
| `:History` | `v:oldfiles` and open buffers | | `BCommits` | Git commits for the current buffer |
| `:History:` | Command history | | `Commands` | Commands |
| `:History/` | Search history | | `Maps` | Normal mode mappings |
| `:Snippets` | Snippets ([UltiSnips][us]) | | `Helptags` | Help tags <sup id="a1">[1](#helptags)</sup> |
| `:Commits [LOG_OPTS]` | Git commits (requires [fugitive.vim][f]) | | `Filetypes` | File types
| `:BCommits [LOG_OPTS]` | Git commits for the current buffer; visual-select lines to track changes in the range |
| `:Commands` | Commands |
| `:Maps` | Normal mode mappings |
| `:Helptags` | Help tags <sup id="a1">[1](#helptags)</sup> |
| `:Filetypes` | File types
- Most commands support `CTRL-T` / `CTRL-X` / `CTRL-V` key - Most commands support `CTRL-T` / `CTRL-X` / `CTRL-V` key
bindings to open in a new tab, a new split, or in a new vertical split bindings to open in a new tab, a new split, or in a new vertical split
- Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen - Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen
- You can set `g:fzf_vim.command_prefix` to give the same prefix to the commands - You can set `g:fzf_command_prefix` to give the same prefix to the commands
- e.g. `let g:fzf_vim.command_prefix = 'Fzf'` and you have `FzfFiles`, etc. - e.g. `let g:fzf_command_prefix = 'Fzf'` and you have `FzfFiles`, etc.
(<a name="helptags">1</a>: `Helptags` will shadow the command of the same name (<a name="helptags">1</a>: `Helptags` will shadow the command of the same name
from [pathogen][pat]. But its functionality is still available via `call from [pathogen][pat]. But its functionality is still available via `call
@@ -121,237 +89,86 @@ pathogen#helptags()`. [↩](#a1))
[pat]: https://github.com/tpope/vim-pathogen [pat]: https://github.com/tpope/vim-pathogen
[f]: https://github.com/tpope/vim-fugitive [f]: https://github.com/tpope/vim-fugitive
Customization ### Customization
-------------
### Configuration options of the base plugin #### Global options
Every command in fzf.vim internally calls `fzf#wrap` function of the main
repository which supports a set of global option variables. So please read
through [README-VIM][README-VIM] to learn more about them.
### Configuration options for fzf.vim
All configuration values for this plugin are stored in `g:fzf_vim` dictionary,
so **make sure to initialize it before assigning any configuration values to
it**.
```vim ```vim
" Initialize configuration dictionary " This is the default extra key bindings
let g:fzf_vim = {} let g:fzf_action = {
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'split',
\ 'ctrl-v': 'vsplit' }
" Default fzf layout
" - down / up / left / right
let g:fzf_layout = { 'down': '~40%' }
" In Neovim, you can set up fzf window using a Vim command
let g:fzf_layout = { 'window': 'enew' }
let g:fzf_layout = { 'window': '-tabnew' }
" Customize fzf colors to match your color scheme
let g:fzf_colors =
\ { 'fg': ['fg', 'Normal'],
\ 'bg': ['bg', 'Normal'],
\ 'hl': ['fg', 'Comment'],
\ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
\ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
\ 'hl+': ['fg', 'Statement'],
\ 'info': ['fg', 'PreProc'],
\ 'prompt': ['fg', 'Conditional'],
\ 'pointer': ['fg', 'Exception'],
\ 'marker': ['fg', 'Keyword'],
\ 'spinner': ['fg', 'Label'],
\ 'header': ['fg', 'Comment'] }
" Enable per-command history.
" CTRL-N and CTRL-P will be automatically bound to next-history and
" previous-history instead of down and up. If you don't like the change,
" explicitly bind the keys to down and up in your $FZF_DEFAULT_OPTS.
let g:fzf_history_dir = '~/.local/share/fzf-history'
``` ```
#### Preview window #### Command-local options
Some commands will show the preview window on the right. You can customize the
behavior with `g:fzf_vim.preview_window`. Here are some examples:
```vim ```vim
" This is the default option: " [Files] Extra options for fzf
" - Preview window on the right with 50% width " e.g. File preview using Highlight
" - CTRL-/ will toggle preview window. " (http://www.andre-simon.de/doku/highlight/en/highlight.html)
" - Note that this array is passed as arguments to fzf#vim#with_preview function. let g:fzf_files_options =
" - To learn more about preview window options, see `--preview-window` section of `man fzf`. \ '--preview "(highlight -O ansi {} || cat {}) 2> /dev/null | head -'.&lines.'"'
let g:fzf_vim.preview_window = ['right,50%', 'ctrl-/']
" Preview window is hidden by default. You can toggle it with ctrl-/. " [Buffers] Jump to the existing window if possible
" It will show on the right with 50% width, but if the width is smaller let g:fzf_buffers_jump = 1
" than 70 columns, it will show above the candidate list
let g:fzf_vim.preview_window = ['hidden,right,50%,<70(up,40%)', 'ctrl-/']
" Empty value to disable preview window altogether
let g:fzf_vim.preview_window = []
" fzf.vim needs bash to display the preview window.
" On Windows, fzf.vim will first see if bash is in $PATH, then if
" Git bash (C:\Program Files\Git\bin\bash.exe) is available.
" If you want it to use a different bash, set this variable.
" let g:fzf_vim = {}
" let g:fzf_vim.preview_bash = 'C:\Git\bin\bash.exe'
```
#### Command-level options
```vim
" [Buffers] Jump to the existing window if possible (default: 0)
let g:fzf_vim.buffers_jump = 1
" [Ag|Rg|RG] Display path on a separate line for narrow screens (default: 0)
" * Requires Perl and fzf 0.56.0 or later
let g:fzf_vim.grep_multi_line = 0
" PATH:LINE:COL:LINE
let g:fzf_vim.grep_multi_line = 1
" PATH:LINE:COL:
" LINE
let g:fzf_vim.grep_multi_line = 2
" PATH:LINE:COL:
" LINE
" (empty line between items using --gap option)
" [[B]Commits] Customize the options used by 'git log': " [[B]Commits] Customize the options used by 'git log':
let g:fzf_vim.commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"' let g:fzf_commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'
" [Tags] Command to generate tags file " [Tags] Command to generate tags file
let g:fzf_vim.tags_command = 'ctags -R' let g:fzf_tags_command = 'ctags -R'
" [Commands] --expect expression for directly executing the command " [Commands] --expect expression for directly executing the command
let g:fzf_vim.commands_expect = 'alt-enter,ctrl-x' let g:fzf_commands_expect = 'alt-enter,ctrl-x'
" [Ag / fzf#vim#grep] Command to preview the content
" - Requires Ruby
" - Install Highlight or CodeRay for syntax highlighting
let g:fzf_grep_preview_window = 'right:50%'
``` ```
#### Command-level fzf options #### Advanced customization using autoload functions
You can set fzf options for each command by setting You can use autoload functions to define your own commands.
`g:fzf_vim.{command}_options`.
```vim
" In string
let g:fzf_vim.buffers_options = '--style full --border-label " Open Buffers "'
" In list (No need to quote or escape values)
let g:fzf_vim.buffers_options = ['--style', 'full', '--border-label', ' Open Buffers ']
```
#### List type to handle multiple selections
The following commands will fill the quickfix list when multiple entries are
selected.
* `Ag`
* `Rg` / `RG`
* `Lines` / `BLines`
* `Tags` / `BTags`
By setting `g:fzf_vim.listproc`, you can make them use location list instead.
```vim
" Default: Use quickfix list
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#quickfix(list) }
" Use location list instead of quickfix list
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#location(list) }
```
You can customize the list type per command by defining variables named
`g:fzf_vim.listproc_{command_name_in_lowercase}`.
```vim
" Command-wise customization
let g:fzf_vim.listproc_ag = { list -> fzf#vim#listproc#quickfix(list) }
let g:fzf_vim.listproc_rg = { list -> fzf#vim#listproc#location(list) }
```
You can further customize the behavior by providing a custom function to
process the list instead of using the predefined `fzf#vim#listproc#quickfix`
or `fzf#vim#listproc#location`.
```vim
" A customized version of fzf#vim#listproc#quickfix.
" The last two lines are commented out not to move to the first entry.
function! g:fzf_vim.listproc(list)
call setqflist(a:list)
copen
wincmd p
" cfirst
" normal! zvzz
endfunction
```
### Advanced customization
#### Vim functions
Each command in fzf.vim is backed by a Vim function. You can override
a command or define a variation of it by calling its corresponding function.
| Command | Vim function |
| --- | --- |
| `Files` | `fzf#vim#files(dir, [spec dict], [fullscreen bool])` |
| `GFiles` | `fzf#vim#gitfiles(git_options, [spec dict], [fullscreen bool])` |
| `GFiles?` | `fzf#vim#gitfiles('?', [spec dict], [fullscreen bool])` |
| `Buffers` | `fzf#vim#buffers([query string], [bufnrs list], [spec dict], [fullscreen bool])` |
| `Colors` | `fzf#vim#colors([spec dict], [fullscreen bool])` |
| `Rg` | `fzf#vim#grep(command, [spec dict], [fullscreen bool])` |
| `RG` | `fzf#vim#grep2(command_prefix, query, [spec dict], [fullscreen bool])` |
| ... | ... |
(We can see that the last two optional arguments of each function are
identical. They are directly passed to `fzf#wrap` function. If you haven't
read [README-VIM][README-VIM] already, please read it before proceeding.)
#### Example: Customizing `Files` command
This is the default definition of `Files` command:
```vim
command! -bang -nargs=? -complete=dir Files call fzf#vim#files(<q-args>, <bang>0)
```
Let's say you want to a variation of it called `ProjectFiles` that only
searches inside `~/projects` directory. Then you can do it like this:
```vim
command! -bang ProjectFiles call fzf#vim#files('~/projects', <bang>0)
```
Or, if you want to override the command with different fzf options, just pass
a custom spec to the function.
```vim
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline']}, <bang>0)
```
Want a preview window?
```vim
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', 'cat {}']}, <bang>0)
```
It kind of works, but you probably want a nicer previewer program than `cat`.
fzf.vim ships [a versatile preview script](bin/preview.sh) you can readily
use. It internally executes [bat](https://github.com/sharkdp/bat) for syntax
highlighting, so make sure to install it.
```vim
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', '~/.vim/plugged/fzf.vim/bin/preview.sh {}']}, <bang>0)
```
However, it's not ideal to hard-code the path to the script which can be
different in different circumstances. So in order to make it easier to set up
the previewer, fzf.vim provides `fzf#vim#with_preview` helper function.
Similarly to `fzf#wrap`, it takes a spec dictionary and returns a copy of it
with additional preview options.
```vim
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview({'options': ['--layout=reverse', '--info=inline']}), <bang>0)
```
You can just omit the spec argument if you only want the previewer.
```vim
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
```
#### Example: `git grep` wrapper
The following example implements `GGrep` command that works similarly to
predefined `Ag` or `Rg` using `fzf#vim#grep`.
- We set the base directory to git root by setting `dir` attribute in spec
dictionary.
- [The preview script](bin/preview.sh) supports `grep` format
(`FILE_PATH:LINE_NO:...`), so we can just wrap the spec with
`fzf#vim#with_preview` as before to enable previewer.
```vim ```vim
" git grep
command! -bang -nargs=* GGrep command! -bang -nargs=* GGrep
\ call fzf#vim#grep( \ call fzf#vim#grep('git grep --line-number '.shellescape(<q-args>), 0, <bang>0)
\ 'git grep --line-number -- '.fzf#shellescape(<q-args>),
\ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0) " We use VimEnter event so that the code is run after fzf.vim is loaded
autocmd VimEnter * command! Colors
\ call fzf#vim#colors({'left': '15%', 'options': '--reverse --margin 30%,0'})
``` ```
Mappings Mappings
@@ -366,9 +183,12 @@ Mappings
| `<plug>(fzf-complete-word)` | `cat /usr/share/dict/words` | | `<plug>(fzf-complete-word)` | `cat /usr/share/dict/words` |
| `<plug>(fzf-complete-path)` | Path completion using `find` (file + dir) | | `<plug>(fzf-complete-path)` | Path completion using `find` (file + dir) |
| `<plug>(fzf-complete-file)` | File completion using `find` | | `<plug>(fzf-complete-file)` | File completion using `find` |
| `<plug>(fzf-complete-file-ag)` | File completion using `ag` |
| `<plug>(fzf-complete-line)` | Line completion (all open buffers) | | `<plug>(fzf-complete-line)` | Line completion (all open buffers) |
| `<plug>(fzf-complete-buffer-line)` | Line completion (current buffer only) | | `<plug>(fzf-complete-buffer-line)` | Line completion (current buffer only) |
### Usage
```vim ```vim
" Mapping selecting mappings " Mapping selecting mappings
nmap <leader><tab> <plug>(fzf-maps-n) nmap <leader><tab> <plug>(fzf-maps-n)
@@ -378,38 +198,22 @@ omap <leader><tab> <plug>(fzf-maps-o)
" Insert mode completion " Insert mode completion
imap <c-x><c-k> <plug>(fzf-complete-word) imap <c-x><c-k> <plug>(fzf-complete-word)
imap <c-x><c-f> <plug>(fzf-complete-path) imap <c-x><c-f> <plug>(fzf-complete-path)
imap <c-x><c-j> <plug>(fzf-complete-file-ag)
imap <c-x><c-l> <plug>(fzf-complete-line) imap <c-x><c-l> <plug>(fzf-complete-line)
" Advanced customization using autoload functions
inoremap <expr> <c-x><c-k> fzf#vim#complete#word({'left': '15%'})
``` ```
Completion functions ### Completion helper
--------------------
| Function | Description | `fzf#complete` is a helper function for creating custom fuzzy completion using
| --- | --- | fzf. If the first parameter is a command string or a Vim list, it will be used
| `fzf#vim#complete#path(command, [spec])` | Path completion | as the source.
| `fzf#vim#complete#word([spec])` | Word completion |
| `fzf#vim#complete#line([spec])` | Line completion (all open buffers) |
| `fzf#vim#complete#buffer_line([spec])` | Line completion (current buffer only) |
```vim
" Path completion with custom source command
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('fd')
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('rg --files')
" Word completion with custom spec with popup layout option
inoremap <expr> <c-x><c-k> fzf#vim#complete#word({'window': { 'width': 0.2, 'height': 0.9, 'xoffset': 1 }})
```
Custom completion
-----------------
`fzf#vim#complete` is a helper function for creating custom fuzzy completion
using fzf. If the first parameter is a command string or a Vim list, it will
be used as the source.
```vim ```vim
" Replace the default dictionary completion with fzf-based fuzzy completion " Replace the default dictionary completion with fzf-based fuzzy completion
inoremap <expr> <c-x><c-k> fzf#vim#complete('cat /usr/share/dict/words') inoremap <expr> <c-x><c-k> fzf#complete('cat /usr/share/dict/words')
``` ```
For advanced uses, you can pass an options dictionary to the function. The set For advanced uses, you can pass an options dictionary to the function. The set
@@ -423,47 +227,24 @@ following exceptions:
- Or a function to extract completion prefix - Or a function to extract completion prefix
- Both `source` and `options` can be given as funcrefs that take the - Both `source` and `options` can be given as funcrefs that take the
completion prefix as the argument and return the final value completion prefix as the argument and return the final value
- `sink` or `sink*` are ignored - `sink` or `sink*` are not allowed
```vim #### Reducer example
" Global line completion (not just open buffers. ripgrep required.)
inoremap <expr> <c-x><c-l> fzf#vim#complete(fzf#wrap({
\ 'prefix': '^.*$',
\ 'source': 'rg -n ^ --color always',
\ 'options': '--ansi --delimiter : --nth 3..',
\ 'reducer': { lines -> join(split(lines[0], ':\zs')[2:], '') }}))
```
### Reducer example
```vim ```vim
function! s:make_sentence(lines) function! s:make_sentence(lines)
return substitute(join(a:lines), '^.', '\=toupper(submatch(0))', '').'.' return substitute(join(a:lines), '^.', '\=toupper(submatch(0))', '').'.'
endfunction endfunction
inoremap <expr> <c-x><c-s> fzf#vim#complete({ inoremap <expr> <c-x><c-s> fzf#complete({
\ 'source': 'cat /usr/share/dict/words', \ 'source': 'cat /usr/share/dict/words',
\ 'reducer': function('<sid>make_sentence'), \ 'reducer': function('<sid>make_sentence'),
\ 'options': '--multi --reverse --margin 15%,0', \ 'options': '--multi --reverse --margin 15%,0',
\ 'left': 20}) \ 'left': 20})
``` ```
Status line of terminal buffer Status line (neovim)
------------------------------ --------------------
When fzf starts in a terminal buffer (see [fzf/README-VIM.md][termbuf]), you
may want to customize the statusline of the containing buffer.
[termbuf]: https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzf-inside-terminal-buffer
### Hide statusline
```vim
autocmd! FileType fzf set laststatus=0 noshowmode noruler
\| autocmd BufLeave <buffer> set laststatus=2 showmode ruler
```
### Custom statusline
```vim ```vim
function! s:fzf_statusline() function! s:fzf_statusline()
@@ -483,7 +264,7 @@ License
MIT MIT
[fzf]: https://github.com/junegunn/fzf [fzf]: https://github.com/junegunn/fzf
[run]: https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzfrun [run]: https://github.com/junegunn/fzf#usage-as-vim-plugin
[vimrc]: https://github.com/junegunn/dotfiles/blob/master/vimrc
[ag]: https://github.com/ggreer/the_silver_searcher [ag]: https://github.com/ggreer/the_silver_searcher
[rg]: https://github.com/BurntSushi/ripgrep
[us]: https://github.com/SirVer/ultisnips [us]: https://github.com/SirVer/ultisnips

1200
autoload/fzf/vim.vim Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,6 @@
let s:cpo_save = &cpo let s:cpo_save = &cpo
set cpo&vim set cpo&vim
let s:is_win = has('win32') || has('win64')
function! s:extend(base, extra) function! s:extend(base, extra)
let base = copy(a:base) let base = copy(a:base)
@@ -47,10 +46,9 @@ else
endif endif
function! fzf#vim#complete#word(...) function! fzf#vim#complete#word(...)
let sources = empty(&dictionary) ? ['/usr/share/dict/words'] : split(&dictionary, ',')
return fzf#vim#complete(s:extend({ return fzf#vim#complete(s:extend({
\ 'source': 'cat ' . join(map(sources, 'fzf#shellescape(v:val)'))}, \ 'source': 'cat /usr/share/dict/words'},
\ get(a:000, 0, fzf#wrap()))) \ get(a:000, 0, g:fzf#vim#default_layout)))
endfunction endfunction
" ---------------------------------------------------------------------------- " ----------------------------------------------------------------------------
@@ -60,26 +58,25 @@ endfunction
" ---------------------------------------------------------------------------- " ----------------------------------------------------------------------------
function! s:file_split_prefix(prefix) function! s:file_split_prefix(prefix)
let expanded = expand(a:prefix) let expanded = expand(a:prefix)
let slash = (s:is_win && !&shellslash) ? '\\' : '/'
return isdirectory(expanded) ? return isdirectory(expanded) ?
\ [expanded, \ [expanded,
\ substitute(a:prefix, '[/\\]*$', slash, ''), \ substitute(a:prefix, '/*$', '/', ''),
\ ''] : \ ''] :
\ [fnamemodify(expanded, ':h'), \ [fnamemodify(expanded, ':h'),
\ substitute(fnamemodify(a:prefix, ':h'), '[/\\]*$', slash, ''), \ substitute(fnamemodify(a:prefix, ':h'), '/*$', '/', ''),
\ fnamemodify(expanded, ':t')] \ fnamemodify(expanded, ':t')]
endfunction endfunction
function! s:file_source(prefix) function! s:file_source(prefix)
let [dir, head, tail] = s:file_split_prefix(a:prefix) let [dir, head, tail] = s:file_split_prefix(a:prefix)
return printf( return printf(
\ "cd %s && ".s:file_cmd." | sed %s", \ "cd %s && ".s:file_cmd." | sed 's:^:%s:'",
\ fzf#shellescape(dir), fzf#shellescape('s:^:'.(empty(a:prefix) || a:prefix == tail ? '' : head).':')) \ shellescape(dir), empty(a:prefix) || a:prefix == tail ? '' : head)
endfunction endfunction
function! s:file_options(prefix) function! s:file_options(prefix)
let [_, head, tail] = s:file_split_prefix(a:prefix) let [_, head, tail] = s:file_split_prefix(a:prefix)
return ['--prompt', head, '--query', tail] return printf('--prompt %s --query %s', shellescape(head), shellescape(tail))
endfunction endfunction
function! s:fname_prefix(str) function! s:fname_prefix(str)
@@ -131,7 +128,7 @@ function! fzf#vim#complete#path(command, ...)
return fzf#vim#complete(s:extend({ return fzf#vim#complete(s:extend({
\ 'prefix': s:function('s:fname_prefix'), \ 'prefix': s:function('s:fname_prefix'),
\ 'source': s:function('s:file_source'), \ 'source': s:function('s:file_source'),
\ 'options': s:function('s:file_options')}, get(a:000, 0, fzf#wrap()))) \ 'options': s:function('s:file_options')}, get(a:000, 0, g:fzf#vim#default_layout)))
endfunction endfunction
" ---------------------------------------------------------------------------- " ----------------------------------------------------------------------------
@@ -150,13 +147,13 @@ function! fzf#vim#complete#line(...)
\ 'prefix': '^.*$', \ 'prefix': '^.*$',
\ 'source': lines, \ 'source': lines,
\ 'options': '--tiebreak=index --ansi --nth '.nth.'.. --tabstop=1', \ 'options': '--tiebreak=index --ansi --nth '.nth.'.. --tabstop=1',
\ 'reducer': s:function('s:reduce_line')}, get(a:000, 0, fzf#wrap()))) \ 'reducer': s:function('s:reduce_line')}, get(a:000, 0, g:fzf#vim#default_layout)))
endfunction endfunction
function! fzf#vim#complete#buffer_line(...) function! fzf#vim#complete#buffer_line(...)
return fzf#vim#complete(s:extend({ call fzf#vim#complete(s:extend({
\ 'prefix': '^.*$', \ 'prefix': '^.*$',
\ 'source': fzf#vim#_uniq(getline(1, '$'))}, get(a:000, 0, fzf#wrap()))) \ 'source': s:uniq(getline(1, '$'))}, get(a:000, 0, g:fzf#vim#default_layout)))
endfunction endfunction
let &cpo = s:cpo_save let &cpo = s:cpo_save

View File

@@ -1,95 +0,0 @@
" Copyright (c) 2024 Junegunn Choi
"
" MIT License
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the
" "Software"), to deal in the Software without restriction, including
" without limitation the rights to use, copy, modify, merge, publish,
" distribute, sublicense, and/or sell copies of the Software, and to
" permit persons to whom the Software is furnished to do so, subject to
" the following conditions:
"
" The above copyright notice and this permission notice shall be
" included in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
function! s:warn(message)
echohl WarningMsg
echom a:message
echohl None
return 0
endfunction
function! fzf#vim#ipc#start(Callback)
if !exists('*job_start') && !exists('*jobstart')
call s:warn('job_start/jobstart function not supported')
return ''
endif
if !executable('mkfifo')
call s:warn('mkfifo is not available')
return ''
endif
call fzf#vim#ipc#stop()
let g:fzf_ipc = { 'fifo': tempname(), 'callback': a:Callback }
if !filereadable(g:fzf_ipc.fifo)
call system('mkfifo '..shellescape(g:fzf_ipc.fifo))
if v:shell_error
call s:warn('Failed to create fifo')
endif
endif
call fzf#vim#ipc#restart()
return g:fzf_ipc.fifo
endfunction
function! fzf#vim#ipc#restart()
if !exists('g:fzf_ipc')
throw 'fzf#vim#ipc not started'
endif
let Callback = g:fzf_ipc.callback
if exists('*job_start')
let g:fzf_ipc.job = job_start(
\ ['cat', g:fzf_ipc.fifo],
\ {'out_cb': { _, msg -> call(Callback, [msg]) },
\ 'exit_cb': { _, status -> status == 0 ? fzf#vim#ipc#restart() : '' }}
\ )
else
let eof = ['']
let g:fzf_ipc.job = jobstart(
\ ['cat', g:fzf_ipc.fifo],
\ {'stdout_buffered': 1,
\ 'on_stdout': { j, msg, e -> msg != eof ? call(Callback, msg) : '' },
\ 'on_exit': { j, status, e -> status == 0 ? fzf#vim#ipc#restart() : '' }}
\ )
endif
endfunction
function! fzf#vim#ipc#stop()
if !exists('g:fzf_ipc')
return
endif
let job = g:fzf_ipc.job
if exists('*job_stop')
call job_stop(job)
else
call jobstop(job)
call jobwait([job])
endif
call delete(g:fzf_ipc.fifo)
unlet g:fzf_ipc
endfunction

View File

@@ -1,38 +0,0 @@
" Copyright (c) 2023 Junegunn Choi
"
" MIT License
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the
" "Software"), to deal in the Software without restriction, including
" without limitation the rights to use, copy, modify, merge, publish,
" distribute, sublicense, and/or sell copies of the Software, and to
" permit persons to whom the Software is furnished to do so, subject to
" the following conditions:
"
" The above copyright notice and this permission notice shall be
" included in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
function! fzf#vim#listproc#quickfix(list)
call setqflist(a:list)
copen
wincmd p
cfirst
normal! zvzz
endfunction
function! fzf#vim#listproc#location(list)
call setloclist(0, a:list)
lopen
wincmd p
lfirst
normal! zvzz
endfunction

View File

@@ -1,3 +1,26 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
#
# usage: ./preview.rb FILENAME LINENO VSPLIT(0|1)
puts 'preview.rb is deprecated. Use preview.sh instead.' require 'shellwords'
COMMAND = %[(highlight -O ansi -l {} || coderay {} || cat {}) 2> /dev/null]
ANSI = /\x1b\[[0-9;]*m/
REVERSE = "\x1b[7m"
RESET = "\x1b[m"
file, center, split = ARGV.fetch(0), ARGV.fetch(1).to_i, ARGV.fetch(2) == '1'
height = File.readable?('/dev/tty') ? `stty size < /dev/tty`.split.first.to_i : 40
height /= 2 if split
height -= 2 # preview border
offset = [1, center - height / 3].max
IO.popen(['sh', '-c', COMMAND.gsub('{}', Shellwords.shellescape(file))]) do |io|
io.each_line.drop(offset - 1).take(height).each_with_index do |line, lno|
if lno + offset == center
puts REVERSE + line.chomp.gsub(ANSI) { |m| m + REVERSE } + RESET
else
puts line
end
end
end

View File

@@ -1,93 +0,0 @@
#!/usr/bin/env bash
REVERSE="\x1b[7m"
RESET="\x1b[m"
if [[ $# -lt 1 ]]; then
echo "usage: $0 [--tag] FILENAME[:LINENO][:IGNORED]"
exit 1
fi
if [[ $1 = --tag ]]; then
shift
"$(dirname "${BASH_SOURCE[0]}")/tagpreview.sh" "$@"
exit $?
fi
# Ignore if an empty path is given
[[ -z $1 ]] && exit
IFS=':' read -r -a INPUT <<< "$1"
FILE=${INPUT[0]}
CENTER=${INPUT[1]}
if [[ "$1" =~ ^[A-Za-z]:\\ ]]; then
FILE=$FILE:${INPUT[1]}
CENTER=${INPUT[2]}
fi
if [[ -n "$CENTER" && ! "$CENTER" =~ ^[0-9] ]]; then
exit 1
fi
CENTER=${CENTER/[^0-9]*/}
# MS Win support
if [[ "$FILE" =~ '\' ]]; then
if [ -z "$MSWINHOME" ]; then
MSWINHOME="$HOMEDRIVE$HOMEPATH"
fi
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null ; then
MSWINHOME="${MSWINHOME//\\/\\\\}"
FILE="${FILE/#\~\\/$MSWINHOME\\}"
FILE=$(wslpath -u "$FILE")
elif [ -n "$MSWINHOME" ]; then
FILE="${FILE/#\~\\/$MSWINHOME\\}"
fi
fi
FILE="${FILE/#\~\//$HOME/}"
if [ ! -r "$FILE" ]; then
if [[ "${INPUT[0]}" != '[No Name]' ]]; then
echo "File not found ${FILE}"
fi
exit 1
fi
if [ -z "$CENTER" ]; then
CENTER=0
fi
# Sometimes bat is installed as batcat.
if [[ -z "$BATCAT" ]]; then
if command -v batcat > /dev/null; then
BATCAT="batcat"
elif command -v bat > /dev/null; then
BATCAT="bat"
fi
fi
if [ -z "$FZF_PREVIEW_COMMAND" ] && [ "${BATCAT:+x}" ] && [[ ! -d "$FILE" ]] ; then
${BATCAT} --style="${BAT_STYLE:-numbers}" --color=always --pager=never \
--highlight-line=$CENTER -- "$FILE"
exit $?
fi
FILE_LENGTH=${#FILE}
MIME=$(file --dereference --mime -- "$FILE")
if [[ "${MIME:FILE_LENGTH}" =~ binary ]] && [[ ! -d "$FILE" ]]; then
echo "$MIME"
exit 0
fi
DEFAULT_COMMAND="highlight -O ansi -l {} || coderay {} || rougify {} || cat {}"
if [[ -d "$FILE" ]]; then
DEFAULT_COMMAND="tree -C -L2 {} || ls -l --color=always {}"
fi
CMD=${FZF_PREVIEW_COMMAND:-$DEFAULT_COMMAND}
CMD=${CMD//{\}/"$(printf %q "$FILE")"}
eval "$CMD" 2> /dev/null | awk "{ \
if (NR == $CENTER) \
{ gsub(/\x1b[[0-9;]*m/, \"&$REVERSE\"); printf(\"$REVERSE%s\n$RESET\", \$0); } \
else printf(\"$RESET%s\n\", \$0); \
}"

View File

@@ -1,73 +0,0 @@
#!/usr/bin/env bash
REVERSE="\x1b[7m"
RESET="\x1b[m"
if [ -z "$1" ]; then
echo "usage: $0 FILENAME:TAGFILE:EXCMD"
exit 1
fi
IFS=':' read -r FILE TAGFILE EXCMD <<< "$*"
# Complete file paths which are relative to the given tag file
if [ "${FILE:0:1}" != "/" ]; then
FILE="$(dirname "${TAGFILE}")/${FILE}"
fi
if [ ! -r "$FILE" ]; then
echo "File not found ${FILE}"
exit 1
fi
# If users aren't using vim, they are probably using neovim
if command -v vim > /dev/null; then
VIMNAME="vim"
elif command -v nvim > /dev/null; then
VIMNAME="nvim"
else
echo "Cannot preview tag: vim or nvim unavailable"
exit 1
fi
CENTER="$("${VIMNAME}" -R -i NONE -u NONE -e -m -s "${FILE}" \
-c "set nomagic" \
-c "silent ${EXCMD}" \
-c 'let l=line(".") | new | put =l | print | qa!')" || exit
START_LINE="$(( CENTER - FZF_PREVIEW_LINES / 2 ))"
if (( START_LINE <= 0 )); then
START_LINE=1
fi
END_LINE="$(( START_LINE + FZF_PREVIEW_LINES - 1 ))"
# Sometimes bat is installed as batcat.
if command -v batcat > /dev/null; then
BATNAME="batcat"
elif command -v bat > /dev/null; then
BATNAME="bat"
fi
if [ -z "$FZF_PREVIEW_COMMAND" ] && [ "${BATNAME:+x}" ]; then
${BATNAME} --style="${BAT_STYLE:-numbers}" \
--color=always \
--pager=never \
--wrap=never \
--terminal-width="${FZF_PREVIEW_COLUMNS}" \
--line-range="${START_LINE}:${END_LINE}" \
--highlight-line="${CENTER}" \
"$FILE"
exit $?
fi
DEFAULT_COMMAND="highlight -O ansi -l {} || coderay {} || rougify {} || cat {}"
CMD=${FZF_PREVIEW_COMMAND:-$DEFAULT_COMMAND}
CMD=${CMD//{\}/$(printf %q "$FILE")}
eval "$CMD" 2> /dev/null | awk "{ \
if (NR >= $START_LINE && NR <= $END_LINE) { \
if (NR == $CENTER) \
{ gsub(/\x1b[[0-9;]*m/, \"&$REVERSE\"); printf(\"$REVERSE%s\n$RESET\", \$0); } \
else printf(\"$RESET%s\n\", \$0); \
} \
}"

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env perl
use strict;
my $prefix = shift @ARGV;
foreach my $file (@ARGV) {
my $lines;
if ($prefix eq "") {
open $lines, $file;
} else {
# https://perldoc.perl.org/perlopentut#Expressing-the-command-as-a-list
open $lines, '-|', 'readtags', '-t', $file, '-e', '-p', '-', $prefix;
}
while (<$lines>) {
unless (/^\!/) {
s/^[^\t]*/sprintf("%-24s", $&)/e;
s/$/\t$file/;
print;
}
}
close $lines;
}

View File

@@ -1,35 +1,20 @@
fzf-vim.txt fzf-vim Last change: June 8 2025 fzf-vim.txt fzf-vim Last change: September 20 2015
FZF-VIM - TABLE OF CONTENTS *fzf-vim* *fzf-vim-toc* FZF-VIM - TABLE OF CONTENTS *fzf-vim* *fzf-vim-toc*
============================================================================== ==============================================================================
fzf :heart: vim |fzf-vim-fzfheart-vim| fzf :heart: vim
Rationale |fzf-vim-rationale| Rationale
Why you should use fzf on Vim |fzf-vim-why-you-should-use-fzf-on-vim| Why you should use fzf on Vim
Installation |fzf-vim-installation| Installation
Using vim-plug |fzf-vim-using-vim-plug| Commands
Dependencies |fzf-vim-dependencies| Customization
Commands |fzf-vim-commands| Mappings
Customization |fzf-vim-customization| Usage
Configuration options of the base plugin |fzf-vim-configuration-options-of-the-base-plugin| Completion helper
Configuration options for fzf.vim |fzf-vim-configuration-options-for-fzf-vim| Reducer example
Preview window |fzf-vim-preview-window| License
Command-level options |fzf-vim-command-level-options|
Command-level fzf options |fzf-vim-command-level-fzf-options|
List type to handle multiple selections |fzf-vim-list-type-to-handle-multiple-selections|
Advanced customization |fzf-vim-advanced-customization|
Vim functions |fzf-vim-vim-functions|
Example: Customizing Files command |fzf-vim-example-customizing-files-command|
Example: git grep wrapper |fzf-vim-example-git-grep-wrapper|
Mappings |fzf-vim-mappings|
Completion functions |fzf-vim-completion-functions|
Custom completion |fzf-vim-custom-completion|
Reducer example |fzf-vim-reducer-example|
Status line of terminal buffer |fzf-vim-status-line-of-terminal-buffer|
Hide statusline |fzf-vim-hide-statusline|
Custom statusline |fzf-vim-custom-statusline|
License |fzf-vim-license|
FZF :HEART: VIM *fzf-vim-fzfheart-vim* FZF :HEART: VIM *fzf-vim-fzf-heart-vim*
============================================================================== ==============================================================================
Things you can do with {fzf}{1} and Vim. Things you can do with {fzf}{1} and Vim.
@@ -40,14 +25,19 @@ Things you can do with {fzf}{1} and Vim.
RATIONALE *fzf-vim-rationale* RATIONALE *fzf-vim-rationale*
============================================================================== ==============================================================================
{fzf}{1} itself is not a Vim plugin, and the official repository only provides {fzf}{1} in itself is not a Vim plugin, and the official repository only
the {basic wrapper function}{2} for Vim. It's up to the users to write their provides the {basic wrapper function}{2} for Vim and it's up to the users to
own Vim commands with it. However, I've learned that many users of fzf are not write their own Vim commands with it. However, I've learned that many users of
familiar with Vimscript and are looking for the "default" implementation of fzf are not familiar with Vimscript and are looking for the "default"
the features they can find in the alternative Vim plugins. implementation of the features they can find in the alternative Vim plugins.
{1} https://github.com/junegunn/fzf This repository is a bundle of fzf-based commands and mappings extracted from
{2} https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzfrun my {.vimrc}{3} to address such needs. They are not designed to be flexible or
configurable, and there's no guarantee of backward-compatibility.
{1} https://github.com/junegunn/fzf
{2} https://github.com/junegunn/fzf#usage-as-vim-plugin
{3} https://github.com/junegunn/dotfiles/blob/master/vimrc
WHY YOU SHOULD USE FZF ON VIM *fzf-vim-why-you-should-use-fzf-on-vim* WHY YOU SHOULD USE FZF ON VIM *fzf-vim-why-you-should-use-fzf-on-vim*
@@ -61,355 +51,146 @@ is small, which is the case for many of the commands provided here.
Nevertheless I wrote them anyway since it's really easy to implement custom Nevertheless I wrote them anyway since it's really easy to implement custom
selector with fzf. selector with fzf.
fzf is an independent command-line program and thus requires an external
terminal emulator when on GVim. You may or may not like the experience. Also
note that fzf currently does not compile on Windows.
INSTALLATION *fzf-vim-installation* INSTALLATION *fzf-vim-installation*
============================================================================== ==============================================================================
fzf.vim depends on the basic Vim plugin of {the main fzf repository}{1}, which Using {vim-plug}{4}:
means you need to set up both "fzf" and "fzf.vim" on Vim. To learn more about
fzf/Vim integration, see {README-VIM}{3}.
{1} https://github.com/junegunn/fzf
{3} https://github.com/junegunn/fzf/blob/master/README-VIM.md
< Using vim-plug >____________________________________________________________~
*fzf-vim-using-vim-plug*
> >
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': 'yes \| ./install' }
Plug 'junegunn/fzf.vim' Plug 'junegunn/fzf.vim'
< <
`fzf#install()` makes sure that you have the latest binary, but it's optional, {4} https://github.com/junegunn/vim-plug
so you can omit it if you use a plugin manager that doesn't support hooks.
< Dependencies >______________________________________________________________~
*fzf-vim-dependencies*
- {fzf}{1} 0.54.0 or above
- For syntax-highlighted preview, install {bat}{4}
- If {delta}{5} is available, `GF?`, `Commits` and `BCommits` will use it to
format `git diff` output.
- `Ag` requires {The Silver Searcher (ag)}{6}
- `Rg` requires {ripgrep (rg)}{7}
- `Tags` and `Helptags` require Perl
- `Tags PREFIX` requires `readtags` command from {Universal Ctags}{8}
>
# Installing dependencies using Homebrew
brew install fzf bat ripgrep the_silver_searcher perl universal-ctags
<
{1} https://github.com/junegunn/fzf
{4} https://github.com/sharkdp/bat
{5} https://github.com/dandavison/delta
{6} https://github.com/ggreer/the_silver_searcher
{7} https://github.com/BurntSushi/ripgrep
{8} https://ctags.io/
COMMANDS *fzf-vim-commands* COMMANDS *fzf-vim-commands*
============================================================================== ==============================================================================
*:Files* *:GFiles* *:Buffers* *:Colors* *:Ag* *:Rg* *:RG* *:Lines* *:BLines* *:Tags* *:BTags*
*:Changes* *:Marks* *:BMarks* *:Jumps* *:Windows* *:Locate* *:History* *:Snippets* *:Commits*
*:BCommits* *:Commands* *:Maps* *:Helptags* *:Filetypes*
-----------------------+-------------------------------------------------------------------------------------- -----------------+-------------------------------------------------------------------
Command | List ~ Command | List ~
-----------------------+-------------------------------------------------------------------------------------- -----------------+-------------------------------------------------------------------
`:Files [PATH]` | Files (runs `$FZF_DEFAULT_COMMAND` if defined) `Files[PATH]` | Files (similar to `:FZF` )
`:GFiles [OPTS]` | Git files ( `git ls-files` ) `GFiles [OPTS]` | Git files (git ls-files)
`:GFiles?` | Git files ( `git status` ) `GFiles?` | Git files (git status)
`:Buffers` | Open buffers `Buffers` | Open buffers
`:Colors` | Color schemes `Colors` | Color schemes
`:Ag [PATTERN]` | {ag}{6} search result ( `ALT-A` to select all, `ALT-D` to deselect all) `Ag[PATTERN]` | {ag}{5} search result (ALT-A to select all, ALT-D to deselect all)
`:Rg [PATTERN]` | {rg}{7} search result ( `ALT-A` to select all, `ALT-D` to deselect all) `Lines [QUERY]` | Lines in loaded buffers
`:RG [PATTERN]` | {rg}{7} search result; relaunch ripgrep on every keystroke `BLines [QUERY]` | Lines in the current buffer
`:Lines [QUERY]` | Lines in loaded buffers `Tags[QUERY]` | Tags in the project ( `ctags-R` )
`:BLines [QUERY]` | Lines in the current buffer `BTags[QUERY]` | Tags in the current buffer
`:Tags [PREFIX]` | Tags in the project ( `ctags -R` ) `Marks` | Marks
`:BTags [QUERY]` | Tags in the current buffer `Windows` | Windows
`:Changes` | Changelist across all open buffers `LocatePATTERN` | `locate` command output
`:Marks` | Marks `History` | `v:oldfiles` and open buffers
`:BMarks` | Marks in the current buffer `History:` | Command history
`:Jumps` | Jumps `History/` | Search history
`:Windows` | Windows `Snippets` | Snippets ({UltiSnips}{6})
`:Locate PATTERN` | `locate` command output `Commits` | Git commits (requires {fugitive.vim}{7})
`:History` | `v:oldfiles` and open buffers `BCommits` | Git commits for the current buffer
`:History:` | Command history `Commands` | Commands
`:History/` | Search history `Maps` | Normal mode mappings
`:Snippets` | Snippets ({UltiSnips}{9}) `Helptags` | Help tags [1]
`:Commits [LOG_OPTS]` | Git commits (requires {fugitive.vim}{10}) `Filetypes` | File types
`:BCommits [LOG_OPTS]` | Git commits for the current buffer; visual-select lines to track changes in the range -----------------+-------------------------------------------------------------------
`:Commands` | Commands
`:Maps` | Normal mode mappings
`:Helptags` | Help tags [1]
`:Filetypes` | File types
-----------------------+--------------------------------------------------------------------------------------
*g:fzf_vim.command_prefix*
- Most commands support CTRL-T / CTRL-X / CTRL-V key bindings to open in a new - Most commands support CTRL-T / CTRL-X / CTRL-V key bindings to open in a new
tab, a new split, or in a new vertical split tab, a new split, or in a new vertical split
- Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen - Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen
- You can set `g:fzf_vim.command_prefix` to give the same prefix to the commands - You can set `g:fzf_command_prefix` to give the same prefix to the commands
- e.g. `let g:fzf_vim.command_prefix = 'Fzf'` and you have `FzfFiles`, etc. - e.g. `let g:fzf_command_prefix = 'Fzf'` and you have `FzfFiles`, etc.
(1: `Helptags` will shadow the command of the same name from {pathogen}{11}. (1: `Helptags` will shadow the command of the same name from {pathogen}{8}.
But its functionality is still available via `call pathogen#helptags()`. [↩]) But its functionality is still available via `call pathogen#helptags()`.)
{6} https://github.com/ggreer/the_silver_searcher {5} https://github.com/ggreer/the_silver_searcher
{7} https://github.com/BurntSushi/ripgrep {6} https://github.com/SirVer/ultisnips
{7} https://github.com/BurntSushi/ripgrep {7} https://github.com/tpope/vim-fugitive
{9} https://github.com/SirVer/ultisnips {8} https://github.com/tpope/vim-pathogen
{10} https://github.com/tpope/vim-fugitive
{11} https://github.com/tpope/vim-pathogen
CUSTOMIZATION *fzf-vim-customization* < Customization >_____________________________________________________________~
============================================================================== *fzf-vim-customization*
*g:fzf_action* *g:fzf_layout* *g:fzf_colors* *g:fzf_commits_log_options*
< Configuration options of the base plugin >__________________________________~ Global options~
*fzf-vim-configuration-options-of-the-base-plugin*
Every command in fzf.vim internally calls `fzf#wrap` function of the main
repository which supports a set of global option variables. So please read
through {README-VIM}{3} to learn more about them.
{3} https://github.com/junegunn/fzf/blob/master/README-VIM.md
< Configuration options for fzf.vim >_________________________________________~
*fzf-vim-configuration-options-for-fzf-vim*
*g:fzf_vim*
All configuration values for this plugin are stored in `g:fzf_vim` dictionary,
so make sure to initialize it before assigning any configuration values to it.
> >
" Initialize configuration dictionary " This is the default extra key bindings
let g:fzf_vim = {} let g:fzf_action = {
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'split',
\ 'ctrl-v': 'vsplit' }
" Default fzf layout
" - down / up / left / right
let g:fzf_layout = { 'down': '~40%' }
" In Neovim, you can set up fzf window using a Vim command
let g:fzf_layout = { 'window': 'enew' }
let g:fzf_layout = { 'window': '-tabnew' }
" Customize fzf colors to match your color scheme
let g:fzf_colors =
\ { 'fg': ['fg', 'Normal'],
\ 'bg': ['bg', 'Normal'],
\ 'hl': ['fg', 'Comment'],
\ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
\ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
\ 'hl+': ['fg', 'Statement'],
\ 'info': ['fg', 'PreProc'],
\ 'prompt': ['fg', 'Conditional'],
\ 'pointer': ['fg', 'Exception'],
\ 'marker': ['fg', 'Keyword'],
\ 'spinner': ['fg', 'Label'],
\ 'header': ['fg', 'Comment'] }
" Enable per-command history.
" CTRL-N and CTRL-P will be automatically bound to next-history and
" previous-history instead of down and up. If you don't like the change,
" explicitly bind the keys to down and up in your $FZF_DEFAULT_OPTS.
let g:fzf_history_dir = '~/.local/share/fzf-history'
< <
Preview window~ Command-local options~
*fzf-vim-preview-window*
*g:fzf_vim.preview_window*
Some commands will show the preview window on the right. You can customize the
behavior with `g:fzf_vim.preview_window`. Here are some examples:
*g:fzf_vim.preview_bash*
> >
" This is the default option: " [Files] Extra options for fzf
" - Preview window on the right with 50% width " e.g. File preview using coderay (http://coderay.rubychan.de/)
" - CTRL-/ will toggle preview window. let g:fzf_files_options =
" - Note that this array is passed as arguments to fzf#vim#with_preview function. \ '--preview "(coderay {} || cat {}) 2> /dev/null | head -'.&lines.'"'
" - To learn more about preview window options, see `--preview-window` section of `man fzf`.
let g:fzf_vim.preview_window = ['right,50%', 'ctrl-/']
" Preview window is hidden by default. You can toggle it with ctrl-/. " [Buffers] Jump to the existing window if possible
" It will show on the right with 50% width, but if the width is smaller let g:fzf_buffers_jump = 1
" than 70 columns, it will show above the candidate list
let g:fzf_vim.preview_window = ['hidden,right,50%,<70(up,40%)', 'ctrl-/']
" Empty value to disable preview window altogether
let g:fzf_vim.preview_window = []
" fzf.vim needs bash to display the preview window.
" On Windows, fzf.vim will first see if bash is in $PATH, then if
" Git bash (C:\Program Files\Git\bin\bash.exe) is available.
" If you want it to use a different bash, set this variable.
" let g:fzf_vim = {}
" let g:fzf_vim.preview_bash = 'C:\Git\bin\bash.exe'
<
Command-level options~
*fzf-vim-command-level-options*
*g:fzf_vim.commands_expect* *g:fzf_vim.tags_command* *g:fzf_vim.commits_log_options*
*g:fzf_vim.buffers_jump*
>
" [Buffers] Jump to the existing window if possible (default: 0)
let g:fzf_vim.buffers_jump = 1
" [Ag|Rg|RG] Display path on a separate line for narrow screens (default: 0)
" * Requires Perl and fzf 0.56.0 or later
let g:fzf_vim.grep_multi_line = 0
" PATH:LINE:COL:LINE
let g:fzf_vim.grep_multi_line = 1
" PATH:LINE:COL:
" LINE
let g:fzf_vim.grep_multi_line = 2
" PATH:LINE:COL:
" LINE
" (empty line between items using --gap option)
" [[B]Commits] Customize the options used by 'git log': " [[B]Commits] Customize the options used by 'git log':
let g:fzf_vim.commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"' let g:fzf_commits_log_options = \
'--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'
" [Tags] Command to generate tags file " [Tags] Command to generate tags file
let g:fzf_vim.tags_command = 'ctags -R' let g:fzf_tags_command = 'ctags -R'
" [Commands] --expect expression for directly executing the command " [Commands] --expect expression for directly executing the command
let g:fzf_vim.commands_expect = 'alt-enter,ctrl-x' let g:fzf_commands_expect = 'alt-enter,ctrl-x'
< <
Command-level fzf options~ Advanced customization using autoload functions~
*fzf-vim-command-level-fzf-options*
You can set fzf options for each command by setting You can use autoload functions to define your own commands.
`g:fzf_vim.{command}_options`.
>
" In string
let g:fzf_vim.buffers_options = '--style full --border-label " Open Buffers "'
" In list (No need to quote or escape values)
let g:fzf_vim.buffers_options = ['--style', 'full', '--border-label', ' Open Buffers ']
<
List type to handle multiple selections~
*fzf-vim-list-type-to-handle-multiple-selections*
The following commands will fill the quickfix list when multiple entries are
selected.
- `Ag`
- `Rg` / `RG`
- `Lines` / `BLines`
- `Tags` / `BTags`
*g:fzf_vim.listproc*
By setting `g:fzf_vim.listproc`, you can make them use location list instead.
>
" Default: Use quickfix list
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#quickfix(list) }
" Use location list instead of quickfix list
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#location(list) }
<
You can customize the list type per command by defining variables named
`g:fzf_vim.listproc_{command_name_in_lowercase}`.
*g:fzf_vim.listproc_rg* *g:fzf_vim.listproc_ag*
>
" Command-wise customization
let g:fzf_vim.listproc_ag = { list -> fzf#vim#listproc#quickfix(list) }
let g:fzf_vim.listproc_rg = { list -> fzf#vim#listproc#location(list) }
<
You can further customize the behavior by providing a custom function to
process the list instead of using the predefined `fzf#vim#listproc#quickfix`
or `fzf#vim#listproc#location`.
>
" A customized version of fzf#vim#listproc#quickfix.
" The last two lines are commented out not to move to the first entry.
function! g:fzf_vim.listproc(list)
call setqflist(a:list)
copen
wincmd p
" cfirst
" normal! zvzz
endfunction
<
< Advanced customization >____________________________________________________~
*fzf-vim-advanced-customization*
Vim functions~
*fzf-vim-vim-functions*
Each command in fzf.vim is backed by a Vim function. You can override a
command or define a variation of it by calling its corresponding function.
----------+---------------------------------------------------------------------------------
Command | Vim function ~
----------+---------------------------------------------------------------------------------
`Files` | `fzf#vim#files(dir, [spec dict], [fullscreen bool])`
`GFiles` | `fzf#vim#gitfiles(git_options, [spec dict], [fullscreen bool])`
`GFiles?` | `fzf#vim#gitfiles('?', [spec dict], [fullscreen bool])`
`Buffers` | `fzf#vim#buffers([query string], [bufnrs list], [spec dict], [fullscreen bool])`
`Colors` | `fzf#vim#colors([spec dict], [fullscreen bool])`
`Rg` | `fzf#vim#grep(command, [spec dict], [fullscreen bool])`
`RG` | `fzf#vim#grep2(command_prefix, query, [spec dict], [fullscreen bool])`
... | ...
----------+---------------------------------------------------------------------------------
(We can see that the last two optional arguments of each function are
identical. They are directly passed to `fzf#wrap` function. If you haven't
read {README-VIM}{3} already, please read it before proceeding.)
{3} https://github.com/junegunn/fzf/blob/master/README-VIM.md
Example: Customizing Files command~
*fzf-vim-example-customizing-files-command*
This is the default definition of `Files` command:
>
command! -bang -nargs=? -complete=dir Files call fzf#vim#files(<q-args>, <bang>0)
<
Let's say you want to a variation of it called `ProjectFiles` that only
searches inside `~/projects` directory. Then you can do it like this:
>
command! -bang ProjectFiles call fzf#vim#files('~/projects', <bang>0)
<
Or, if you want to override the command with different fzf options, just pass
a custom spec to the function.
>
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline']}, <bang>0)
<
Want a preview window?
>
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', 'cat {}']}, <bang>0)
<
It kind of works, but you probably want a nicer previewer program than `cat`.
fzf.vim ships {a versatile preview script}{12} you can readily use. It
internally executes {bat}{4} for syntax highlighting, so make sure to install
it.
>
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', '~/.vim/plugged/fzf.vim/bin/preview.sh {}']}, <bang>0)
<
However, it's not ideal to hard-code the path to the script which can be
different in different circumstances. So in order to make it easier to set up
the previewer, fzf.vim provides `fzf#vim#with_preview` helper function.
Similarly to `fzf#wrap`, it takes a spec dictionary and returns a copy of it
with additional preview options.
>
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview({'options': ['--layout=reverse', '--info=inline']}), <bang>0)
<
You can just omit the spec argument if you only want the previewer.
>
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
<
{12} bin/preview.sh
{4} https://github.com/sharkdp/bat
Example: git grep wrapper~
*fzf-vim-example-git-grep-wrapper*
The following example implements `GGrep` command that works similarly to
predefined `Ag` or `Rg` using `fzf#vim#grep`.
- We set the base directory to git root by setting `dir` attribute in spec
dictionary.
- {The preview script}{12} supports `grep` format (`FILE_PATH:LINE_NO:...`), so
we can just wrap the spec with `fzf#vim#with_preview` as before to enable
previewer.
> >
" git grep
command! -bang -nargs=* GGrep command! -bang -nargs=* GGrep
\ call fzf#vim#grep( \ call fzf#vim#grep('git grep --line-number '.shellescape(<q-args>), 0, <bang>0)
\ 'git grep --line-number -- '.fzf#shellescape(<q-args>),
\ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0) " We use VimEnter event so that the code is run after fzf.vim is loaded
autocmd VimEnter * command! Colors
\ call fzf#vim#colors({'left': '15%', 'options': '--reverse --margin 30%,0'})
< <
{12} bin/preview.sh
MAPPINGS *fzf-vim-mappings* MAPPINGS *fzf-vim-mappings*
@@ -422,12 +203,17 @@ MAPPINGS *fzf-vim-mappings*
<plug>(fzf-maps-i) | Insert mode mappings <plug>(fzf-maps-i) | Insert mode mappings
<plug>(fzf-maps-x) | Visual mode mappings <plug>(fzf-maps-x) | Visual mode mappings
<plug>(fzf-maps-o) | Operator-pending mappings <plug>(fzf-maps-o) | Operator-pending mappings
<plug>(fzf-complete-word) | `cat /usr/share/dict/words` <plug>(fzf-complete-word) | `cat/usr/share/dict/words`
<plug>(fzf-complete-path) | Path completion using `find` (file + dir) <plug>(fzf-complete-path) | Path completion using `find` (file + dir)
<plug>(fzf-complete-file) | File completion using `find` <plug>(fzf-complete-file) | File completion using `find`
<plug>(fzf-complete-file-ag) | File completion using `ag`
<plug>(fzf-complete-line) | Line completion (all open buffers) <plug>(fzf-complete-line) | Line completion (all open buffers)
<plug>(fzf-complete-buffer-line) | Line completion (current buffer only) <plug>(fzf-complete-buffer-line) | Line completion (current buffer only)
---------------------------------+------------------------------------------ ---------------------------------+------------------------------------------
< Usage >_____________________________________________________________________~
*fzf-vim-usage*
> >
" Mapping selecting mappings " Mapping selecting mappings
nmap <leader><tab> <plug>(fzf-maps-n) nmap <leader><tab> <plug>(fzf-maps-n)
@@ -437,38 +223,22 @@ MAPPINGS *fzf-vim-mappings*
" Insert mode completion " Insert mode completion
imap <c-x><c-k> <plug>(fzf-complete-word) imap <c-x><c-k> <plug>(fzf-complete-word)
imap <c-x><c-f> <plug>(fzf-complete-path) imap <c-x><c-f> <plug>(fzf-complete-path)
imap <c-x><c-j> <plug>(fzf-complete-file-ag)
imap <c-x><c-l> <plug>(fzf-complete-line) imap <c-x><c-l> <plug>(fzf-complete-line)
" Advanced customization using autoload functions
inoremap <expr> <c-x><c-k> fzf#vim#complete#word({'left': '15%'})
< <
COMPLETION FUNCTIONS *fzf-vim-completion-functions* < Completion helper >_________________________________________________________~
============================================================================== *fzf-vim-completion-helper*
-----------------------------------------+-------------------------------------- `fzf#complete` is a helper function for creating custom fuzzy completion using
Function | Description ~ fzf. If the first parameter is a command string or a Vim list, it will be used
-----------------------------------------+-------------------------------------- as the source.
`fzf#vim#complete#path(command, [spec])` | Path completion
`fzf#vim#complete#word([spec])` | Word completion
`fzf#vim#complete#line([spec])` | Line completion (all open buffers)
`fzf#vim#complete#buffer_line([spec])` | Line completion (current buffer only)
-----------------------------------------+--------------------------------------
>
" Path completion with custom source command
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('fd')
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('rg --files')
" Word completion with custom spec with popup layout option
inoremap <expr> <c-x><c-k> fzf#vim#complete#word({'window': { 'width': 0.2, 'height': 0.9, 'xoffset': 1 }})
<
CUSTOM COMPLETION *fzf-vim-custom-completion*
==============================================================================
`fzf#vim#complete` is a helper function for creating custom fuzzy completion
using fzf. If the first parameter is a command string or a Vim list, it will
be used as the source.
> >
" Replace the default dictionary completion with fzf-based fuzzy completion " Replace the default dictionary completion with fzf-based fuzzy completion
inoremap <expr> <c-x><c-k> fzf#vim#complete('cat /usr/share/dict/words') inoremap <expr> <c-x><c-k> fzf#complete('cat /usr/share/dict/words')
< <
For advanced uses, you can pass an options dictionary to the function. The set For advanced uses, you can pass an options dictionary to the function. The set
of options is pretty much identical to that for `fzf#run` only with the of options is pretty much identical to that for `fzf#run` only with the
@@ -481,60 +251,23 @@ following exceptions:
- Or a function to extract completion prefix - Or a function to extract completion prefix
- Both `source` and `options` can be given as funcrefs that take the completion - Both `source` and `options` can be given as funcrefs that take the completion
prefix as the argument and return the final value prefix as the argument and return the final value
- `sink` or `sink*` are ignored - `sink` or `sink*` are not allowed
>
" Global line completion (not just open buffers. ripgrep required.)
inoremap <expr> <c-x><c-l> fzf#vim#complete(fzf#wrap({
\ 'prefix': '^.*$',
\ 'source': 'rg -n ^ --color always',
\ 'options': '--ansi --delimiter : --nth 3..',
\ 'reducer': { lines -> join(split(lines[0], ':\zs')[2:], '') }}))
<
< Reducer example >___________________________________________________________~
Reducer example~
*fzf-vim-reducer-example* *fzf-vim-reducer-example*
> >
function! s:make_sentence(lines) function! s:make_sentence(lines)
return substitute(join(a:lines), '^.', '\=toupper(submatch(0))', '').'.' return substitute(join(a:lines), '^.', '\=toupper(submatch(0))', '').'.'
endfunction endfunction
inoremap <expr> <c-x><c-s> fzf#vim#complete({ inoremap <expr> <c-x><c-s> fzf#complete({
\ 'source': 'cat /usr/share/dict/words', \ 'source': 'cat /usr/share/dict/words',
\ 'reducer': function('<sid>make_sentence'), \ 'reducer': function('<sid>make_sentence'),
\ 'options': '--multi --reverse --margin 15%,0', \ 'options': '--multi --reverse --margin 15%,0',
\ 'left': 20}) \ 'left': 20})
< <
STATUS LINE OF TERMINAL BUFFER *fzf-vim-status-line-of-terminal-buffer*
==============================================================================
When fzf starts in a terminal buffer (see {fzf/README-VIM.md}{13}), you may
want to customize the statusline of the containing buffer.
{13} https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzf-inside-terminal-buffer
< Hide statusline >___________________________________________________________~
*fzf-vim-hide-statusline*
>
autocmd! FileType fzf set laststatus=0 noshowmode noruler
\| autocmd BufLeave <buffer> set laststatus=2 showmode ruler
<
< Custom statusline >_________________________________________________________~
*fzf-vim-custom-statusline*
>
function! s:fzf_statusline()
" Override statusline as you like
highlight fzf1 ctermfg=161 ctermbg=251
highlight fzf2 ctermfg=23 ctermbg=251
highlight fzf3 ctermfg=237 ctermbg=251
setlocal statusline=%#fzf1#\ >\ %#fzf2#fz%#fzf3#f
endfunction
autocmd! User FzfStatusLine call <SID>fzf_statusline()
<
LICENSE *fzf-vim-license* LICENSE *fzf-vim-license*
============================================================================== ==============================================================================

View File

@@ -21,71 +21,53 @@
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
if exists('g:loaded_fzf_vim')
finish
endif
let g:loaded_fzf_vim = 1
let s:cpo_save = &cpo let s:cpo_save = &cpo
set cpo&vim set cpo&vim
let s:is_win = has('win32') || has('win64')
function! s:conf(name, default) let g:fzf#vim#default_layout = {'down': '~40%'}
let conf = get(g:, 'fzf_vim', {})
let val = get(conf, a:name, get(g:, 'fzf_' . a:name, a:default))
return val
endfunction
function! s:defs(commands) function! s:defs(commands)
let prefix = s:conf('command_prefix', '') let prefix = get(g:, 'fzf_command_prefix', '')
if prefix =~# '^[^A-Z]' if prefix =~# '^[^A-Z]'
echoerr 'g:fzf_command_prefix must start with an uppercase letter' echoerr 'g:fzf_command_prefix must start with an uppercase letter'
return return
endif endif
for command in a:commands for command in a:commands
let name = ':'.prefix.matchstr(command, '\C[A-Z]\S\+') execute substitute(command, '\ze\C[A-Z]', prefix, '')
if 2 != exists(name)
execute substitute(command, '\ze\C[A-Z]', prefix, '')
endif
endfor endfor
endfunction endfunction
call s:defs([ call s:defs([
\'command! -bang -nargs=? -complete=dir Files call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)', \'command! -bang -nargs=? -complete=dir Files call fzf#vim#files(<q-args>, <bang>0)',
\'command! -bang -nargs=? GitFiles call fzf#vim#gitfiles(<q-args>, fzf#vim#with_preview(<q-args> == "?" ? { "placeholder": "" } : {}), <bang>0)', \'command! -bang -nargs=? GitFiles call fzf#vim#gitfiles(<q-args>, <bang>0)',
\'command! -bang -nargs=? GFiles call fzf#vim#gitfiles(<q-args>, fzf#vim#with_preview(<q-args> == "?" ? { "placeholder": "" } : {}), <bang>0)', \'command! -bang -nargs=? GFiles call fzf#vim#gitfiles(<q-args>, <bang>0)',
\'command! -bar -bang -nargs=? -complete=buffer Buffers call fzf#vim#buffers(<q-args>, fzf#vim#with_preview({ "placeholder": "{1}" }), <bang>0)', \'command! -bang Buffers call fzf#vim#buffers(<bang>0)',
\'command! -bang -nargs=* Lines call fzf#vim#lines(<q-args>, <bang>0)', \'command! -bang -nargs=* Lines call fzf#vim#lines(<q-args>, <bang>0)',
\'command! -bang -nargs=* BLines call fzf#vim#buffer_lines(<q-args>, <bang>0)', \'command! -bang -nargs=* BLines call fzf#vim#buffer_lines(<q-args>, <bang>0)',
\'command! -bar -bang Colors call fzf#vim#colors(<bang>0)', \'command! -bang Colors call fzf#vim#colors(<bang>0)',
\'command! -bang -nargs=+ -complete=dir Locate call fzf#vim#locate(<q-args>, fzf#vim#with_preview(), <bang>0)', \'command! -bang -nargs=+ -complete=dir Locate call fzf#vim#locate(<q-args>, <bang>0)',
\'command! -bang -nargs=* Ag call fzf#vim#ag(<q-args>, fzf#vim#with_preview(), <bang>0)', \'command! -bang -nargs=* Ag call fzf#vim#ag(<q-args>, <bang>0)',
\'command! -bang -nargs=* Rg call fzf#vim#grep("rg --column --line-number --no-heading --color=always --smart-case -- ".fzf#shellescape(<q-args>), fzf#vim#with_preview(), <bang>0)', \'command! -bang -nargs=* Tags call fzf#vim#tags(<q-args>, <bang>0)',
\'command! -bang -nargs=* RG call fzf#vim#grep2("rg --column --line-number --no-heading --color=always --smart-case -- ", <q-args>, fzf#vim#with_preview(), <bang>0)', \'command! -bang -nargs=* BTags call fzf#vim#buffer_tags(<q-args>, <bang>0)',
\'command! -bang -nargs=* Tags call fzf#vim#tags(<q-args>, fzf#vim#with_preview({ "placeholder": "--tag {2}:{-1}:{3..}" }), <bang>0)', \'command! -bang Snippets call fzf#vim#snippets(<bang>0)',
\'command! -bang -nargs=* BTags call fzf#vim#buffer_tags(<q-args>, fzf#vim#with_preview({ "placeholder": "{2}:{3..}" }), <bang>0)', \'command! -bang Commands call fzf#vim#commands(<bang>0)',
\'command! -bar -bang Snippets call fzf#vim#snippets(<bang>0)', \'command! -bang Marks call fzf#vim#marks(<bang>0)',
\'command! -bar -bang Commands call fzf#vim#commands(<bang>0)', \'command! -bang Helptags call fzf#vim#helptags(<bang>0)',
\'command! -bar -bang Jumps call fzf#vim#jumps(fzf#vim#with_preview({ "placeholder": "{2..4}"}), <bang>0)', \'command! -bang Windows call fzf#vim#windows(<bang>0)',
\'command! -bar -bang -nargs=* Marks call fzf#vim#marks(<q-args>, <bang>0)', \'command! -bang Commits call fzf#vim#commits(<bang>0)',
\'command! -bar -bang -nargs=* BMarks call fzf#vim#marks("abcdefghijklmnopqrstuvwxyz", <bang>0)', \'command! -bang BCommits call fzf#vim#buffer_commits(<bang>0)',
\'command! -bar -bang Changes call fzf#vim#changes(<bang>0)', \'command! -bang Maps call fzf#vim#maps("n", <bang>0)',
\'command! -bar -bang Helptags call fzf#vim#helptags(fzf#vim#with_preview({ "placeholder": "--tag {2}:{3}:{4}" }), <bang>0)', \'command! -bang Filetypes call fzf#vim#filetypes(<bang>0)',
\'command! -bar -bang Windows call fzf#vim#windows(fzf#vim#with_preview({ "placeholder": "{2}" }), <bang>0)', \'command! -bang -nargs=* History call s:history(<q-args>, <bang>0)'])
\'command! -bar -bang -nargs=* -range=% -complete=file Commits let b:fzf_winview = winsaveview() | <line1>,<line2>call fzf#vim#commits(<q-args>, fzf#vim#with_preview({ "placeholder": "" }), <bang>0)',
\'command! -bar -bang -nargs=* -range=% BCommits let b:fzf_winview = winsaveview() | <line1>,<line2>call fzf#vim#buffer_commits(<q-args>, fzf#vim#with_preview({ "placeholder": "" }), <bang>0)',
\'command! -bar -bang Maps call fzf#vim#maps("n", <bang>0)',
\'command! -bar -bang Filetypes call fzf#vim#filetypes(<bang>0)',
\'command! -bang -nargs=* History call s:history(<q-args>, fzf#vim#with_preview(), <bang>0)'])
function! s:history(arg, extra, bang) function! s:history(arg, bang)
let bang = a:bang || a:arg[len(a:arg)-1] == '!' let bang = a:bang || a:arg[len(a:arg)-1] == '!'
if a:arg[0] == ':' if a:arg[0] == ':'
call fzf#vim#command_history(bang) call fzf#vim#command_history(bang)
elseif a:arg[0] == '/' elseif a:arg[0] == '/'
call fzf#vim#search_history(bang) call fzf#vim#search_history(bang)
else else
call fzf#vim#history(a:extra, bang) call fzf#vim#history(bang)
endif endif
endfunction endfunction
@@ -93,25 +75,25 @@ function! fzf#complete(...)
return call('fzf#vim#complete', a:000) return call('fzf#vim#complete', a:000)
endfunction endfunction
if (has('nvim') || has('terminal') && has('patch-8.0.995')) && (s:conf('statusline', 1) || s:conf('nvim_statusline', 1)) if has('nvim') && get(g:, 'fzf_nvim_statusline', 1)
function! s:fzf_restore_colors() function! s:fzf_restore_colors()
if exists('#User#FzfStatusLine') if exists('#User#FzfStatusLine')
doautocmd User FzfStatusLine doautocmd User FzfStatusLine
else else
if $TERM !~ "256color" if $TERM !~ "256color"
highlight default fzf1 ctermfg=1 ctermbg=8 guifg=#E12672 guibg=#565656 highlight fzf1 ctermfg=1 ctermbg=8 guifg=#E12672 guibg=#565656
highlight default fzf2 ctermfg=2 ctermbg=8 guifg=#BCDDBD guibg=#565656 highlight fzf2 ctermfg=2 ctermbg=8 guifg=#BCDDBD guibg=#565656
highlight default fzf3 ctermfg=7 ctermbg=8 guifg=#D9D9D9 guibg=#565656 highlight fzf3 ctermfg=7 ctermbg=8 guifg=#D9D9D9 guibg=#565656
else else
highlight default fzf1 ctermfg=161 ctermbg=238 guifg=#E12672 guibg=#565656 highlight fzf1 ctermfg=161 ctermbg=238 guifg=#E12672 guibg=#565656
highlight default fzf2 ctermfg=151 ctermbg=238 guifg=#BCDDBD guibg=#565656 highlight fzf2 ctermfg=151 ctermbg=238 guifg=#BCDDBD guibg=#565656
highlight default fzf3 ctermfg=252 ctermbg=238 guifg=#D9D9D9 guibg=#565656 highlight fzf3 ctermfg=252 ctermbg=238 guifg=#D9D9D9 guibg=#565656
endif endif
setlocal statusline=%#fzf1#\ >\ %#fzf2#fz%#fzf3#f setlocal statusline=%#fzf1#\ >\ %#fzf2#fz%#fzf3#f
endif endif
endfunction endfunction
function! s:fzf_vim_term() function! s:fzf_nvim_term()
if get(w:, 'airline_active', 0) if get(w:, 'airline_active', 0)
let w:airline_disabled = 1 let w:airline_disabled = 1
autocmd BufWinLeave <buffer> let w:airline_disabled = 0 autocmd BufWinLeave <buffer> let w:airline_disabled = 0
@@ -124,14 +106,11 @@ if (has('nvim') || has('terminal') && has('patch-8.0.995')) && (s:conf('statusli
augroup _fzf_statusline augroup _fzf_statusline
autocmd! autocmd!
autocmd FileType fzf call s:fzf_vim_term() autocmd FileType fzf call s:fzf_nvim_term()
augroup END augroup END
endif endif
if !exists('g:fzf#vim#buffers') let g:fzf#vim#buffers = {}
let g:fzf#vim#buffers = {}
endif
augroup fzf_buffers augroup fzf_buffers
autocmd! autocmd!
if exists('*reltimefloat') if exists('*reltimefloat')
@@ -143,14 +122,9 @@ augroup fzf_buffers
augroup END augroup END
inoremap <expr> <plug>(fzf-complete-word) fzf#vim#complete#word() inoremap <expr> <plug>(fzf-complete-word) fzf#vim#complete#word()
if s:is_win inoremap <expr> <plug>(fzf-complete-path) fzf#vim#complete#path("find . -path '*/\.*' -prune -o -print \| sed '1d;s:^..::'")
inoremap <expr> <plug>(fzf-complete-path) fzf#vim#complete#path('dir /s/b') inoremap <expr> <plug>(fzf-complete-file) fzf#vim#complete#path("find . -path '*/\.*' -prune -o -type f -print -o -type l -print \| sed 's:^..::'")
inoremap <expr> <plug>(fzf-complete-file) fzf#vim#complete#path('dir /s/b/a:-d') inoremap <expr> <plug>(fzf-complete-file-ag) fzf#vim#complete#path("ag -l -g ''")
else
inoremap <expr> <plug>(fzf-complete-path) fzf#vim#complete#path("find . -path '*/\.*' -prune -o -print \| sed '1d;s:^..::'")
inoremap <expr> <plug>(fzf-complete-file) fzf#vim#complete#path("find . -path '*/\.*' -prune -o -type f -print -o -type l -print \| sed 's:^..::'")
endif
inoremap <expr> <plug>(fzf-complete-file-ag) fzf#vim#complete#path('ag -l -g ""')
inoremap <expr> <plug>(fzf-complete-line) fzf#vim#complete#line() inoremap <expr> <plug>(fzf-complete-line) fzf#vim#complete#line()
inoremap <expr> <plug>(fzf-complete-buffer-line) fzf#vim#complete#buffer_line() inoremap <expr> <plug>(fzf-complete-buffer-line) fzf#vim#complete#buffer_line()