m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-18 08:13:40 -05:00

Merge pull request #136 from junegunn/fzf-tmux

Add fzf-tmux script
This commit is contained in:
Junegunn Choi
2015-03-07 10:01:23 +09:00
4 changed files with 144 additions and 134 deletions

179
README.md
View File

@@ -14,16 +14,17 @@ Installation
fzf project consists of the followings: fzf project consists of the followings:
- `fzf` executable - `fzf` executable
- `fzf-tmux` script for launching fzf in a tmux pane
- Shell extensions - Shell extensions
- Key bindings (`CTRL-T`, `CTRL-R`, and `ALT-C`) (bash, zsh, fish) - Key bindings (`CTRL-T`, `CTRL-R`, and `ALT-C`) (bash, zsh, fish)
- Fuzzy auto-completion (bash) - Fuzzy auto-completion (bash only)
You can [download fzf executable][bin] alone, but it's recommended that you You can [download fzf executable][bin] alone, but it's recommended that you
install the extra stuff using the attached install script. install the extra stuff using the attached install script.
[bin]: https://github.com/junegunn/fzf-bin/releases [bin]: https://github.com/junegunn/fzf-bin/releases
### Using git (recommended) #### Using git (recommended)
Clone this repository and run Clone this repository and run
[install](https://github.com/junegunn/fzf/blob/master/install) script. [install](https://github.com/junegunn/fzf/blob/master/install) script.
@@ -33,7 +34,7 @@ git clone https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install ~/.fzf/install
``` ```
### Using curl #### Using curl
In case you don't have git installed: In case you don't have git installed:
@@ -44,7 +45,7 @@ curl -L https://github.com/junegunn/fzf/archive/master.tar.gz |
~/.fzf/install ~/.fzf/install
``` ```
### Using Homebrew #### Using Homebrew
On OS X, you can use [Homebrew](http://brew.sh/) to install fzf. On OS X, you can use [Homebrew](http://brew.sh/) to install fzf.
@@ -55,7 +56,7 @@ brew install fzf
/usr/local/Cellar/fzf/$(fzf --version)/install /usr/local/Cellar/fzf/$(fzf --version)/install
``` ```
### Install as Vim plugin #### Install as Vim plugin
Once you have cloned the repository, add the following line to your .vimrc. Once you have cloned the repository, add the following line to your .vimrc.
@@ -63,7 +64,8 @@ Once you have cloned the repository, add the following line to your .vimrc.
set rtp+=~/.fzf set rtp+=~/.fzf
``` ```
Or you can have [vim-plug](https://github.com/junegunn/vim-plug) manage fzf: Or you can have [vim-plug](https://github.com/junegunn/vim-plug) manage fzf
(recommended):
```vim ```vim
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': 'yes \| ./install' } Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': 'yes \| ./install' }
@@ -72,48 +74,6 @@ Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': 'yes \| ./install' }
Usage Usage
----- -----
```
usage: fzf [options]
Search mode
-x, --extended Extended-search mode
-e, --extended-exact Extended-search mode (exact match)
-i Case-insensitive match (default: smart-case match)
+i Case-sensitive match
-n, --nth=N[,..] Comma-separated list of field index expressions
for limiting search scope. Each can be a non-zero
integer or a range expression ([BEGIN]..[END])
--with-nth=N[,..] Transform the item using index expressions for search
-d, --delimiter=STR Field delimiter regex for --nth (default: AWK-style)
Search result
+s, --no-sort Do not sort the result
--tac Reverse the order of the input
(e.g. 'history | fzf --tac --no-sort')
Interface
-m, --multi Enable multi-select with tab/shift-tab
--no-mouse Disable mouse
+c, --no-color Disable colors
+2, --no-256 Disable 256-color
--black Use black background
--reverse Reverse orientation
--prompt=STR Input prompt (default: '> ')
Scripting
-q, --query=STR Start the finder with the given query
-1, --select-1 Automatically select the only match
-0, --exit-0 Exit immediately when there's no match
-f, --filter=STR Filter mode. Do not start interactive finder.
--print-query Print query as the first line
--sync Synchronous search for multi-staged filtering
(e.g. 'fzf --multi | fzf --sync')
Environment variables
FZF_DEFAULT_COMMAND Default command to use when input is tty
FZF_DEFAULT_OPTS Defaults options. (e.g. '-x -m')
```
fzf will launch curses-based finder, read the list from STDIN, and write the fzf will launch curses-based finder, read the list from STDIN, and write the
selected item to STDOUT. selected item to STDOUT.
@@ -129,27 +89,16 @@ files excluding hidden ones. (You can override the default command with
vim $(fzf) vim $(fzf)
``` ```
### Keys #### Using the finder
Use CTRL-J and CTRL-K (or CTRL-N and CTRL-P) to change the selection, press - `CTRL-J` / `CTRL-K` (or `CTRL-N` / `CTRL-P)` to move cursor up and down
enter key to select the item. CTRL-C, CTRL-G, or ESC will terminate the finder. - `Enter` key to select the item, `CTRL-C` / `CTRL-G` / `ESC` to exit
- On multi-select mode (`-m`), `TAB` and `Shift-TAB` to mark multiple items
- Emacs style key bindings
- Mouse: scroll, click, double-click; shift-click and shift-scroll on
multi-select mode
The following readline key bindings should also work as expected. #### Extended-search mode
- CTRL-A / CTRL-E
- CTRL-B / CTRL-F
- CTRL-H / CTRL-D
- CTRL-W / CTRL-U / CTRL-Y
- ALT-B / ALT-F
If you enable multi-select mode with `-m` option, you can select multiple items
with TAB or Shift-TAB key.
You can also use mouse. Double-click on an item to select it or shift-click (or
ctrl-click) to select multiple items. Use mouse wheel to move the cursor up and
down.
### Extended-search mode
With `-x` or `--extended` option, fzf will start in "extended-search mode". With `-x` or `--extended` option, fzf will start in "extended-search mode".
@@ -168,40 +117,12 @@ such as: `^music .mp3$ sbtrkt !rmx`
If you don't need fuzzy matching and do not wish to "quote" every word, start If you don't need fuzzy matching and do not wish to "quote" every word, start
fzf with `-e` or `--extended-exact` option. fzf with `-e` or `--extended-exact` option.
Useful examples Examples
--------------- --------
```sh Many useful examples can be found on [the wiki
# fe [FUZZY PATTERN] - Open the selected file with the default editor page](https://github.com/junegunn/fzf/wiki/examples). Feel free to add your
# - Bypass fuzzy finder if there's only one match (--select-1) own as well.
# - Exit if there's no match (--exit-0)
fe() {
local file
file=$(fzf --query="$1" --select-1 --exit-0)
[ -n "$file" ] && ${EDITOR:-vim} "$file"
}
# fd - cd to selected directory
fd() {
local dir
dir=$(find ${1:-*} -path '*/\.*' -prune \
-o -type d -print 2> /dev/null | fzf +m) &&
cd "$dir"
}
# fh - repeat history
fh() {
eval $(([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed 's/ *[0-9]* *//')
}
# fkill - kill process
fkill() {
ps -ef | sed 1d | fzf -m | awk '{print $2}' | xargs kill -${1:-9}
}
```
For more examples, see [the wiki
page](https://github.com/junegunn/fzf/wiki/examples).
Key bindings for command line Key bindings for command line
----------------------------- -----------------------------
@@ -225,13 +146,26 @@ If you want to customize the key bindings, consider editing the
installer-generated source code: `~/.fzf.bash`, `~/.fzf.zsh`, and installer-generated source code: `~/.fzf.bash`, `~/.fzf.zsh`, and
`~/.config/fish/functions/fzf_key_bindings.fish`. `~/.config/fish/functions/fzf_key_bindings.fish`.
Auto-completion `fzf-tmux` script
--------------- -----------------
Disclaimer: *Auto-completion feature is currently experimental, it can change [fzf-tmux](bin/fzf-tmux) is a bash script that opens fzf in a tmux pane.
over time*
### bash ```sh
# usage: fzf-tmux [-h HEIGHT[%]] [-w WIDTH[%]] [--] [FZF OPTIONS]
# select git branches in horizontal split (15 lines)
git branch | fzf-tmux -h 15
# select multiple words in vertical split (20% of screen width)
cat /usr/share/dict/words | fzf-tmux -w 20% --multi
```
It will still work even when you're not on tmux, silently ignoring `-h` and
`-w` options, so you can invariably use `fzf-tmux` in your scripts.
Fuzzy completion for bash
-------------------------
#### Files and directories #### Files and directories
@@ -300,18 +234,12 @@ export FZF_COMPLETION_TRIGGER='~~'
export FZF_COMPLETION_OPTS='+c -x' export FZF_COMPLETION_OPTS='+c -x'
``` ```
### zsh
TODO :smiley:
(Pull requests are appreciated.)
Usage as Vim plugin Usage as Vim plugin
------------------- -------------------
(Note: To use fzf in GVim, an external terminal emulator is required.) (Note: To use fzf in GVim, an external terminal emulator is required.)
### `:FZF[!]` #### `:FZF[!]`
If you have set up fzf for Vim, `:FZF` command will be added. If you have set up fzf for Vim, `:FZF` command will be added.
@@ -349,7 +277,7 @@ Refer to the [this wiki
page](https://github.com/junegunn/fzf/wiki/fzf-with-MacVim-and-iTerm2) to see page](https://github.com/junegunn/fzf/wiki/fzf-with-MacVim-and-iTerm2) to see
how to set up. how to set up.
### `fzf#run([options])` #### `fzf#run([options])`
For more advanced uses, you can call `fzf#run()` function which returns the list For more advanced uses, you can call `fzf#run()` function which returns the list
of the selected items. of the selected items.
@@ -368,7 +296,7 @@ of the selected items.
| `tmux_height` | number/string | Use tmux horizontal split with the given height (e.g. `20`, `50%`) | | `tmux_height` | number/string | Use tmux horizontal split with the given height (e.g. `20`, `50%`) |
| `launcher` | string | External terminal emulator to start fzf with (Only used in GVim) | | `launcher` | string | External terminal emulator to start fzf with (Only used in GVim) |
#### Examples ##### Examples
If `sink` option is not given, `fzf#run` will simply return the list. If `sink` option is not given, `fzf#run` will simply return the list.
@@ -423,14 +351,17 @@ nnoremap <silent> <Leader><Enter> :call fzf#run({
\ })<CR> \ })<CR>
``` ```
### Articles More examples can be found on [the wiki
page](https://github.com/junegunn/fzf/wiki/Examples-(vim)).
#### Articles
- [fzf+vim+tmux](http://junegunn.kr/2014/04/fzf+vim+tmux) - [fzf+vim+tmux](http://junegunn.kr/2014/04/fzf+vim+tmux)
Tips Tips
---- ----
### Rendering issues #### Rendering issues
If you have any rendering issues, check the followings: If you have any rendering issues, check the followings:
@@ -444,7 +375,7 @@ If you have any rendering issues, check the followings:
`FZF_DEFAULT_OPTS` for further convenience. `FZF_DEFAULT_OPTS` for further convenience.
4. If you still have problem, try `--no-256` option or even `--no-color`. 4. If you still have problem, try `--no-256` option or even `--no-color`.
### Respecting `.gitignore`, `.hgignore`, and `svn:ignore` #### Respecting `.gitignore`, `.hgignore`, and `svn:ignore`
[ag](https://github.com/ggreer/the_silver_searcher) or [ag](https://github.com/ggreer/the_silver_searcher) or
[pt](https://github.com/monochromegane/the_platinum_searcher) will do the [pt](https://github.com/monochromegane/the_platinum_searcher) will do the
@@ -461,7 +392,7 @@ export FZF_DEFAULT_COMMAND='ag -l -g ""'
fzf fzf
``` ```
### `git ls-tree` for fast traversal #### `git ls-tree` for fast traversal
If you're running fzf in a large git repository, `git ls-tree` can boost up the If you're running fzf in a large git repository, `git ls-tree` can boost up the
speed of the traversal. speed of the traversal.
@@ -481,10 +412,12 @@ fzf() {
} }
``` ```
### Using fzf with tmux splits #### Using fzf with tmux panes
It isn't too hard to write your own fzf-tmux combo like the default The supplied [fzf-tmux](bin/fzf-tmux) script should suffice in most of the
CTRL-T key binding. (Or is it?) cases, but if you want to be able to update command line like the default
`CTRL-T` key binding, you'll have to use `send-keys` command of tmux. The
following example will show you how it can be done.
```sh ```sh
# This is a helper function that splits the current pane to start the given # This is a helper function that splits the current pane to start the given
@@ -514,7 +447,7 @@ fzf_tmux_dir() {
bind '"\C-x\C-d": "$(fzf_tmux_dir)\e\C-e"' bind '"\C-x\C-d": "$(fzf_tmux_dir)\e\C-e"'
``` ```
### Fish shell #### Fish shell
It's [a known bug of fish](https://github.com/fish-shell/fish-shell/issues/1362) It's [a known bug of fish](https://github.com/fish-shell/fish-shell/issues/1362)
that it doesn't allow reading from STDIN in command substitution, which means that it doesn't allow reading from STDIN in command substitution, which means
@@ -537,7 +470,7 @@ function fe
end end
``` ```
### Handling UTF-8 NFD paths on OSX #### Handling UTF-8 NFD paths on OSX
Use iconv to convert NFD paths to NFC: Use iconv to convert NFD paths to NFC:

70
bin/fzf-tmux Executable file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env bash
# fzf-tmux: starts fzf in a tmux pane
# usage: fzf-tmux [-h HEIGHT[%]] [-w WIDTH[%]] [--] [FZF OPTIONS]
args=()
opt=""
while [ $# -gt 0 ]; do
arg="$1"
case "$arg" in
-w*|-h*)
if [ ${#arg} -gt 2 ]; then
size="${arg:2}"
else
shift
size="$1"
fi
[[ "$arg" =~ ^-w ]] && opt="-h"
[[ "$size" =~ %$ ]] && opt="$opt -p ${size:0:-1}" ||
opt="$opt -l $size"
;;
--)
# "--" can be used to separate fzf-tmux options from fzf options to
# avoid conflicts
break
;;
*)
args+=("$1")
;;
esac
shift
done
if [ -z "$TMUX_PANE" ]; then
fzf "${args[@]}"
exit $?
fi
set -e
# Build arguments to fzf
[ ${#args[@]} -gt 0 ] && fzf_args=$(printf '\\"%s\\" ' "${args[@]}"; echo '')
# Clean up named pipes on exit
id=$RANDOM
fifo1=/tmp/fzf-fifo1-$id
fifo2=/tmp/fzf-fifo2-$id
fifo3=/tmp/fzf-fifo3-$id
cleanup() {
rm -f $fifo1 $fifo2 $fifo3
}
trap cleanup EXIT SIGINT SIGTERM
fail() {
>&2 echo "$1"
exit 1
}
fzf=$(which fzf 2> /dev/null) || fail "fzf executable not found"
mkfifo $fifo2
mkfifo $fifo3
if [ -t 0 ]; then
tmux split-window $opt 'sh -c "'$fzf' '"$fzf_args"' > '$fifo2'; echo \$? > '$fifo3'"'
else
mkfifo $fifo1
tmux split-window $opt 'sh -c "'$fzf' '"$fzf_args"' < '$fifo1' > '$fifo2'; echo \$? > '$fifo3'"'
cat <&0 > $fifo1 &
fi
cat $fifo2
[ "$(cat $fifo3)" = '0' ]

View File

@@ -33,17 +33,24 @@ set cpo&vim
function! s:fzf_exec() function! s:fzf_exec()
if !exists('s:exec') if !exists('s:exec')
call system('type fzf') if executable(s:fzf_go)
if v:shell_error let s:exec = s:fzf_go
let s:exec = executable(s:fzf_go) ?
\ s:fzf_go : (executable(s:fzf_rb) ? s:fzf_rb : '')
else else
let s:exec = 'fzf' let path = split(system('which fzf 2> /dev/null'), '\n')
if !v:shell_error && !empty(path)
let s:exec = path[0]
elseif executable(s:fzf_rb)
let s:exec = s:fzf_rb
else
call system('type fzf')
if v:shell_error
throw 'fzf executable not found'
else
let s:exec = 'fzf'
endif
endif
endif endif
return s:fzf_exec() return s:exec
elseif empty(s:exec)
unlet s:exec
throw 'fzf executable not found'
else else
return s:exec return s:exec
endif endif

View File

@@ -138,7 +138,7 @@ class Tmux
end end
private private
def defaults opts def defaults opts
{ timeout: 5, pane: 0 }.merge(opts) { timeout: 10, pane: 0 }.merge(opts)
end end
def wait opts = {} def wait opts = {}
@@ -209,7 +209,7 @@ class TestGoFZF < TestBase
def test_vanilla def test_vanilla
tmux.send_keys "seq 1 100000 | #{fzf}", :Enter tmux.send_keys "seq 1 100000 | #{fzf}", :Enter
tmux.until(timeout: 10) { |lines| tmux.until(timeout: 20) { |lines|
lines.last =~ /^>/ && lines[-2] =~ /^ 100000/ } lines.last =~ /^>/ && lines[-2] =~ /^ 100000/ }
lines = tmux.capture lines = tmux.capture
assert_equal ' 2', lines[-4] assert_equal ' 2', lines[-4]