zsh:glog: Fix preview with files that were renamed

Previously when calling `glog -- file` with a file that was renamed
sometime in the history, the preview would just be empty for all commits
before the rename, since it's path didn't exist.

Fix this by checking for empty output and falling back to the full patch
in that case.

This also heavily refactors the code around `$fzf_preview` to make it
more readable.

TODO: It would be nice if git-show would fail in this case instead of
      just printing nothing and returning zero
This commit is contained in:
2025-05-23 18:04:55 +02:00
parent 339ef90db0
commit 00d28845a3

View File

@@ -49,39 +49,49 @@ local commit_hash='s/^[^a-f0-9]*([a-f0-9]*).*$/\1/'
local dateshort='--date=format:%F' # year local dateshort='--date=format:%F' # year
local date="$dateshort %T %z" # year time timezone local date="$dateshort %T %z" # year time timezone
local -A fzf_preview # Use git's pager in the preview window (and with it any special highlighting
read -r -d '' <<EOT # tool, such as diff-so-fancy)
local pager
pager="$(git config --get --default="" core.pager)"
into_pager="${pager:+|} $pager"
# NOTE: use read for a bit better readability of the code since less needs
# quoting and formatting is easier
read -r -d '' get_hash_cmd <<EOT
hash="\$(echo -E {} | sed -E "$commit_hash")"; [[ -z "\$hash" ]] || hash="\$(echo -E {} | sed -E "$commit_hash")"; [[ -z "\$hash" ]] ||
EOT EOT
fzf_preview[construct]="$REPLY" read -r -d '' show_cmd <<EOT
read -r -d '' <<EOT
git show "$format" "$date" --color=always --patch-with-stat "\$hash" git show "$format" "$date" --color=always --patch-with-stat "\$hash"
EOT EOT
fzf_preview[patch]="$fzf_preview[construct] { $REPLY" show_stat_cmd="${show_cmd/patch-with-}"
# Get file arguments after (and including) `--` and wrap each in quotes
local -A fzf_preview
fzf_preview[patch]="$get_hash_cmd $show_cmd $into_pager"
fzf_preview[stat]="$get_hash_cmd $show_stat_cmd $into_pager"
# TODO: Display `...` behind patch-stat if the patch touched more files # TODO: Display `...` behind patch-stat if the patch touched more files
# TODO: Use `-O <file>` for 'patch' command with `-- <file>` argument, so that # TODO: Use `-O <file>` for 'patch' command with `-- <file>` argument, so that
# the passed file is ontop although the full patch is shown # the passed file is ontop although the full patch is shown
# TODO: Support -L flag as well (add `-s` for list and `-- <file>` & maybe `-W` # TODO: Support -L flag as well (add `-s` for list and `-- <file>` & maybe `-W`
# for preview) # for preview)
fzf_preview[files_only]="$fzf_preview[patch] ${(@)${@:${@[(ei)--]}}/(#m)*/'$MATCH'}" # Get file arguments after (and including) `--` and wrap each in quotes
read -r -d '' 'fzf_preview[files_only]' <<EOT
# Use git's pager in the preview window (and with it any special highlighting $get_hash_cmd {
# tool, such as diff-so-fancy) {
local pager out="\$($show_cmd ${(@)${@:${@[(ei)--]}}/(#m)*/'$MATCH'})"
pager="$(git config --get --default="" core.pager)" if [[ \$out ]]; then
fzf_preview[patch]+="${pager:+ | }$pager; }" printf '%s' "\$out"
fzf_preview[files_only]+="${pager:+ | }$pager; }" else
echo "warning: files were renamed. showing full diff"
read -r -d '' <<EOT $show_cmd
git show "$format" "$date" --color=always --stat "\$hash" fi
} $into_pager
}
EOT EOT
fzf_preview[stat]="$fzf_preview[construct] { $REPLY; }"
# Put the commit hash into the clipboard # Put the commit hash into the clipboard
# (If no known clipboard tool is available, just print it) # (If no known clipboard tool is available, just print it)
local fzf_copy_command="$fzf_preview[construct] echo -n \"\$hash\"" local fzf_copy_command="$get_hash_cmd echo -n \"\$hash\""
if [[ $OSTYPE =~ darwin ]] && (( $+commands[pbcopy] )); then if [[ $OSTYPE =~ darwin ]] && (( $+commands[pbcopy] )); then
fzf_copy_command+=" | pbcopy" fzf_copy_command+=" | pbcopy"
elif (( $+commands[xclip] )); then elif (( $+commands[xclip] )); then