2013-10-23 23:25:19 -04:00
|
|
|
fzf - Fuzzy finder for your shell
|
|
|
|
=================================
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
fzf is a general-purpose fuzzy finder for your shell.
|
|
|
|
|
2013-10-29 09:14:11 -04:00
|
|
|
![](https://raw.github.com/junegunn/i/master/fzf.gif)
|
2013-10-28 02:50:46 -04:00
|
|
|
|
2013-10-23 23:25:19 -04:00
|
|
|
It was heavily inspired by [ctrlp.vim](https://github.com/kien/ctrlp.vim) and
|
|
|
|
the likes.
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
Requirements
|
|
|
|
------------
|
|
|
|
|
2013-10-23 23:25:19 -04:00
|
|
|
fzf requires Ruby (>= 1.8.5).
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
Installation
|
|
|
|
------------
|
|
|
|
|
2013-11-19 11:29:36 -05:00
|
|
|
### Using install script
|
2013-10-22 21:26:55 -04:00
|
|
|
|
2013-11-19 11:29:36 -05:00
|
|
|
Clone this repository and run
|
2013-10-22 21:26:55 -04:00
|
|
|
[install](https://github.com/junegunn/fzf/blob/master/install) script.
|
|
|
|
|
|
|
|
```sh
|
2013-11-19 11:29:36 -05:00
|
|
|
git clone https://github.com/junegunn/fzf.git ~/.fzf
|
|
|
|
~/.fzf/install
|
2013-10-22 21:26:55 -04:00
|
|
|
```
|
|
|
|
|
2013-11-26 05:01:01 -05:00
|
|
|
The script will generate `~/.fzf.bash` and `~/.fzf.zsh` and update your
|
|
|
|
`.bashrc` and `.zshrc` to load them.
|
2013-11-19 11:29:36 -05:00
|
|
|
|
|
|
|
### Manual installation
|
|
|
|
|
|
|
|
Or you can just download
|
|
|
|
[fzf executable](https://raw.github.com/junegunn/fzf/master/fzf) and put it
|
|
|
|
somewhere in your search $PATH.
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
```sh
|
2013-11-19 11:29:36 -05:00
|
|
|
mkdir -p ~/bin
|
|
|
|
wget https://raw.github.com/junegunn/fzf/master/fzf -O ~/bin/fzf
|
|
|
|
chmod +x ~/bin/fzf
|
2013-10-22 21:26:55 -04:00
|
|
|
```
|
|
|
|
|
2013-10-31 12:12:46 -04:00
|
|
|
### Install as Ruby gem
|
|
|
|
|
|
|
|
fzf can be installed as a Ruby gem
|
|
|
|
|
|
|
|
```
|
|
|
|
gem install fzf
|
|
|
|
```
|
|
|
|
|
2013-11-01 23:56:43 -04:00
|
|
|
It's a bit easier to install and update the script but the Ruby gem version
|
|
|
|
takes slightly longer to start.
|
2013-10-31 12:12:46 -04:00
|
|
|
|
|
|
|
### Install as Vim plugin
|
2013-10-22 21:26:55 -04:00
|
|
|
|
2013-11-02 07:40:25 -04:00
|
|
|
You can use any Vim plugin manager to install fzf for Vim. If you don't use one,
|
|
|
|
I recommend you try [vim-plug](https://github.com/junegunn/vim-plug).
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
1. [Install vim-plug](https://github.com/junegunn/vim-plug#usage)
|
|
|
|
2. Edit your .vimrc
|
|
|
|
|
|
|
|
call plug#begin()
|
|
|
|
Plug 'junegunn/fzf'
|
|
|
|
" ...
|
|
|
|
call plug#end()
|
|
|
|
|
|
|
|
3. Run `:PlugInstall`
|
|
|
|
|
|
|
|
Usage
|
|
|
|
-----
|
|
|
|
|
2013-10-25 05:31:16 -04:00
|
|
|
```
|
|
|
|
usage: fzf [options]
|
|
|
|
|
2013-11-23 06:09:56 -05:00
|
|
|
-m, --multi Enable multi-select
|
|
|
|
-x, --extended Extended-search mode
|
|
|
|
-q, --query=STR Initial query
|
|
|
|
-s, --sort=MAX Maximum number of matched items to sort. Default: 1000
|
|
|
|
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
|
|
|
|
+i Case-sensitive match
|
|
|
|
+c, --no-color Disable colors
|
2013-10-25 05:31:16 -04:00
|
|
|
```
|
|
|
|
|
2013-10-22 21:26:55 -04:00
|
|
|
fzf will launch curses-based finder, read the list from STDIN, and write the
|
|
|
|
selected item to STDOUT.
|
|
|
|
|
|
|
|
```sh
|
|
|
|
find * -type f | fzf > selected
|
|
|
|
```
|
|
|
|
|
|
|
|
Without STDIN pipe, fzf will use find command to fetch the list of
|
2013-11-01 23:56:43 -04:00
|
|
|
files excluding hidden ones. (You can override the default command with
|
|
|
|
`FZF_DEFAULT_COMMAND`)
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
```sh
|
2013-11-06 06:54:02 -05:00
|
|
|
vim $(fzf)
|
2013-10-22 21:26:55 -04:00
|
|
|
```
|
|
|
|
|
2013-10-25 05:31:16 -04:00
|
|
|
If you want to preserve the exact sequence of the input, provide `--no-sort` (or
|
|
|
|
`+s`) option.
|
2013-10-24 05:56:33 -04:00
|
|
|
|
|
|
|
```sh
|
2013-10-25 05:31:16 -04:00
|
|
|
history | fzf +s
|
2013-10-24 05:56:33 -04:00
|
|
|
```
|
|
|
|
|
2013-10-22 21:26:55 -04:00
|
|
|
### Key binding
|
|
|
|
|
|
|
|
Use CTRL-J and CTRL-K (or CTRL-N and CTRL-P) to change the selection, press
|
2013-11-20 07:18:51 -05:00
|
|
|
enter key to select the item. CTRL-C, CTRL-G, or ESC will terminate the finder.
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
The following readline key bindings should also work as expected.
|
|
|
|
|
|
|
|
- CTRL-A / CTRL-E
|
|
|
|
- CTRL-B / CTRL-F
|
|
|
|
- CTRL-W / CTRL-U
|
2013-11-16 11:19:16 -05:00
|
|
|
- ALT-B / ALT-F
|
2013-10-22 21:26:55 -04:00
|
|
|
|
2013-11-09 13:56:18 -05:00
|
|
|
If you enable multi-select mode with `-m` option, you can select multiple items
|
2013-11-10 06:19:57 -05:00
|
|
|
with TAB or Shift-TAB key.
|
2013-11-09 13:56:18 -05:00
|
|
|
|
2013-11-15 12:21:39 -05:00
|
|
|
### Extended-search mode
|
2013-11-15 06:40:57 -05:00
|
|
|
|
2013-11-15 12:21:39 -05:00
|
|
|
With `-x` or `--extended` option, fzf will start in "extended-search mode".
|
2013-11-15 06:40:57 -05:00
|
|
|
|
2013-11-15 12:21:39 -05:00
|
|
|
In this mode, you can specify multiple patterns delimited by spaces,
|
|
|
|
such as: `^music .mp3$ sbtrkt !rmx`
|
2013-11-15 06:40:57 -05:00
|
|
|
|
2013-11-15 11:55:33 -05:00
|
|
|
| Token | Description | Match type |
|
|
|
|
| -------- | -------------------------------- | -------------------- |
|
|
|
|
| `^music` | Items that start with `music` | prefix-exact-match |
|
|
|
|
| `.mp3$` | Items that end with `.mp3` | suffix-exact-match |
|
|
|
|
| `sbtrkt` | Items that match `sbtrkt` | fuzzy-match |
|
|
|
|
| `!rmx` | Items that do not match `rmx` | inverse-fuzzy-match |
|
|
|
|
| `'wild` | Items that include `wild` | exact-match (quoted) |
|
|
|
|
| `!'fire` | Items that do not include `fire` | inverse-exact-match |
|
2013-11-15 06:40:57 -05:00
|
|
|
|
2013-10-24 05:56:33 -04:00
|
|
|
Usage as Vim plugin
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
If you install fzf as a Vim plugin, `:FZF` command will be added.
|
|
|
|
|
|
|
|
```vim
|
2013-11-19 20:31:33 -05:00
|
|
|
" Look for files under current directory
|
2013-10-24 05:56:33 -04:00
|
|
|
:FZF
|
2013-11-19 20:31:33 -05:00
|
|
|
|
|
|
|
" Look for files under your home directory
|
|
|
|
:FZF ~
|
|
|
|
|
|
|
|
" With options
|
|
|
|
:FZF --no-sort -m /tmp
|
2013-10-24 05:56:33 -04:00
|
|
|
```
|
|
|
|
|
2013-11-16 12:41:10 -05:00
|
|
|
You can override the source command which produces input to fzf.
|
2013-10-24 05:56:33 -04:00
|
|
|
|
|
|
|
```vim
|
2013-11-16 12:41:10 -05:00
|
|
|
let g:fzf_source = 'find . -type f'
|
|
|
|
```
|
|
|
|
|
|
|
|
And you can predefine default options to fzf command.
|
|
|
|
|
|
|
|
```vim
|
|
|
|
let g:fzf_options = '--no-color --extended'
|
|
|
|
```
|
|
|
|
|
|
|
|
For more advanced uses, you can call `fzf#run` function as follows.
|
|
|
|
|
|
|
|
```vim
|
|
|
|
:call fzf#run('tabedit', '-m +c')
|
2013-10-24 05:56:33 -04:00
|
|
|
```
|
|
|
|
|
2013-11-02 07:40:25 -04:00
|
|
|
Most of the time, you will prefer native Vim plugins with better integration
|
|
|
|
with Vim. The only reason one might consider using fzf in Vim is its speed. For
|
|
|
|
a very large list of files, fzf is significantly faster and it does not block.
|
|
|
|
|
2013-10-24 05:56:33 -04:00
|
|
|
Useful bash examples
|
|
|
|
--------------------
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
```sh
|
|
|
|
# vimf - Open selected file in Vim
|
2013-10-24 11:40:04 -04:00
|
|
|
vimf() {
|
2013-11-06 06:54:02 -05:00
|
|
|
FILE=$(fzf) && vim "$FILE"
|
2013-10-24 11:40:04 -04:00
|
|
|
}
|
2013-10-22 21:26:55 -04:00
|
|
|
|
|
|
|
# fd - cd to selected directory
|
|
|
|
fd() {
|
2013-11-06 06:54:02 -05:00
|
|
|
DIR=$(find ${1:-*} -path '*/\.*' -prune -o -type d -print 2> /dev/null | fzf) && cd "$DIR"
|
2013-10-22 21:26:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
# fda - including hidden directories
|
|
|
|
fda() {
|
2013-11-06 06:54:02 -05:00
|
|
|
DIR=$(find ${1:-*} -type d 2> /dev/null | fzf) && cd "$DIR"
|
2013-10-22 21:26:55 -04:00
|
|
|
}
|
|
|
|
|
2013-10-24 05:56:33 -04:00
|
|
|
# fh - repeat history
|
|
|
|
fh() {
|
2013-10-25 05:31:16 -04:00
|
|
|
eval $(history | fzf +s | sed 's/ *[0-9]* *//')
|
2013-10-24 05:56:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
# fkill - kill process
|
|
|
|
fkill() {
|
2013-11-09 14:00:27 -05:00
|
|
|
ps -ef | sed 1d | fzf -m | awk '{print $2}' | xargs kill -${1:-9}
|
2013-10-24 05:56:33 -04:00
|
|
|
}
|
2013-11-26 11:00:23 -05:00
|
|
|
```
|
2013-10-24 05:56:33 -04:00
|
|
|
|
2013-11-26 11:00:23 -05:00
|
|
|
bash key bindings
|
|
|
|
-----------------
|
2013-11-01 23:56:43 -04:00
|
|
|
|
2013-11-26 11:00:23 -05:00
|
|
|
```sh
|
|
|
|
# Required to refresh the prompt after fzf
|
2013-10-22 21:26:55 -04:00
|
|
|
bind '"\er": redraw-current-line'
|
2013-11-26 11:00:23 -05:00
|
|
|
|
|
|
|
# CTRL-T - Paste the selected file path into the command line
|
|
|
|
fsel() {
|
|
|
|
find ${1:-*} | fzf -m | while read item; do
|
2013-11-26 20:20:27 -05:00
|
|
|
printf '%q ' "$item"
|
2013-11-26 11:00:23 -05:00
|
|
|
done
|
|
|
|
echo
|
|
|
|
}
|
|
|
|
bind '"\C-t": " \C-u \C-a\C-k$(fsel)\e\C-e\C-y\C-a\C-y\ey\C-h\C-e\er"'
|
2013-11-01 23:56:43 -04:00
|
|
|
|
|
|
|
# CTRL-R - Paste the selected command from history into the command line
|
|
|
|
bind '"\C-r": " \C-e\C-u$(history | fzf +s | sed \"s/ *[0-9]* *//\")\e\C-e\er"'
|
2013-10-22 21:26:55 -04:00
|
|
|
```
|
|
|
|
|
2013-11-08 11:16:39 -05:00
|
|
|
zsh widgets
|
|
|
|
-----------
|
|
|
|
|
|
|
|
```sh
|
2013-11-19 11:29:36 -05:00
|
|
|
# CTRL-T - Paste the selected file path(s) into the command line
|
2013-11-08 11:16:39 -05:00
|
|
|
fzf-file-widget() {
|
2013-11-10 12:13:04 -05:00
|
|
|
local FILES
|
|
|
|
local IFS="
|
|
|
|
"
|
|
|
|
FILES=($(
|
|
|
|
find * -path '*/\.*' -prune \
|
|
|
|
-o -type f -print \
|
|
|
|
-o -type l -print 2> /dev/null | fzf -m))
|
|
|
|
unset IFS
|
|
|
|
FILES=$FILES:q
|
|
|
|
LBUFFER="${LBUFFER%% #} $FILES"
|
2013-11-08 11:16:39 -05:00
|
|
|
zle redisplay
|
|
|
|
}
|
|
|
|
zle -N fzf-file-widget
|
|
|
|
bindkey '^T' fzf-file-widget
|
|
|
|
|
2013-11-10 12:13:04 -05:00
|
|
|
# ALT-C - cd into the selected directory
|
|
|
|
fzf-cd-widget() {
|
2013-11-10 12:57:47 -05:00
|
|
|
cd "${$(find * -path '*/\.*' -prune \
|
|
|
|
-o -type d -print 2> /dev/null | fzf):-.}"
|
2013-11-10 12:13:04 -05:00
|
|
|
zle reset-prompt
|
|
|
|
}
|
|
|
|
zle -N fzf-cd-widget
|
|
|
|
bindkey '\ec' fzf-cd-widget
|
|
|
|
|
2013-11-08 11:16:39 -05:00
|
|
|
# CTRL-R - Paste the selected command from history into the command line
|
|
|
|
fzf-history-widget() {
|
2013-11-10 12:13:04 -05:00
|
|
|
LBUFFER=$(history | fzf +s | sed "s/ *[0-9]* *//")
|
2013-11-08 11:16:39 -05:00
|
|
|
zle redisplay
|
|
|
|
}
|
|
|
|
zle -N fzf-history-widget
|
|
|
|
bindkey '^R' fzf-history-widget
|
|
|
|
```
|
|
|
|
|
2013-11-19 11:29:36 -05:00
|
|
|
Auto-completion (experimental)
|
|
|
|
------------------------------
|
|
|
|
|
|
|
|
Disclaimer: *Auto-completion feature is currently experimental, it can change
|
|
|
|
over time*
|
|
|
|
|
|
|
|
### bash
|
|
|
|
|
2013-11-23 06:09:56 -05:00
|
|
|
Fuzzy completion can be triggered if the word before the cursor ends
|
|
|
|
with the trigger sequence which is by default `**`.
|
|
|
|
|
|
|
|
- `COMMAND [DIRECTORY/][FUZZY_PATTERN]**<TAB>`
|
2013-11-19 11:29:36 -05:00
|
|
|
|
2013-11-19 11:42:57 -05:00
|
|
|
#### Examples
|
|
|
|
|
2013-11-19 11:29:36 -05:00
|
|
|
```sh
|
2013-11-19 11:42:57 -05:00
|
|
|
# Files under current directory
|
|
|
|
# - You can select multiple items with TAB key
|
2013-11-19 11:29:36 -05:00
|
|
|
vim **<TAB>
|
2013-11-19 11:42:57 -05:00
|
|
|
|
|
|
|
# Files under parent directory
|
2013-11-23 06:09:56 -05:00
|
|
|
vim ../**<TAB>
|
|
|
|
|
|
|
|
# Files under parent directory that match `fzf`
|
|
|
|
vim ../fzf**<TAB>
|
2013-11-19 11:42:57 -05:00
|
|
|
|
|
|
|
# Files under your home directory
|
2013-11-19 11:29:36 -05:00
|
|
|
vim ~/**<TAB>
|
|
|
|
|
2013-11-19 11:42:57 -05:00
|
|
|
|
|
|
|
# Directories under current directory (single-selection)
|
2013-11-19 11:29:36 -05:00
|
|
|
cd **<TAB>
|
2013-11-19 11:42:57 -05:00
|
|
|
|
2013-11-23 06:09:56 -05:00
|
|
|
# Directories under ~/github that match `fzf`
|
|
|
|
cd ~/github/fzf**<TAB>
|
2013-11-19 11:29:36 -05:00
|
|
|
```
|
|
|
|
|
2013-11-19 11:42:57 -05:00
|
|
|
#### Settings
|
2013-11-19 11:29:36 -05:00
|
|
|
|
|
|
|
```sh
|
2013-11-19 11:42:57 -05:00
|
|
|
# Use ~~ as the trigger sequence instead of the default **
|
2013-11-19 11:29:36 -05:00
|
|
|
export FZF_COMPLETION_TRIGGER='~~'
|
2013-11-19 11:42:57 -05:00
|
|
|
|
|
|
|
# Options to fzf command
|
|
|
|
export FZF_COMPLETION_OPTS='+c -x'
|
2013-11-19 11:29:36 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
### zsh
|
|
|
|
|
2013-11-19 11:42:57 -05:00
|
|
|
TODO :smiley:
|
|
|
|
|
|
|
|
(Pull requests are appreciated.)
|
2013-11-19 11:29:36 -05:00
|
|
|
|
2013-11-10 05:51:32 -05:00
|
|
|
Tips
|
|
|
|
----
|
|
|
|
|
|
|
|
### Faster startup with `--disable-gems` options
|
|
|
|
|
|
|
|
If you're running Ruby 1.9 or above, you can improve the startup time with
|
|
|
|
`--disable-gems` option to Ruby.
|
|
|
|
|
|
|
|
- `time ruby ~/bin/fzf -h`
|
|
|
|
- 0.077 sec
|
|
|
|
- `time ruby --disable-gems ~/bin/fzf -h`
|
|
|
|
- 0.025 sec
|
|
|
|
|
2013-11-28 23:40:31 -05:00
|
|
|
You can define fzf function with the option as follows:
|
2013-11-10 05:51:32 -05:00
|
|
|
|
|
|
|
```sh
|
2013-11-28 23:40:31 -05:00
|
|
|
fzf() {
|
|
|
|
ruby --disable-gems ~/bin/fzf "$@"
|
|
|
|
}
|
|
|
|
export -f fzf
|
2013-11-10 05:51:32 -05:00
|
|
|
```
|
|
|
|
|
2013-11-28 23:40:31 -05:00
|
|
|
However, this is automatically set up in your .bashrc and .zshrc if you use the
|
|
|
|
bundled [install](https://github.com/junegunn/fzf/blob/master/install) script.
|
2013-11-19 11:29:36 -05:00
|
|
|
|
2013-11-10 05:51:32 -05:00
|
|
|
### Incorrect display on Ruby 1.8
|
|
|
|
|
|
|
|
It is reported that the output of fzf can become unreadable on some terminals
|
|
|
|
when it's running on Ruby 1.8. If you experience the problem, upgrade your Ruby
|
|
|
|
to 1.9 or above. Ruby 1.9 or above is also required for displaying Unicode
|
|
|
|
characters.
|
|
|
|
|
2013-10-22 21:26:55 -04:00
|
|
|
License
|
|
|
|
-------
|
|
|
|
|
|
|
|
MIT
|
|
|
|
|
|
|
|
Author
|
|
|
|
------
|
|
|
|
|
|
|
|
Junegunn Choi
|
|
|
|
|