-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Examples
You can replace fzf command on each example with fzf-tmux to start fzf in a new tmux split pane.
# fe [FUZZY PATTERN] - Open the selected file with the default editor
# - Bypass fuzzy finder if there's only one match (--select-1)
# - Exit if there's no match (--exit-0)
fe() {
local file
file=$(fzf --query="$1" --select-1 --exit-0)
[ -n "$file" ] && ${EDITOR:-vim} "$file"
}
# Modified version where you can press
# - CTRL-O to open with `open` command,
# - CTRL-E or Enter key to open with the $EDITOR
fo() {
local out file key
out=$(fzf-tmux --query="$1" --exit-0 --expect=ctrl-o,ctrl-e)
key=$(head -1 <<< "$out")
file=$(head -2 <<< "$out" | tail -1)
if [ -n "$file" ]; then
[ "$key" = ctrl-o ] && open "$file" || ${EDITOR:-vim} "$file"
fi
}# fd - cd to selected directory
fd() {
local dir
dir=$(find ${1:-*} -path '*/\.*' -prune \
-o -type d -print 2> /dev/null | fzf +m) &&
cd "$dir"
}# fda - including hidden directories
fda() {
local dir
dir=$(find ${1:-.} -type d 2> /dev/null | fzf +m) && cd "$dir"
}Suggested by @harelba and @dimonomid:
# cdf - cd into the directory of the selected file
cdf() {
local file
local dir
file=$(fzf +m -q "$1") && dir=$(dirname "$file") && cd "$dir"
}# Another CTRL-T script to select a directory and paste it into line
__fzf_select_dir ()
{
builtin typeset READLINE_LINE_NEW="$(
command find -L . \( -path '*/\.*' -o -fstype dev -o -fstype proc \) \
-prune \
-o -type f -print \
-o -type d -print \
-o -type l -print 2>/dev/null \
| command sed 1d \
| command cut -b3- \
| env fzf -m
)"
if
[[ -n $READLINE_LINE_NEW ]]
then
builtin bind '"\er": redraw-current-line'
builtin bind '"\e^": magic-space'
READLINE_LINE=${READLINE_LINE:+${READLINE_LINE:0:READLINE_POINT}}${READLINE_LINE_NEW}${READLINE_LINE:+${READLINE_LINE:READLINE_POINT}}
READLINE_POINT=$(( READLINE_POINT + ${#READLINE_LINE_NEW} ))
else
builtin bind '"\er":'
builtin bind '"\e^":'
fi
}
builtin bind -x '"\C-x1": __fzf_select_dir'
builtin bind '"\C-t": "\C-x1\e^\er"'grep --line-buffered --color=never -r "" * | fzf
# with ag - respects .agignore and .gitignore
ag --nobreak --nonumbers --noheading . | fzf# fh - repeat history
fh() {
eval $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed 's/ *[0-9]* *//')
}# fh - repeat history
fh() {
print -z $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed 's/ *[0-9]* *//')
}Replacing eval with print -z will push the arguments onto the editing buffer stack, allowing you to edit the command before running it. It also means the command you run will appear in your history rather than just fh. Unfortunately this only works for zsh.
These have been tested in bash.
# utility function used to write the command in the shell
writecmd() {
perl -e '$TIOCSTI = 0x5412; $l = <STDIN>; $lc = $ARGV[0] eq "-run" ? "\n" : ""; $l =~ s/\s*$/$lc/; map { ioctl STDOUT, $TIOCSTI, $_; } split "", $l;' -- $1
}
# fh - repeat history
fh() {
([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed -re 's/^\s*[0-9]+\s*//' | writecmd -run
}
# fhe - repeat history edit
fhe() {
([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed -re 's/^\s*[0-9]+\s*//' | writecmd
}# Another CTRL-R script to insert the selected command from history into the command line/region
__fzf_history ()
{
builtin history -a;
builtin history -c;
builtin history -r;
builtin typeset \
READLINE_LINE_NEW="$(
HISTTIMEFORMAT= builtin history |
command fzf +s --tac +m -n2..,.. --tiebreak=index --toggle-sort=ctrl-r |
command sed '
/^ *[0-9]/ {
s/ *\([0-9]*\) .*/!\1/;
b end;
};
d;
: end
'
)";
if
[[ -n $READLINE_LINE_NEW ]]
then
builtin bind '"\er": redraw-current-line'
builtin bind '"\e^": magic-space'
READLINE_LINE=${READLINE_LINE:+${READLINE_LINE:0:READLINE_POINT}}${READLINE_LINE_NEW}${READLINE_LINE:+${READLINE_LINE:READLINE_POINT}}
READLINE_POINT=$(( READLINE_POINT + ${#READLINE_LINE_NEW} ))
else
builtin bind '"\er":'
builtin bind '"\e^":'
fi
}
builtin set -o histexpand;
builtin bind -x '"\C-x1": __fzf_history';
builtin bind '"\C-r": "\C-x1\e^\er"'# Toggle bash options (set and shopt)
BOLD=$(tput bold || tput md)
RESET=$(tput sgr0 || tput me)
GREEN=$(tput setaf 2 || tput AF 2)
RED=$(tput setaf 1 || tput AF 1)
#WHITE=$(tput setaf 7 || tput AF 7)
while read -r b o n _
do
case "${b}${o}" in
"set+o") set -o "$n" ;;
"set-o") set +o "$n" ;;
"shopt-s") shopt -u "$n" ;;
"shopt-u") shopt -s "$n" ;;
esac
printf ${RESET}
done < <(
< <(shopt -p ; shopt -op) sed "
/ -[so] / {
s/$/ ${BOLD}${GREEN}enabled/;
b return
}; {
s/$/ ${BOLD}${RED}disabled/;
};
: return;
" |
sort -k 3 |
column -t |
fzf --ansi --multi --with-nth=3.. --tiebreak=begin
)# fkill - kill process
fkill() {
pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}')
if [ "x$pid" != "x" ]
then
kill -${1:-9} $pid
fi
}# fbr - checkout git branch
fbr() {
local branches branch
branches=$(git branch -vv) &&
branch=$(echo "$branches" | fzf +m) &&
git checkout $(echo "$branch" | sed "s/.* //")
}
# fbr - checkout git branch (including remote branches)
fbr() {
local branches branch
branches=$(git branch --all | grep -v HEAD) &&
branch=$(echo "$branches" |
fzf-tmux -d $(( 2 + $(wc -l <<< "$branches") )) +m) &&
git checkout $(echo "$branch" | sed "s/.* //" | sed "s#remotes/[^/]*/##")
}
# fco - checkout git branch/tag
fco() {
local tags branches target
tags=$(
git tag | awk '{print "\x1b[31;1mtag\x1b[m\t" $1}') || return
branches=$(
git branch --all | grep -v HEAD |
sed "s/.* //" | sed "s#remotes/[^/]*/##" |
sort -u | awk '{print "\x1b[34;1mbranch\x1b[m\t" $1}') || return
target=$(
(echo "$tags"; echo "$branches") |
fzf-tmux -l30 -- --no-hscroll --ansi +m -d "\t" -n 2) || return
git checkout $(echo "$target" | awk '{print $2}')
}# fcoc - checkout git commit
fcoc() {
local commits commit
commits=$(git log --pretty=oneline --abbrev-commit --reverse) &&
commit=$(echo "$commits" | fzf --tac +s +m -e) &&
git checkout $(echo "$commit" | sed "s/ .*//")
}# fshow - git commit browser
fshow() {
local out sha q
while out=$(
git log --decorate=short --graph --oneline --color=always |
fzf --ansi --multi --no-sort --reverse --query="$q" --print-query); do
q=$(head -1 <<< "$out")
while read sha; do
[ -n "$sha" ] && git show --color=always $sha | less -R
done < <(sed '1d;s/^[^a-z0-9]*//;/^$/d' <<< "$out" | awk '{print $1}')
done
}# fcs - get git commit sha
# example usage: git rebase -i `fcs`
fcs() {
local commits commit
commits=$(git log --color=always --pretty=oneline --abbrev-commit --reverse) &&
commit=$(echo "$commits" | fzf --tac +s +m -e --ansi --reverse) &&
echo -n $(echo "$commit" | sed "s/ .*//")
}# fstash - easier way to deal with stashes
# type fstash to get a list of your stashes
# enter shows you the contents of the stash
# ctrl-d shows a diff of the stash against your current HEAD
# ctrl-b checks the stash out as a branch, for easier merging
fstash() {
local out q k sha
while out=$(
git stash list --pretty="%C(yellow)%h %>(14)%Cgreen%cr %C(blue)%gs" |
fzf --ansi --no-sort --query="$q" --print-query \
--expect=ctrl-d,ctrl-b);
do
q=$(head -1 <<< "$out")
k=$(head -2 <<< "$out" | tail -1)
sha=$(tail -1 <<< "$out" | cut -d' ' -f1)
[ -z "$sha" ] && continue
if [ "$k" = 'ctrl-d' ]; then
git diff $sha
elif [ "$k" = 'ctrl-b' ]; then
git stash branch "stash-$sha" $sha
break;
else
git stash show -p $sha
fi
done
}# ftags - search ctags
ftags() {
local line
[ -e tags ] &&
line=$(
awk 'BEGIN { FS="\t" } !/^!/ {print toupper($4)"\t"$1"\t"$2"\t"$3}' tags |
cut -c1-80 | fzf --nth=1,2
) && $EDITOR $(cut -f3 <<< "$line") -c "set nocst" \
-c "silent tag $(cut -f2 <<< "$line")"
}# fs [FUZZY PATTERN] - Select selected tmux session
# - Bypass fuzzy finder if there's only one match (--select-1)
# - Exit if there's no match (--exit-0)
fs() {
local session
session=$(tmux list-sessions -F "#{session_name}" | \
fzf --query="$1" --select-1 --exit-0) &&
tmux switch-client -t "$session"
}# ftpane - switch pane
ftpane () {
local panes current_window target target_window target_pane
panes=$(tmux list-panes -s -F '#I:#P - #{pane_current_path} #{pane_current_command}')
current_window=$(tmux display-message -p '#I')
target=$(echo "$panes" | fzf) || return
target_window=$(echo $target | awk 'BEGIN{FS=":|-"} {print$1}')
target_pane=$(echo $target | awk 'BEGIN{FS=":|-"} {print$2}' | cut -c 1)
if [[ $current_window -eq $target_window ]]; then
tmux select-pane -t ${target_window}.${target_pane}
else
tmux select-pane -t ${target_window}.${target_pane} &&
tmux select-window -t $target_window
fi
}Inspired by v. Opens files in ~/.viminfo
# v - open files in ~/.viminfo
v() {
local files
files=$(grep '^>' ~/.viminfo | cut -c3- |
while read line; do
[ -f "${line/\~/$HOME}" ] && echo "$line"
done | fzf-tmux -d -m -q "$*" -1) && vim ${files//\~/$HOME}
}With fasd.
Suggested by @epiloque
v() {
local file
file="$(fasd -Rfl "$1" | fzf -1 -0 --no-sort +m)" && vi "${file}" || return 1
}Integration with z.
like normal z when used with arguments but displays an fzf prompt when used without.
unalias z 2> /dev/null
z() {
if [[ -z "$*" ]]; then
cd "$(_z -l 2>&1 | fzf +s --tac | sed 's/^[0-9,.]* *//')"
else
_z "$@"
fi
}Here is another version that also supports relaunching z with the arguments for the previous command as the default input by using zz
unalias z
z() {
if [[ -z "$*" ]]; then
cd "$(_z -l 2>&1 | fzf +s --tac | sed 's/^[0-9,.]* *//')"
else
_last_z_args="$@"
_z "$@"
fi
}
zz() {
cd "$(_z -l 2>&1 | sed 's/^[0-9,.]* *//' | fzf -q $_last_z_args)"
}Since z is not very optimal located on a qwerty keyboard I have these aliased as j and jj
alias j=z
alias jj=zzWith fasd.
Suggested by @l4u and @epiloque
z() {
local dir
dir="$(fasd -Rdl "$1" | fzf -1 -0 --no-sort +m)" && cd "${dir}" || return 1
}Yet another useful application for fzf: shell bookmarks. It looks as follows:
See complete article for details: Fuzzy bookmarks for your shell
# c - browse chrome history
c() {
local cols sep
cols=$(( COLUMNS / 3 ))
sep='{{::}}'
# Copy History DB to circumvent the lock
# - See http://stackoverflow.com/questions/8936878 for the file path
cp -f ~/Library/Application\ Support/Google/Chrome/Default/History /tmp/h
sqlite3 -separator $sep /tmp/h \
"select substr(title, 1, $cols), url
from urls order by last_visit_time desc" |
awk -F $sep '{printf "%-'$cols's \x1b[36m%s\n", $1, $2}' |
fzf --ansi --multi | sed 's#.*\(https*://\)#\1#' | xargs open
}https://gist.github.com/junegunn/15859538658e449b886f (for OS X)
# fzf-fs
# https://github.com/D630/fzf-fs
% [.] fzf-fs [<ARG>]Alt-i to paste item from locate / output (zsh only):
# ALT-I - Paste the selected entry from locate output into the command line
fzf-locate-widget() {
local selected
if selected=$(locate / | fzf -q "$LBUFFER"); then
LBUFFER=$selected
fi
zle redisplay
}
zle -N fzf-locate-widget
bindkey '\ei' fzf-locate-widget# CTRL-X-1 - Invoke Readline functions by name
__fzf_readline ()
{
builtin eval "
builtin bind ' \
\"\C-x3\": $(
builtin bind -l | command fzf +s +m --toggle-sort=ctrl-r
) \
'
"
}
builtin bind -x '"\C-x2": __fzf_readline';
builtin bind '"\C-x1": "\C-x2\C-x3"'# RVM integration
frb() {
local rb
rb=$((echo system; rvm list | grep ruby | cut -c 4-) |
awk '{print $1}' |
fzf-tmux -l 30 +m --reverse) && rvm use $rb
}You must have jq installed on your computer in order to use this function.
vs(){
#List all vagrant boxes available in the system including its status, and try to access the selected one via ssh
cd $(cat ~/.vagrant.d/data/machine-index/index | jq '.machines[] | {name, vagrantfile_path, state}' | jq '.name + "," + .state + "," + .vagrantfile_path'| sed 's/^"\(.*\)"$/\1/'| column -s, -t | sort -rk 2 | fzf | awk '{print $3}'); vagrant ssh
}# fzf-wrapper
# https://github.com/D630/fzf-wrapper
% . fzf-wrapper
% [<ENV>...] __fzf_wrapper [<ARG>...]