#!/usr/bin/env 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. # TODO: preview breaks when files were passed but they were renamed and have a # different name at the point of this commit # extendedglob is necessary for the expansion of the binds array emulate -L zsh -o extendedglob # Return if fzf is not available if (( ! $+commands[fzf] )); 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 local -a format=( '--pretty=format:' '%C(yellow)' 'Commit: ' '%H' '%n' # commit hash '%C(auto)' ' ' '%D' '%n' # ref names (if any) '%C(blue)' 'Author: ' '%aN <%aE>' '%n' # author mail '%C(red)' 'AuthorDate: ' '%ad' '%n' # author date '%C(blue)' 'Commit: ' '%cN <%cE>' '%n' # commiter mail '%C(red)' 'CommitDate: ' '%cd' '%n' # commit date '%C(blue)' 'Signer: ' '%GS' '%n' # signer name '%C(green)' 'Key (%G?): ' '%GK' '%n' # pgp key used to sign '%n' '%C(reset)%C(bold)' ' %s%C(reset)' '%n' # subject '%n' '%-b' # body '%n' ) format="${(j::)format}" # 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 '' <` for 'patch' command with `-- ` argument, so that # the passed file is ontop although the full patch is shown # TODO: Support -L flag as well (add `-s` for list and `-- ` & maybe `-W` # for preview) fzf_preview[files_only]="$fzf_preview[patch] ${(@)${@:${@[(ei)--]}}/(#m)*/\"$MATCH\"}" # Use git's pager in the preview window (and with it any special highlighting # tool, such as diff-so-fancy) local pager pager="$(git config --get --default="" core.pager)" fzf_preview[patch]+="${pager:+ | }$pager; }" fzf_preview[files_only]+="${pager:+ | }$pager; }" read -r -d '' </dev/null)}) if (( ! $? )) && (( $tty_size[2] > 152 )); then fzf_args+=( --preview-window=right --bind "ctrl-space:change-preview-window(hidden|bottom|right)" ) else fzf_args+=( --preview-window=down --bind "ctrl-space:change-preview-window(hidden|right|bottom)" ) fi # Display the commits in the above format and pipe that into fzf if stdout is a # terminal. if [ -t 1 ]; then git log "$formatshort" "$dateshort" --color=always "$@" \ | env LESS="$LESS${LESS:+ }-+F" fzf "${fzf_args[@]}" else git log "$formatshort" "$dateshort" --color=always "$@" fi return 0