Merge pull request #6 from junegunn/completion

Prototype implementation of bash auto-completion
This commit is contained in:
Junegunn Choi 2013-11-19 08:44:30 -08:00
commit a9fd496691
4 changed files with 242 additions and 20 deletions

View File

@ -16,8 +16,24 @@ fzf requires Ruby (>= 1.8.5).
Installation Installation
------------ ------------
Download [fzf executable](https://raw.github.com/junegunn/fzf/master/fzf) and ### Using install script
put it somewhere in your search $PATH.
Clone this repository and run
[install](https://github.com/junegunn/fzf/blob/master/install) script.
```sh
git clone https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
```
The script will add an alias to fzf and auto-completion support to your
`.bashrc` and `.zshrc`.
### 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.
```sh ```sh
mkdir -p ~/bin mkdir -p ~/bin
@ -25,20 +41,6 @@ wget https://raw.github.com/junegunn/fzf/master/fzf -O ~/bin/fzf
chmod +x ~/bin/fzf chmod +x ~/bin/fzf
``` ```
Or you can just clone this repository and run
[install](https://github.com/junegunn/fzf/blob/master/install) script.
```sh
git clone https://github.com/junegunn/fzf.git
fzf/install
```
Make sure that ~/bin is included in $PATH.
```sh
export PATH=$PATH:~/bin
```
### Install as Ruby gem ### Install as Ruby gem
fzf can be installed as a Ruby gem fzf can be installed as a Ruby gem
@ -215,7 +217,7 @@ zsh widgets
----------- -----------
```sh ```sh
# CTRL-T - Paste the selected file(s) path into the command line # CTRL-T - Paste the selected file path(s) into the command line
fzf-file-widget() { fzf-file-widget() {
local FILES local FILES
local IFS=" local IFS="
@ -250,6 +252,54 @@ zle -N fzf-history-widget
bindkey '^R' fzf-history-widget bindkey '^R' fzf-history-widget
``` ```
Auto-completion (experimental)
------------------------------
Disclaimer: *Auto-completion feature is currently experimental, it can change
over time*
### bash
fuzzy-finder-completion can be triggered if you type in a directory name
followed by the trigger sequence which is by default `**`.
#### Examples
```sh
# Files under current directory
# - You can select multiple items with TAB key
vim **<TAB>
# Files under parent directory
vim ..**<TAB>
# Files under your home directory
vim ~/**<TAB>
# Directories under current directory (single-selection)
cd **<TAB>
# Directories under parent directory
cd ../<TAB>
```
#### Settings
```sh
# Use ~~ as the trigger sequence instead of the default **
export FZF_COMPLETION_TRIGGER='~~'
# Options to fzf command
export FZF_COMPLETION_OPTS='+c -x'
```
### zsh
TODO :smiley:
(Pull requests are appreciated.)
Tips Tips
---- ----
@ -269,6 +319,9 @@ Define fzf alias with the option as follows:
alias fzf='ruby --disable-gems ~/bin/fzf' alias fzf='ruby --disable-gems ~/bin/fzf'
``` ```
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.
### Incorrect display on Ruby 1.8 ### Incorrect display on Ruby 1.8
It is reported that the output of fzf can become unreadable on some terminals It is reported that the output of fzf can become unreadable on some terminals

95
fzf-completion.bash Normal file
View File

@ -0,0 +1,95 @@
#!/bin/bash
# ____ ____
# / __/___ / __/
# / /_/_ / / /_
# / __/ / /_/ __/
# /_/ /___/_/-completion.bash
#
# - $FZF_COMPLETION_TRIGGER (default: '**')
# - $FZF_COMPLETION_OPTS (default: empty)
_fzf_opts_completion() {
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-m --multi -x --extended -s --sort +s +i +c --no-color"
case "${prev}" in
--sort|-s)
COMPREPLY=( $(compgen -W "$(seq 2000 1000 10000)" -- ${cur}) )
return 0
;;
esac
if [[ ${cur} =~ ^-|\+ ]]; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
return 0
}
_fzf_generic_completion() {
local cur prev opts base matches ignore
COMPREPLY=()
FZF_COMPLETION_TRIGGER=${FZF_COMPLETION_TRIGGER:-**}
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [[ ${cur} == *"$FZF_COMPLETION_TRIGGER" ]]; then
base=${cur:0:${#cur}-${#FZF_COMPLETION_TRIGGER}}
base=${base%/}
eval base=$base
ignore=${FZF_COMPLETION_IGNORE:-*/.git/*}
find_opts="-name .git -prune -o -name .svn -prune -o"
if [ -z "$base" -o -d "$base" ]; then
matches=$(find ${base:-*} $1 2> /dev/null | fzf $FZF_COMPLETION_OPTS $2 | while read item; do
if [[ ${item} =~ \ ]]; then
echo -n "\"$item\" "
else
echo -n "$item "
fi
done)
matches=${matches% }
if [ -n "$matches" ]; then
COMPREPLY=( "$matches" )
return 0
fi
fi
fi
}
_fzf_all_completion() {
_fzf_generic_completion \
"-name .git -prune -o -name .svn -prune -o -type f -print -o -type l -print" \
"-m"
}
_fzf_dir_completion() {
_fzf_generic_completion \
"-name .git -prune -o -name .svn -prune -o -type d -print" \
""
}
complete -F _fzf_opts_completion fzf
for cmd in "cd pushd rmdir"; do
complete -F _fzf_dir_completion -o default $cmd
done
FZF_COMPLETION_COMMANDS=${FZF_COMPLETION_COMMANDS:-
awk basename bunzip2 bzip2 curl diff diff3 dirname du emacs ex file find ftp
g++ gcc git grep gunzip gvim gzip head hg jar java javac jps ld less ls more
mvim open patch perl python rsync ruby scp sed sftp sort svn tail tar tee
uniq unzip vi view vim wc zip
}
for cmd in $FZF_COMPLETION_COMMANDS; do
complete -F _fzf_all_completion -o default $cmd
done
bind '"\e\e": complete'
bind '"\er": redraw-current-line'
bind '"\C-i": "\e\e\er"'

9
fzf-completion.zsh Normal file
View File

@ -0,0 +1,9 @@
#!/bin/zsh
# ____ ____
# / __/___ / __/
# / /_/_ / / /_
# / __/ / /_/ __/
# /_/ /___/_/-completion.zsh
#
# TODO

71
install
View File

@ -1,7 +1,72 @@
#!/bin/bash #!/bin/bash
cd `dirname $BASH_SOURCE` cd `dirname $BASH_SOURCE`
mkdir -p ~/bin FZF_BASE=`pwd`
ln -sf `pwd`/fzf ~/bin/fzf
chmod +x ~/bin/fzf # ruby executable
echo -n "Checking Ruby executable ... "
RUBY=`which ruby`
if [ $? -ne 0 ]; then
echo "ruby executable not found!"
exit 1
fi
echo "OK"
# Curses-support
echo -n "Checking Curses support ... "
/usr/bin/env ruby -e "begin; require 'curses'; rescue Exception; exit 1; end"
if [ $? -ne 0 ]; then
echo "Your ruby does not support 'curses'"
exit 1
fi
echo "OK"
# Ruby version
echo -n "Checking Ruby version ... "
/usr/bin/env ruby -e 'exit RUBY_VERSION >= "1.9"'
if [ $? -eq 0 ]; then
echo ">= 1.9"
FZF_ALIAS="alias fzf='$RUBY --disable-gems $FZF_BASE/fzf'"
else
echo "< 1.9"
FZF_ALIAS="alias fzf='$RUBY $FZF_BASE/fzf' # fzf"
fi
# Auto-completion
read -p "Do you want to add auto-completion support? (y/n) " -n 1 -r
echo
[[ ! $REPLY =~ ^[Nn]$ ]]
AUTO_COMPLETION=$?
echo
for shell in bash zsh; do
rc=~/.${shell}rc
echo "Update $rc:"
# Install fzf alias
echo "- Add fzf alias:"
echo " - $FZF_ALIAS"
if [ $(grep "alias fzf=" $rc | wc -l) -gt 0 ]; then
echo " - (X) fzf alias already exists"
else
echo $FZF_ALIAS >> $rc
echo " - Added."
fi
# Install auto-completion support
if [ $AUTO_COMPLETION -eq 0 ]; then
FZF_COMPLETION="source $FZF_BASE/fzf-completion.${shell}"
echo "- Add auto-completion support"
echo " - $FZF_COMPLETION"
if [ $(grep "source.*fzf-completion" $rc | wc -l) -gt 0 ]; then
echo " - (X) fzf-completion.${shell} already being sourced"
else
echo $FZF_COMPLETION >> $rc
echo " - Added."
fi
fi
echo
done
echo "Finished. Remove the added lines to uninstall fzf."