Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: add forgit show command #417

Merged
merged 3 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ It's **lightweight** and **easy to use**.

# 📥 Installation

*Make sure you have [`fzf`](https://github.com/junegunn/fzf) installed.*
## Requirements

- [`fzf`](https://github.com/junegunn/fzf) version `0.49.0` or higher

If your OS package manager bundles an older version of `fzf`, you might install it using [`fzf`'s own install script'](https://github.com/junegunn/fzf?tab=readme-ov-file#using-git).

## Shell package managers

``` zsh
# for zplug
Expand Down Expand Up @@ -101,6 +107,8 @@ Then add the following to your shell's config file:

- **Interactive `git diff` viewer** (`gd`)

- **Interactive `git show` viewer** (`gso`)

- **Interactive `git reset HEAD <file>` selector** (`grh`)

- **Interactive `git checkout <file>` selector** (`gcf`)
Expand Down Expand Up @@ -172,6 +180,7 @@ You can change the default aliases by defining these variables below.
forgit_log=glo
forgit_reflog=grl
forgit_diff=gd
forgit_show=gso
forgit_add=ga
forgit_reset_head=grh
forgit_ignore=gi
Expand Down Expand Up @@ -232,6 +241,7 @@ These are passed to the according `git` calls.
| `glo` | `FORGIT_LOG_GIT_OPTS` |
| `grl` | `FORGIT_REFLOG_GIT_OPTS` |
| `gd` | `FORGIT_DIFF_GIT_OPTS` |
| `gso` | `FORGIT_SHOW_GIT_OPTS` |
| `grh` | `FORGIT_RESET_HEAD_GIT_OPTS` |
| `gcf` | `FORGIT_CHECKOUT_FILE_GIT_OPTS` |
| `gcb` | `FORGIT_CHECKOUT_BRANCH_GIT_OPTS`, `FORGIT_CHECKOUT_BRANCH_BRANCH_GIT_OPTS` |
Expand Down Expand Up @@ -286,6 +296,7 @@ Customizing fzf options for each command individually is also supported:
| `grl` | `FORGIT_REFLOG_FZF_OPTS` |
| `gi` | `FORGIT_IGNORE_FZF_OPTS` |
| `gd` | `FORGIT_DIFF_FZF_OPTS` |
| `gso` | `FORGIT_SHOW_FZF_OPTS` |
| `grh` | `FORGIT_RESET_HEAD_FZF_OPTS` |
| `gcf` | `FORGIT_CHECKOUT_FILE_FZF_OPTS` |
| `gcb` | `FORGIT_CHECKOUT_BRANCH_FZF_OPTS` |
Expand Down
98 changes: 97 additions & 1 deletion bin/git-forgit
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@
# This gives users the choice to set aliases inside of their git config instead
# of their shell config if they prefer.

# Check if fzf is installed
installed_fzf_version=$(fzf --version 2>/dev/null | awk '{print $1}')
if [[ -z "$installed_fzf_version" ]]; then
echo "fzf is not installed. Please install fzf first."
exit 1
fi

# Check fzf version
required_fzf_version="0.49.0"
higher_fzf_version=$(printf '%s\n' "$required_fzf_version" "$installed_fzf_version" | sort -V | tail -n1)
if [[ "$higher_fzf_version" != "$installed_fzf_version" ]]; then
echo "fzf version $required_fzf_version or higher is required. You have $installed_fzf_version."
exit 1
fi

# Set shell for fzf preview commands
# Disable shellcheck for "which", because it suggests "command -v xxx" instead,
# which is not a working replacement.
Expand Down Expand Up @@ -185,7 +200,7 @@ _forgit_log_enter() {
local sha
sha=$(echo "$1" | _forgit_extract_sha)
shift
echo "$sha" | xargs -I% "${FORGIT}" diff %^! "$@"
echo "$sha" | xargs -I% "${FORGIT}" show % "$@"
}

# git commit viewer
Expand Down Expand Up @@ -339,6 +354,83 @@ _forgit_diff() {
return $fzf_exit_code
}

_forgit_exec_show() {
_forgit_show_git_opts=()
_forgit_parse_array _forgit_show_git_opts "$FORGIT_SHOW_GIT_OPTS"
git show --pretty="" --diff-merges=first-parent --color=always "${_forgit_show_git_opts[@]}" "$@"
}

_forgit_show_view() {
local input_line=$1
local diff_context=$2
local commit=$3
local repo
repo=$(git rev-parse --show-toplevel)
cd "$repo" || return 1
echo "$input_line" | _forgit_get_files_from_diff_line | xargs -0 \
"$FORGIT" exec_show "${commit}^{commit}" -U"$diff_context" -- | _forgit_pager diff
}

_forgit_show_preview() {
local input_line=$1
local diff_context=$2
local commit=$3
if [[ "$FZF_PREVIEW_LABEL" =~ "Diff" ]]; then
_forgit_show_view "${input_line}" "${diff_context}" "${commit}"
else
git show --quiet --color=always "${FZF_PROMPT%% *}"
fi
}

_forgit_show_enter() {
file=$1
commit=$2
_forgit_show_view "$file" "$_forgit_fullscreen_context" "${commit}"
}

# git show viewer
_forgit_show() {
_forgit_inside_work_tree || return 1
local files opts commit escaped_commit
files=()
if [[ $# -ne 0 ]]; then
if git rev-parse "$1" -- &>/dev/null ; then
commit="$1" && files=("${@:2}")
else
commit="HEAD" && files=("$@")
fi
else
commit="HEAD"
fi
# Escape opening brackets to support stashes (see comment in _forgit_diff)
escaped_commit=${commit//\{/\\\\\{}
opts="
$FORGIT_FZF_DEFAULT_OPTS
+m -0 --bind=\"enter:execute($FORGIT show_enter {} $escaped_commit | $FORGIT pager enter)\"
--preview=\"$FORGIT show_preview {} '$_forgit_preview_context' $escaped_commit\"
--preview-label=\" Diff \"
--bind=\"alt-e:execute($FORGIT edit_diffed_file {})+refresh-preview\"
--bind=\"alt-t:transform:[[ ! \\\"\$FZF_PREVIEW_LABEL\\\" =~ 'Diff' ]] &&
echo 'change-preview-label( Diff )+refresh-preview' ||
echo 'change-preview-label( Commit Message )+refresh-preview'\"
$FORGIT_DIFF_FZF_OPTS
--prompt=\"${commit} > \"
"
_forgit_show_git_opts=()
_forgit_parse_array _forgit_show_git_opts "$FORGIT_SHOW_GIT_OPTS"
# Add "^{commit}" suffix after the actual commit. This suppresses the tag information in case it is a tag.
# See: https://git-scm.com/docs/git-show#Documentation/git-show.txt-codegitshow-s--formatsv100commitcode
git show --pretty="" --name-status --diff-merges=first-parent "${_forgit_show_git_opts[@]}" "${commit}^{commit}" \
-- "${files[@]}" |
sed -E 's/^([[:alnum:]]+)[[:space:]]+(.*)$/[\1] \2/' |
sed 's/ / -> /2' | expand -t 8 |
FZF_DEFAULT_OPTS="$opts" fzf
fzf_exit_code=$?
# exit successfully on 130 (ctrl-c/esc)
[[ $fzf_exit_code == 130 ]] && return 0
return $fzf_exit_code
}

_forgit_add_preview() {
file=$(echo "$1" | _forgit_get_single_file_from_add_line)
if (git status -s -- "$file" | grep '^??') &>/dev/null; then # diff with /dev/null for untracked files
Expand Down Expand Up @@ -1021,6 +1113,7 @@ public_commands=(
"rebase"
"reset_head"
"revert_commit"
"show"
"stash_show"
"stash_push"
)
Expand All @@ -1035,10 +1128,13 @@ private_commands=(
"cherry_pick_preview"
"clean_preview"
"diff_enter"
"exec_show"
"file_preview"
"ignore_preview"
"revert_preview"
"reset_head_preview"
"show_enter"
"show_preview"
"stash_push_preview"
"stash_show_preview"
"yank_sha"
Expand Down
2 changes: 2 additions & 0 deletions completions/_git-forgit
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ _git-forgit() {
reset_head) _git-staged ;;
revert_commit) __git_recent_commits ;;
stash_show) _git-stash-show ;;
show) _git-show ;;
esac
}

Expand All @@ -122,6 +123,7 @@ compdef _git-rebase forgit::rebase
compdef _git-staged forgit::reset::head
compdef __git_recent_commits forgit::revert::commit
compdef _git-stash-show forgit::stash::show
compdef _git-show forgit::show

# this is the case of calling the command and pressing tab
# the very first time of a shell session, we have to manually
Expand Down
4 changes: 4 additions & 0 deletions completions/git-forgit.bash
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ _git_forgit()
rebase
reset_head
revert_commit
show
stash_show
stash_push
"
Expand All @@ -101,6 +102,7 @@ _git_forgit()
rebase) _git_rebase ;;
reset_head) _git_reset ;;
revert_commit) _git_revert ;;
show) _git_show ;;
stash_show) _git_stash_show ;;
esac
;;
Expand Down Expand Up @@ -135,6 +137,7 @@ then
__git_complete forgit::rebase _git_rebase
__git_complete forgit::reset::head _git_reset
__git_complete forgit::revert::commit _git_revert
__git_complete forgit::show _git_show
__git_complete forgit::stash::show _git_stash_show

# Completion for forgit plugin shell aliases
Expand All @@ -154,6 +157,7 @@ then
__git_complete "${forgit_rebase}" _git_rebase
__git_complete "${forgit_reset_head}" _git_reset
__git_complete "${forgit_revert_commit}" _git_revert
__git_complete "${forgit_show}" _git_show
__git_complete "${forgit_stash_show}" _git_stash_show
fi
fi
1 change: 1 addition & 0 deletions completions/git-forgit.fish
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ complete -c git-forgit -n __fish_forgit_needs_subcommand -a reflog -d 'git reflo
complete -c git-forgit -n __fish_forgit_needs_subcommand -a rebase -d 'git rebase'
complete -c git-forgit -n __fish_forgit_needs_subcommand -a reset_head -d 'git reset HEAD (unstage) selector'
complete -c git-forgit -n __fish_forgit_needs_subcommand -a revert_commit -d 'git revert commit selector'
complete -c git-forgit -n __fish_forgit_needs_subcommand -a show -d 'git show viewer'
complete -c git-forgit -n __fish_forgit_needs_subcommand -a stash_show -d 'git stash viewer'
complete -c git-forgit -n __fish_forgit_needs_subcommand -a stash_push -d 'git stash push selector'

Expand Down
1 change: 1 addition & 0 deletions conf.d/forgit.plugin.fish
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ if test -z "$FORGIT_NO_ALIASES"
abbr -a -- (string collect $forgit_log; or string collect "glo") git-forgit log
abbr -a -- (string collect $forgit_reflog; or string collect "grl") git-forgit reflog
abbr -a -- (string collect $forgit_diff; or string collect "gd") git-forgit diff
abbr -a -- (string collect $forgit_show; or string collect "gso") git-forgit show
abbr -a -- (string collect $forgit_ignore; or string collect "gi") git-forgit ignore
abbr -a -- (string collect $forgit_checkout_file; or string collect "gcf") git-forgit checkout_file
abbr -a -- (string collect $forgit_checkout_branch; or string collect "gcb") git-forgit checkout_branch
Expand Down
6 changes: 6 additions & 0 deletions forgit.plugin.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ forgit::diff() {
"$FORGIT" diff "$@"
}

forgit::show() {
"$FORGIT" show "$@"
}

forgit::add() {
"$FORGIT" add "$@"
}
Expand Down Expand Up @@ -146,6 +150,7 @@ if [[ -z "$FORGIT_NO_ALIASES" ]]; then
export forgit_log="${forgit_log:-glo}"
export forgit_reflog="${forgit_reflog:-grl}"
export forgit_diff="${forgit_diff:-gd}"
export forgit_show="${forgit_show:-gso}"
export forgit_ignore="${forgit_ignore:-gi}"
export forgit_checkout_file="${forgit_checkout_file:-gcf}"
export forgit_checkout_branch="${forgit_checkout_branch:-gcb}"
Expand All @@ -166,6 +171,7 @@ if [[ -z "$FORGIT_NO_ALIASES" ]]; then
alias "${forgit_log}"='forgit::log'
alias "${forgit_reflog}"='forgit::reflog'
alias "${forgit_diff}"='forgit::diff'
alias "${forgit_show}"='forgit::show'
alias "${forgit_ignore}"='forgit::ignore'
alias "${forgit_checkout_file}"='forgit::checkout::file'
alias "${forgit_checkout_branch}"='forgit::checkout::branch'
Expand Down