Compare commits

...

21 Commits

Author SHA1 Message Date
Junegunn Choi
49c752b1f7 [vim] up/down/left/right options to take boolean values
When 1 is given, 50% of the screen width or height will be used as the
default size of the pane.
2015-03-10 12:13:11 +09:00
Junegunn Choi
daa79a6df2 [vim] fzf#run with tmux panes can now return values to the caller
As they're made synchronous with the use of fzf-tmux script
2015-03-10 12:07:32 +09:00
Junegunn Choi
48e0c1e721 Ignore new options in legacy Ruby version 2015-03-10 02:16:32 +09:00
Junegunn Choi
12d81e212f [vim] Use fzf-tmux script for tmux integration 2015-03-10 01:41:35 +09:00
Junegunn Choi
c22e729d9c [fzf-tmux] Apply environment variables 2015-03-09 23:57:17 +09:00
Junegunn Choi
2b8a1c0d70 Update README - Homebrew instruction and fzf-tmux options 2015-03-09 23:40:43 +09:00
Junegunn Choi
e4b56b9702 Merge pull request #138 from junegunn/fzf-tmux-swap-pane
[fzf-tmux] Allow opening fzf on any position (up/down/left/right)
2015-03-09 23:28:53 +09:00
Junegunn Choi
789a474b28 [fzf-tmux] Allow opening fzf on any position (-u/-d/-l/-r)
The previous -w and -h will be synonyms for -r and -d respectively.
2015-03-09 12:49:26 +09:00
Junegunn Choi
fb2959c514 [fzf-tmux] Fix duplicate arguments to fzf
fzf-tmux -w -q q
fzf-tmux -w -- -q q
2015-03-08 16:40:48 +09:00
Junegunn Choi
62a28468a7 [fzf-tmux] Fix -- 2015-03-08 16:36:37 +09:00
Junegunn Choi
23dba99eda [fzf-tmux] Allow -w / -h without size argument 2015-03-08 15:08:27 +09:00
Junegunn Choi
5f62d224b0 Fix fzf-tmux script (bash 3.2 compatibility) 2015-03-07 10:07:36 +09:00
Junegunn Choi
6728870071 Merge pull request #136 from junegunn/fzf-tmux
Add fzf-tmux script
2015-03-07 10:01:23 +09:00
Junegunn Choi
87c71a3ea6 Increase timeout in test cases 2015-03-07 09:53:54 +09:00
Junegunn Choi
06ab399497 Improve how vim plugin finds fzf executable
This avoids the problem in which :FZF command silently fails when fzf
executable cannot be found in $PATH of the hosting tmux server.
2015-03-07 09:48:56 +09:00
Junegunn Choi
f7b52d2541 Use absolute path of fzf when splitting tmux window 2015-03-07 09:29:16 +09:00
Junegunn Choi
c111af0ed2 Use the term pane instead of split when not ambiguous
/cc @Tranquility
2015-03-07 09:08:41 +09:00
Junegunn Choi
07e2bd673e Update README 2015-03-06 18:57:36 +09:00
Junegunn Choi
e4ce64d10b Add fzf-tmux script 2015-03-06 18:51:50 +09:00
Junegunn Choi
5f3326a888 Deprecation alert 2015-03-06 13:21:55 +09:00
Junegunn Choi
1304428003 Update bash completion *for* fzf 2015-03-06 10:42:38 +09:00
6 changed files with 281 additions and 221 deletions

