Files
git/contrib/git-jump/git-jump
Greg Hurrell 74216ffe0a git-jump: pick a mode automatically when invoked without arguments
When `git jump` is invoked with no positional arguments (and no
arguments after `--stdout`) it currently prints usage and exits with
status 1.

But there are two situations where we can usefully infer the most
valuable and likely mode that a user would want to use, and select it
automatically:

1. When there are unmerged paths in the index, the user likely
   wants `git jump merge`.

2. When the working tree has unstaged changes, the user likely
   wants `git jump diff`.

In this commit we teach `git jump` a new "auto" mode which detects these
cases and dispatches to the corresponding mode automatically. The user
can either explicitly spell out `git jump auto`, or just leave it at
`git jump` (because "auto" is the default).

If none of the interesting cases listed above applies, then auto mode
falls back to the existing usage-and-exit behavior.

Signed-off-by: Greg Hurrell <greg.hurrell@datadoghq.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-21 23:01:04 +09:00

138 lines
3.0 KiB
Bash
Executable File

#!/bin/sh
usage() {
cat <<\EOF
usage: git jump [--stdout] <mode> [<args>]
or: git jump [--stdout]
Jump to interesting elements in an editor.
The <mode> parameter is one of the following.
With no <mode> and no <args>, it defaults to "auto".
diff: elements are diff hunks. Arguments are given to diff.
merge: elements are merge conflicts. Arguments are given to ls-files -u.
grep: elements are grep hits. Arguments are given to git grep or, if
configured, to the command in `jump.grepCmd`.
ws: elements are whitespace errors. Arguments are given to diff --check.
auto: select one of the other modes based on worktree state;
"merge" if there are unmerged paths, "diff" if there are
unstaged changes, "ws" if there are whitespace errors.
If the optional argument `--stdout` is given, print the quickfix
lines to standard output instead of feeding it to the editor.
EOF
}
open_editor() {
editor=`git var GIT_EDITOR`
case "$editor" in
*emacs*)
# Supported editor values are:
# - emacs
# - emacsclient
# - emacsclient -t
#
# Wait for completion of the asynchronously executed process
# to avoid race conditions in case of "emacsclient".
eval "$editor --eval \"(let ((buf (grep \\\"cat \$1\\\"))) (pop-to-buffer buf) (select-frame-set-input-focus (selected-frame)) (while (get-buffer-process buf) (sleep-for 0.1)))\""
;;
*)
# assume anything else is vi-compatible
eval "$editor -q \$1"
;;
esac
}
mode_diff() {
git diff --no-prefix --relative "$@" |
perl -ne '
if (m{^\+\+\+ (.*?)\t?$}) { $file = $1 eq "/dev/null" ? undef : $1; next }
defined($file) or next;
if (m/^@@ .*?\+(\d+)/) { $line = $1; next }
defined($line) or next;
if (/^ /) { $line++; next }
if (/^[-+]\s*(.*)/) {
print "$file:$line:1: $1\n";
$line = undef;
}
'
}
mode_merge() {
git ls-files -u "$@" |
perl -pe 's/^.*?\t//' |
sort -u |
while IFS= read fn; do
grep -Hn '^<<<<<<<' "$fn"
done
}
# Grep -n generates nice quickfix-looking lines by itself,
# but let's clean up extra whitespace, so they look better if the
# editor shows them to us in the status bar.
mode_grep() {
cmd=$(git config jump.grepCmd)
test -n "$cmd" || cmd="git grep -n --column"
$cmd "$@" |
perl -pe '
s/[ \t]+/ /g;
s/^ *//;
'
}
mode_ws() {
git diff --check "$@"
}
mode_auto() {
if test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" != "true"; then
usage >&2
exit 1
fi
if test -n "$(git ls-files -u "$@")"; then
mode_merge "$@"
elif ! git diff --quiet "$@"; then
mode_diff "$@"
else
usage >&2
exit 1
fi
}
use_stdout=
while test $# -gt 0; do
case "$1" in
--stdout)
use_stdout=t
;;
--*)
usage >&2
exit 1
;;
*)
break
;;
esac
shift
done
if test $# -lt 1; then
set -- auto
fi
mode=$1; shift
type "mode_$mode" >/dev/null 2>&1 || { usage >&2; exit 1; }
if test "$use_stdout" = "t"; then
"mode_$mode" "$@"
exit 0
fi
trap 'rm -f "$tmp"' 0 1 2 3 15
tmp=`mktemp -t git-jump.XXXXXX` || exit 1
"mode_$mode" "$@" >"$tmp"
test -s "$tmp" || exit 0
open_editor "$tmp"