By adding a shebang to the scripts they can be executed directly without an interactive shell. The shebang also makes vims modeline that only set the filetype obsolete.
125 lines
4.2 KiB
Bash
Executable File
125 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/zsh
|
|
## 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 fzf is not available
|
|
if ! command -v fzf &>/dev/null; then
|
|
printf "command not found: fzf" >&2
|
|
return 1
|
|
fi
|
|
|
|
# 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
|
|
'Key (%G?): %GK' # pgp key used to sign
|
|
'%Creset%C(bold)' # empty line
|
|
' %s%Creset' # bold white subject
|
|
'' # newline
|
|
'%-b' # body
|
|
'' # newline
|
|
)
|
|
|
|
# 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
|
|
|
|
local -A fzf_preview
|
|
read -r -d '' <<EOT
|
|
out="\$(echo -E {} | sed -E "$commit_hash")"; [[ -z "\$out" ]] ||
|
|
EOT
|
|
fzf_preview[construct]="$REPLY"
|
|
|
|
read -r -d '' <<EOT
|
|
git show "${(j:%n:)format}" "$date" --color=always --patch-with-stat "\$out"
|
|
EOT
|
|
fzf_preview[patch]="$fzf_preview[construct] { $REPLY"
|
|
if command -v diff-so-fancy &>/dev/null; then
|
|
fzf_preview[patch]+=" | diff-so-fancy --color=always"
|
|
fi
|
|
fzf_preview[patch]+=" }"
|
|
|
|
read -r -d '' <<EOT
|
|
git show "${(j:%n:)format}" "$date" --color=always --stat "\$out"
|
|
EOT
|
|
fzf_preview[stat]="$fzf_preview[construct] { $REPLY }"
|
|
|
|
# Put the commit hash into the clipboard
|
|
# (If no known clipboard tool is available, just print it)
|
|
local fzf_copy_command="$fzf_preview[construct] echo -n \"\$out\""
|
|
if [[ $OSTYPE =~ darwin ]] && command -v pbcopy &>/dev/null; then
|
|
fzf_copy_command+=" | pbcopy"
|
|
elif command -v xclip &>/dev/null; then
|
|
fzf_copy_command+=" | xclip -selection c"
|
|
fi
|
|
|
|
local -A binds=(
|
|
"ctrl-space" "toggle-preview"
|
|
"ctrl-alt-j" "preview-down"
|
|
"ctrl-alt-k" "preview-up"
|
|
# Copy commit hash
|
|
"ctrl-y" "execute@$fzf_copy_command@"
|
|
# Open preview "fullscreen"
|
|
"enter" "execute@$fzf_preview[patch] | command less -R@"
|
|
# Clear query if not empty, abort otherwise
|
|
"esc" "cancel"
|
|
# Preview stats
|
|
"ctrl-s" "preview($fzf_preview[stat])"
|
|
# Preview patch
|
|
"ctrl-d" "preview($fzf_preview[patch])"
|
|
"ctrl-p" "preview($fzf_preview[patch])"
|
|
)
|
|
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[patch]"
|
|
# 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"
|
|
)
|
|
|
|
# The preview-window should be placed differently depending on the dimensions of
|
|
# the terminal.
|
|
# 0.45 seems to be round about the ratio between cols and lines on my system.
|
|
# With that I get somewhat decent results with. This probably depends on the
|
|
# font and font-size of the terminal and needs to be changed potentially.
|
|
local -a tty_size
|
|
tty_size=(${=$(command stty size 2>/dev/null)})
|
|
if (( ! $? )) && (( $tty_size[2] * 0.4 > $tty_size[1] )); then
|
|
fzf_args+=(--preview-window=right)
|
|
else
|
|
fzf_args+=(--preview-window=down)
|
|
fi
|
|
|
|
# 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
|