191
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.
@@ -52,10 +53,10 @@ On OS X, you can use [Homebrew](http://brew.sh/) to install fzf.
brew install fzf brew install fzf
# Install shell extensions - this should be done whenever fzf is updated # Install shell extensions - this should be done whenever fzf is updated
/usr/local/Cellar/fzf/$(fzf --version)/install $(brew info fzf | grep /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,27 @@ 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 [-u|-d [HEIGHT[%]]] [-l|-r [WIDTH[%]]] [--] [FZF OPTIONS]
# (-[udlr]: up/down/left/right)
# select git branches in horizontal split below (15 lines)
git branch | fzf-tmux -d 15
# select multiple words in vertical split on the left (20% of screen width)
cat /usr/share/dict/words | fzf-tmux -l 20% --multi --reverse
```
It will still work even when you're not on tmux, silently ignoring `-[udlr]`
options, so you can invariably use `fzf-tmux` in your scripts.
Fuzzy completion for bash
-------------------------
#### Files and directories #### Files and directories
@@ -300,18 +235,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 +278,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.
@@ -357,18 +286,17 @@ of the selected items.
`fzf#run()` may take an options-dictionary: `fzf#run()` may take an options-dictionary:
| Option name | Type | Description | | Option name | Type | Description |
| --------------- | ------------- | ------------------------------------------------------------------ | | -------------------------- | ------------- | ---------------------------------------------------------------- |
| `source` | string | External command to generate input to fzf (e.g. `find .`) | | `source` | string | External command to generate input to fzf (e.g. `find .`) |
| `source` | list | Vim list as input to fzf | | `source` | list | Vim list as input to fzf |
| `sink` | string | Vim command to handle the selected item (e.g. `e`, `tabe`) | | `sink` | string | Vim command to handle the selected item (e.g. `e`, `tabe`) |
| `sink` | funcref | Reference to function to process each selected item | | `sink` | funcref | Reference to function to process each selected item |
| `options` | string | Options to fzf | | `options` | string | Options to fzf |
| `dir` | string | Working directory | | `dir` | string | Working directory |
| `tmux_width` | number/string | Use tmux vertical split with the given height (e.g. `20`, `50%`) | | `up`/`down`/`left`/`right` | number/string | Use tmux pane with the given size (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.
@@ -394,7 +322,7 @@ nnoremap <silent> <Leader>C :call fzf#run({
\ "substitute(fnamemodify(v:val, ':t'), '\\..\\{-}$', '', '')"), \ "substitute(fnamemodify(v:val, ':t'), '\\..\\{-}$', '', '')"),
\ 'sink': 'colo', \ 'sink': 'colo',
\ 'options': '+m', \ 'options': '+m',
\ 'tmux_width': 20, \ 'left': 20,
\ 'launcher': 'xterm -geometry 20x30 -e bash -ic %s' \ 'launcher': 'xterm -geometry 20x30 -e bash -ic %s'
\ })<CR> \ })<CR>
``` ```
@@ -419,18 +347,21 @@ nnoremap <silent> <Leader><Enter> :call fzf#run({
\ 'source': reverse(BufList()), \ 'source': reverse(BufList()),
\ 'sink': function('BufOpen'), \ 'sink': function('BufOpen'),
\ 'options': '+m', \ 'options': '+m',
\ 'tmux_height': '40%' \ 'down': '40%'
\ })<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:

125
bin/fzf-tmux Executable file
View File

