84 lines
3.0 KiB
Bash
Executable File
84 lines
3.0 KiB
Bash
Executable File
## Author: druckdev
|
|
## Created: 2020-08-28
|
|
##
|
|
## A TUI for git-log using fzf.
|
|
## Displays git-log in fzf and git-show as preview command for each commit.
|
|
|
|
# extendedglob is necessary for the expansion of the binds array
|
|
emulate -L zsh -o extendedglob
|
|
|
|
# Return if not in git repo
|
|
git rev-parse || return
|
|
|
|
# One line format for fzf list view
|
|
# abbreviated commit hash (yellow), title and ref names
|
|
local formatshort='--pretty=format:%C(yellow)%h %Creset%s%C(auto)%d'
|
|
# Verbose format for the preview window on the right
|
|
# This array is stitched together with newlines later
|
|
local -a format=(
|
|
'--pretty=format:%C(yellow)' # newline created by this eaten by %-
|
|
'%-Commit: %H%C(auto)' # yellow commit hash
|
|
' %D%Cblue' # auto colored ref names (if any)
|
|
'Author: %aN %aE%Cred' # blue author mail
|
|
'AuthorDate: %ad%Cblue' # red author date
|
|
'Commit: %cN %cE%Cred' # blue commiter mail
|
|
'CommitDate: %cd%Cblue' # red commit date
|
|
'Signer: %GS%Cgreen' # signer name
|
|
'Fingerprint: %GF' # pgp fingerprint
|
|
'%Creset%C(bold)' # empty line
|
|
' %s%Creset' # bold white subject
|
|
# With the space the empty line is not eaten when the body is empty:
|
|
' '
|
|
'%-b' # body
|
|
)
|
|
|
|
# Ignore the graph part at the beginning, then capture the commit hash and throw
|
|
# away the rest of the line.
|
|
local commit_hash='s/^[^a-f0-9]*([a-f0-9]*).*$/\1/'
|
|
|
|
local dateshort='--date=format:%F' # year
|
|
local date="$dateshort %T %z" # year time timezone
|
|
|
|
# Put the commit hash into the clipboard
|
|
local fzf_copy_command="echo -n {} | sed -E '$commit_hash' | xclip -sel c"
|
|
# Execute git show on selected commit
|
|
local fzf_preview_command
|
|
read -r -d '' fzf_preview_command <<EOT
|
|
out="\$(echo {} | sed -E "$commit_hash")"
|
|
if [[ -n "\$out" ]]; then
|
|
git show "${(j:%n:)format}" "$date" --color=always "\$out" \
|
|
| diff-so-fancy --color=always
|
|
fi
|
|
EOT
|
|
local -A binds=(
|
|
"ctrl-space" "toggle-preview"
|
|
"ctrl-alt-j" "preview-down"
|
|
"ctrl-alt-k" "preview-up"
|
|
"ctrl-y" "execute-silent@$fzf_copy_command@"
|
|
"enter" "execute@$fzf_preview_command | command less -R@"
|
|
)
|
|
local -a fzf_args=(
|
|
# Understand ansi color escape sequences.
|
|
"--ansi"
|
|
# Expand the binds array in the format "key1:value1,key2:value2".
|
|
"--bind" "${(@kj:,:)binds/(#m)*/$MATCH:$binds[$MATCH]}"
|
|
# Execute git show on the commit as preview.
|
|
"--preview" "$fzf_preview_command"
|
|
# Reverse the layout so that the newest commit is at the top.
|
|
"--reverse"
|
|
# Do not sort when typing to maintain the sorting by date.
|
|
"--no-sort"
|
|
)
|
|
# Hide preview window by default when the terminal is too small.
|
|
# 154 columns so that the commit subject on the left and the body lines on the
|
|
# right all fit. The preview can always be shown using the keybind from above.
|
|
[[ "$(tput cols)" -ge 154 ]] || fzf_args+=(--preview-window hidden)
|
|
|
|
# Display an ascii graph of the commits in the above format and pipe that into
|
|
# fzf.
|
|
git log "$formatshort" --graph "$dateshort" --color=always \
|
|
| fzf "${fzf_args[@]}"
|
|
return 0
|
|
|
|
# vim: ft=zsh
|