-
-
Save junegunn/8b572b8d4b5eddd8b85e5f4d40f17236 to your computer and use it in GitHub Desktop.
# GIT heart FZF | |
# ------------- | |
is_in_git_repo() { | |
git rev-parse HEAD > /dev/null 2>&1 | |
} | |
fzf-down() { | |
fzf --height 50% --min-height 20 --border --bind ctrl-/:toggle-preview "$@" | |
} | |
_gf() { | |
is_in_git_repo || return | |
git -c color.status=always status --short | | |
fzf-down -m --ansi --nth 2..,.. \ | |
--preview '(git diff --color=always -- {-1} | sed 1,4d; cat {-1})' | | |
cut -c4- | sed 's/.* -> //' | |
} | |
_gb() { | |
is_in_git_repo || return | |
git branch -a --color=always | grep -v '/HEAD\s' | sort | | |
fzf-down --ansi --multi --tac --preview-window right:70% \ | |
--preview 'git log --oneline --graph --date=short --color=always --pretty="format:%C(auto)%cd %h%d %s" $(sed s/^..// <<< {} | cut -d" " -f1)' | | |
sed 's/^..//' | cut -d' ' -f1 | | |
sed 's#^remotes/##' | |
} | |
_gt() { | |
is_in_git_repo || return | |
git tag --sort -version:refname | | |
fzf-down --multi --preview-window right:70% \ | |
--preview 'git show --color=always {}' | |
} | |
_gh() { | |
is_in_git_repo || return | |
git log --date=short --format="%C(green)%C(bold)%cd %C(auto)%h%d %s (%an)" --graph --color=always | | |
fzf-down --ansi --no-sort --reverse --multi --bind 'ctrl-s:toggle-sort' \ | |
--header 'Press CTRL-S to toggle sort' \ | |
--preview 'grep -o "[a-f0-9]\{7,\}" <<< {} | xargs git show --color=always' | | |
grep -o "[a-f0-9]\{7,\}" | |
} | |
_gr() { | |
is_in_git_repo || return | |
git remote -v | awk '{print $1 "\t" $2}' | uniq | | |
fzf-down --tac \ | |
--preview 'git log --oneline --graph --date=short --pretty="format:%C(auto)%cd %h%d %s" {1}' | | |
cut -d$'\t' -f1 | |
} | |
_gs() { | |
is_in_git_repo || return | |
git stash list | fzf-down --reverse -d: --preview 'git show --color=always {1}' | | |
cut -d: -f1 | |
} |
if [[ $- =~ i ]]; then | |
bind '"\er": redraw-current-line' | |
bind '"\C-g\C-f": "$(_gf)\e\C-e\er"' | |
bind '"\C-g\C-b": "$(_gb)\e\C-e\er"' | |
bind '"\C-g\C-t": "$(_gt)\e\C-e\er"' | |
bind '"\C-g\C-h": "$(_gh)\e\C-e\er"' | |
bind '"\C-g\C-r": "$(_gr)\e\C-e\er"' | |
bind '"\C-g\C-s": "$(_gs)\e\C-e\er"' | |
fi |
join-lines() { | |
local item | |
while read item; do | |
echo -n "${(q)item} " | |
done | |
} | |
() { | |
local c | |
for c in $@; do | |
eval "fzf-g$c-widget() { local result=\$(_g$c | join-lines); zle reset-prompt; LBUFFER+=\$result }" | |
eval "zle -N fzf-g$c-widget" | |
eval "bindkey '^g^$c' fzf-g$c-widget" | |
done | |
} f b t r h s |
Cool gist! keybinding.zsh
can be further simplified to just:
() {
local c
for c in $@; do
eval "fzf-g$c-widget() { local -r result=(\${(f)\"\$(_g$c)\"}); zle reset-prompt; LBUFFER+=\${(j: :)\${(q)result}} }"
eval "zle -N fzf-g$c-widget"
eval "bindkey '^g^$c' fzf-g$c-widget"
done
} f b t r h s
For some friends using zsh vi mode but the keybindings do not work:
^g
is already assigned to zsh builtin standard widget list-expand
, so we should remove it first by bindkey -r '^g'
.
I am using git bash on Windows and I am getting error like << was unexpected at this time. on those function using <<< {}, any thoughts?
@ztou I found that issue today. Turns out you need to start your git bash session with -l
flag, so the subprocess that fzf starts for the preview is still gitbash. then the <<<
operator will work.
You can even do some crazy stuff like creating a string to make it work from powershell using git bash.
function _gh () {
if (-not (git rev-parse HEAD 2> $null)) { return }
bash -lc @'
git log --date=short --format='%C(green)%C(bold)%cd %C(auto)%h%d %s (%an)' --graph --color=always |
fzf --height 50% --min-height 20 --border --bind ctrl-/:toggle-preview --ansi --no-sort --reverse --multi --bind 'ctrl-s:toggle-sort' \
--header 'Press CTRL-S to toggle sort' \
--preview 'grep -o \"[a-f0-9]\{7,\}\" <<< {} | xargs git show --color=always | bat -p --color=always' |
grep -o '[a-f0-9]\{7,\}'
'@
}
I'd like to ask the reason why some commands in the pipes are after fzf
Here is what I mean. Take _gb as an example.
_gb() {
is_in_git_repo || return
git branch -a --color=always | grep -v '/HEAD\s' | sort |
fzf-down --ansi --multi --tac --preview-window right:70% \
--preview 'git log --oneline --graph --date=short --color=always --pretty="format:%C(auto)%cd %h%d %s" $(sed s/^..// <<< {} | cut -d" " -f1)' |
sed 's/^..//' | cut -d' ' -f1 |
sed 's#^remotes/##'
}
The part sed 's/^..//' | cut -d' ' -f1 | sed 's#^remotes/##'
at the bottom does not make much sense to me as fzf will display the results before these commands. Is there any reason to call them at the end?
As I can see, the above command can be simplified
_gb() {
is_in_git_repo || return
git branch -a --color=always | grep -v '/HEAD\s' | sort |
sed 's/^..//' | cut -d' ' -f1 |
fzf-down --ansi --multi --tac --preview-window right:70% \
--preview 'git log --oneline --graph --date=short --color=always --pretty="format:%C(auto)%cd %h%d %s" {}'
}
or if you want to include the sed
part remove the word "remotes/"
_gb() {
is_in_git_repo || return
git branch -a --color=always | grep -v '/HEAD\s' | sort |
sed 's/^..//' | cut -d' ' -f1 | sed 's#remotes/##'
fzf-down --ansi --multi --tac --preview-window right:70% \
--preview 'git log --oneline --graph --date=short --color=always --pretty="format:%C(auto)%cd %h%d %s" {}'
}
@DanSM-5 Pipe a command after fzf means pass the selection(s) from fzf into this command for further processing.
To implement a feature, you can process the data first and then pass them into fzf and make selections to get what you need, or you can first pass the data into fzf and then post-process the selections to get what you need.
@rockyzhang24 I see, I was pretty much using this for the visualization but that's a nice part too.
For the _gb
function, I just noticed that moving those commands above will remove the *
for the current branch. So it is likely intentional to leave it in fzf list output. I was only paying attention to the color highlight so I really missed that.
If you use a non-standard diff tool (such as bcompare), you'll need to tell git to use the built-in with the --no-ext-diff flag:
_gf() {
is_in_git_repo || return
git -c color.status=always status --short |
fzf-down -m --ansi --nth 2..,.. \
--preview '(git diff --no-ext-diff --color=always -- {-1} | sed 1,4d; cat {-1})' |
cut -c4- | sed 's/.* -> //'
}
Migrated to https://github.com/junegunn/fzf-git.sh
Thanks for the response - I will try and kitty when I get some time.
I actually got the key-bindings working using a bash line editor replacement, ble.sh, that I use for fish-like autosuggestions and more. Here's a note about getting these bindings to work.