@@ -0,0 +1,125 @@
#!/usr/bin/env bash
# fzf-tmux: starts fzf in a tmux pane
# usage: fzf-tmux [-u|-d [HEIGHT[%]]] [-l|-r [WIDTH[%]]] [--] [FZF OPTIONS]
args=()
opt=""
skip=""
swap=""
close=""
term=""
while [ $# -gt 0 ]; do
arg="$1"
case "$arg" in
-)
term=1
;;
-w*|-h*|-d*|-u*|-r*|-l*)
if [ -n "$skip" ]; then
args+=("$1")
shift
continue
fi
if [[ "$arg" =~ ^.[lrw] ]]; then
opt="-h"
if [[ "$arg" =~ ^.l ]]; then
opt="$opt -d"
swap="; swap-pane -D ; select-pane -L"
close="; tmux swap-pane -D"
fi
else
opt=""
if [[ "$arg" =~ ^.u ]]; then
opt="$opt -d"
swap="; swap-pane -D ; select-pane -U"
close="; tmux swap-pane -D"
fi
fi
if [ ${#arg} -gt 2 ]; then
size="${arg:2}"
else
shift
if [[ "$1" =~ ^[0-9]+%?$ ]]; then
size="$1"
else
[ -n "$1" -a "$1" != "--" ] && args+=("$1")
shift
continue
fi
fi
if [[ "$size" =~ %$ ]]; then
size=${size:0:((${#size}-1))}
if [ -n "$swap" ]; then
opt="$opt -p $(( 100 - size ))"
else
opt="$opt -p $size"
fi
else
if [ -n "$swap" ]; then
if [[ "$arg" =~ ^.l ]]; then
[ -n "$COLUMNS" ] && max=$COLUMNS || max=$(tput cols)
else
[ -n "$LINES" ] && max=$LINES || max=$(tput lines)
fi
size=$(( max - size ))
[ $size -lt 0 ] && size=0
opt="$opt -l $size"
else
opt="$opt -l $size"
fi
fi
;;
--)
# "--" can be used to separate fzf-tmux options from fzf options to
# avoid conflicts
skip=1
;;
*)
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"
envs="FZF_DEFAULT_OPTS=$(printf %q "$FZF_DEFAULT_OPTS") FZF_DEFAULT_COMMAND=$(printf %q "$FZF_DEFAULT_COMMAND")"
mkfifo $fifo2
mkfifo $fifo3
if [ -n "$term" -o -t 0 ]; then
tmux set-window-option -q synchronize-panes off \;\
split-window $opt "$envs"' sh -c "'$fzf' '"$fzf_args"' > '$fifo2'; echo \$? > '$fifo3' '"$close"'"' $swap
else
mkfifo $fifo1
tmux set-window-option -q synchronize-panes off \;\
split-window $opt "$envs"' sh -c "'$fzf' '"$fzf_args"' < '$fifo1' > '$fifo2'; echo \$? > '$fifo3' '"$close"'"' $swap
cat <&0 > $fifo1 &
fi
cat $fifo2
[ "$(cat $fifo3)" = '0' ]

4
fzf
View File

@@ -8,6 +8,8 @@
# /_/ /___/_/ Fuzzy finder for your shell # /_/ /___/_/ Fuzzy finder for your shell
# #
# Version: 0.8.9 (Dec 24, 2014) # Version: 0.8.9 (Dec 24, 2014)
# Deprecation alert:
# This script is no longer maintained. Use the new Go version.
# #
# Author: Junegunn Choi # Author: Junegunn Choi
# URL: https://github.com/junegunn/fzf # URL: https://github.com/junegunn/fzf
@@ -198,6 +200,8 @@ class FZF
when '--no-print-query' then @print_query = false when '--no-print-query' then @print_query = false
when '-e', '--extended-exact' then @extended = :exact when '-e', '--extended-exact' then @extended = :exact
when '+e', '--no-extended-exact' then @extended = nil when '+e', '--no-extended-exact' then @extended = nil
when '--tac', '--sync'
# XXX
else else
usage 1, "illegal option: #{o}" usage 1, "illegal option: #{o}"
end end

View File

@@ -14,17 +14,17 @@ _fzf_orig_completion_filter() {
} }
_fzf_opts_completion() { _fzf_opts_completion() {
local cur prev opts local cur opts
COMPREPLY=() COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}" cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts=" opts="
-x --extended -x --extended
-e --extended-exact -e --extended-exact
-i +i -i +i
-n --nth -n --nth
-d --delimiter -d --delimiter
-s --sort +s +s --no-sort
--tac
-m --multi -m --multi
--no-mouse --no-mouse
+c --no-color +c --no-color
@@ -36,14 +36,8 @@ _fzf_opts_completion() {
-1 --select-1 -1 --select-1
-0 --exit-0 -0 --exit-0
-f --filter -f --filter
--print-query" --print-query
--sync"
case "${prev}" in
--sort|-s)
COMPREPLY=( $(compgen -W "$(seq 2000 1000 10000)" -- ${cur}) )
return 0
;;
esac
if [[ ${cur} =~ ^-|\+ ]]; then if [[ ${cur} =~ ^-|\+ ]]; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )

View File

@@ -21,29 +21,35 @@
" 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.
let s:min_tmux_width = 10
let s:min_tmux_height = 3
let s:default_tmux_height = '40%' let s:default_tmux_height = '40%'
let s:launcher = 'xterm -e bash -ic %s' let s:launcher = 'xterm -e bash -ic %s'
let s:fzf_go = expand('<sfile>:h:h').'/bin/fzf' let s:fzf_go = expand('<sfile>:h:h').'/bin/fzf'
let s:fzf_rb = expand('<sfile>:h:h').'/fzf' let s:fzf_rb = expand('<sfile>:h:h').'/fzf'
let s:fzf_tmux = expand('<sfile>:h:h').'/bin/fzf-tmux'
let s:cpo_save = &cpo let s:cpo_save = &cpo
set cpo&vim set cpo&vim
function! s:fzf_exec() function! s:fzf_exec()
if !exists('s:exec') if !exists('s:exec')
if executable(s:fzf_go)
let s:exec = s:fzf_go
else
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') call system('type fzf')
if v:shell_error if v:shell_error
let s:exec = executable(s:fzf_go) ? throw 'fzf executable not found'
\ s:fzf_go : (executable(s:fzf_rb) ? s:fzf_rb : '')
else else
let s:exec = 'fzf' let s:exec = 'fzf'
endif endif
return s:fzf_exec() endif
elseif empty(s:exec) endif
unlet s:exec return s:exec
throw 'fzf executable not found'
else else
return s:exec return s:exec
endif endif
@@ -59,7 +65,7 @@ function! s:tmux_enabled()
endif endif
let s:tmux = 0 let s:tmux = 0
if exists('$TMUX') if exists('$TMUX') && executable(s:fzf_tmux)
let output = system('tmux -V') let output = system('tmux -V')
let s:tmux = !v:shell_error && output >= 'tmux 1.7' let s:tmux = !v:shell_error && output >= 'tmux 1.7'
endif endif
@@ -74,8 +80,23 @@ function! s:escape(path)
return substitute(a:path, ' ', '\\ ', 'g') return substitute(a:path, ' ', '\\ ', 'g')
endfunction endfunction
" Upgrade legacy options
function! s:upgrade(dict)
let copy = copy(a:dict)
if has_key(copy, 'tmux')
let copy.down = remove(copy, 'tmux')
endif
if has_key(copy, 'tmux_height')
let copy.down = remove(copy, 'tmux_height')
endif
if has_key(copy, 'tmux_width')
let copy.right = remove(copy, 'tmux_width')
endif
return copy
endfunction
function! fzf#run(...) abort function! fzf#run(...) abort
let dict = exists('a:1') ? a:1 : {} let dict = exists('a:1') ? s:upgrade(a:1) : {}
let temps = { 'result': tempname() } let temps = { 'result': tempname() }
let optstr = get(dict, 'options', '') let optstr = get(dict, 'options', '')
try try
@@ -99,26 +120,47 @@ function! fzf#run(...) abort
else else
let prefix = '' let prefix = ''
endif endif
let command = prefix.fzf_exec.' '.optstr.' > '.temps.result let split = s:tmux_enabled() && s:tmux_splittable(dict)
let command = prefix.(split ? s:fzf_tmux(dict) : fzf_exec).' '.optstr.' > '.temps.result
if s:tmux_enabled() && s:tmux_splittable(dict) if split
return s:execute_tmux(dict, command, temps) return s:execute_tmux(dict, command, temps)
else else
return s:execute(dict, command, temps) return s:execute(dict, command, temps)
endif endif
endfunction endfunction
function! s:present(dict, ...)
for key in a:000
if !empty(get(a:dict, key, ''))
return 1
endif
endfor
return 0
endfunction
function! s:fzf_tmux(dict)
let size = ''
for o in ['up', 'down', 'left', 'right']
if s:present(a:dict, o)
let size = '-'.o[0].(a:dict[o] == 1 ? '' : a:dict[o])
endif
endfor
return printf('LINES=%d COLUMNS=%d %s %s %s --',
\ &lines, &columns, s:fzf_tmux, size, (has_key(a:dict, 'source') ? '' : '-'))
endfunction
function! s:tmux_splittable(dict) function! s:tmux_splittable(dict)
return return s:present(a:dict, 'up', 'down', 'left', 'right')
\ min([&columns, get(a:dict, 'tmux_width', 0)]) >= s:min_tmux_width ||
\ min([&lines, get(a:dict, 'tmux_height', get(a:dict, 'tmux', 0))]) >= s:min_tmux_height
endfunction endfunction
function! s:pushd(dict) function! s:pushd(dict)
if !empty(get(a:dict, 'dir', '')) if s:present(a:dict, 'dir')
let a:dict.prev_dir = getcwd() let a:dict.prev_dir = getcwd()
execute 'chdir '.s:escape(a:dict.dir) execute 'chdir '.s:escape(a:dict.dir)
return 1
endif endif
return 0
endfunction endfunction
function! s:popd(dict) function! s:popd(dict)
@@ -146,7 +188,7 @@ function! s:execute(dict, command, temps)
endif endif
return [] return []
else else
return s:callback(a:dict, a:temps, 0) return s:callback(a:dict, a:temps)
endif endif
endfunction endfunction
@@ -159,58 +201,20 @@ function! s:env_var(name)
endfunction endfunction
function! s:execute_tmux(dict, command, temps) function! s:execute_tmux(dict, command, temps)
let command = s:env_var('FZF_DEFAULT_OPTS').s:env_var('FZF_DEFAULT_COMMAND').a:command let command = a:command
if !empty(get(a:dict, 'dir', '')) if s:pushd(a:dict)
" -c '#{pane_current_path}' is only available on tmux 1.9 or above
let command = 'cd '.s:escape(a:dict.dir).' && '.command let command = 'cd '.s:escape(a:dict.dir).' && '.command
endif endif
let splitopt = '-v' call system(command)
if has_key(a:dict, 'tmux_width') return s:callback(a:dict, a:temps)
let splitopt = '-h'
let size = a:dict.tmux_width
else
let size = get(a:dict, 'tmux_height', get(a:dict, 'tmux'))
endif
if type(size) == 1 && size =~ '%$'
let sizeopt = '-p '.size[0:-2]
else
let sizeopt = '-l '.size
endif
let s:pane = substitute(
\ system(
\ printf(
\ 'tmux split-window %s %s -P -F "#{pane_id}" %s',
\ splitopt, sizeopt, s:shellesc(command))), '\n', '', 'g')
let s:dict = a:dict
let s:temps = a:temps
augroup fzf_tmux
autocmd!
autocmd VimResized * nested call s:tmux_check()
augroup END
endfunction endfunction
function! s:tmux_check() function! s:callback(dict, temps)
let panes = split(system('tmux list-panes -a -F "#{pane_id}"'), '\n')
if index(panes, s:pane) < 0
augroup fzf_tmux
autocmd!
augroup END
call s:callback(s:dict, s:temps, 1)
redraw
endif
endfunction
function! s:callback(dict, temps, cd)
if !filereadable(a:temps.result) if !filereadable(a:temps.result)
let lines = [] let lines = []
else else
if a:cd | call s:pushd(a:dict) | endif
let lines = readfile(a:temps.result) let lines = readfile(a:temps.result)
if has_key(a:dict, 'sink') if has_key(a:dict, 'sink')
for line in lines for line in lines
@@ -239,7 +243,7 @@ function! s:cmd(bang, ...) abort
let opts.dir = remove(args, -1) let opts.dir = remove(args, -1)
endif endif
if !a:bang if !a:bang
let opts.tmux = get(g:, 'fzf_tmux_height', s:default_tmux_height) let opts.down = get(g:, 'fzf_tmux_height', s:default_tmux_height)
endif endif
call fzf#run(extend({ 'sink': 'e', 'options': join(args) }, opts)) call fzf#run(extend({ 'sink': 'e', 'options': join(args) }, opts))
endfunction endfunction

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]