Merge branch 'jk/difftool-in-subdir'
[git] / contrib / git-jump / git-jump
1 #!/bin/sh
2
3 usage() {
4         cat <<\EOF
5 usage: git jump <mode> [<args>]
6
7 Jump to interesting elements in an editor.
8 The <mode> parameter is one of:
9
10 diff: elements are diff hunks. Arguments are given to diff.
11
12 merge: elements are merge conflicts. Arguments are ignored.
13
14 grep: elements are grep hits. Arguments are given to grep.
15
16 ws: elements are whitespace errors. Arguments are given to diff --check.
17 EOF
18 }
19
20 open_editor() {
21         editor=`git var GIT_EDITOR`
22         eval "$editor -q \$1"
23 }
24
25 mode_diff() {
26         git diff --no-prefix --relative "$@" |
27         perl -ne '
28         if (m{^\+\+\+ (.*)}) { $file = $1; next }
29         defined($file) or next;
30         if (m/^@@ .*?\+(\d+)/) { $line = $1; next }
31         defined($line) or next;
32         if (/^ /) { $line++; next }
33         if (/^[-+]\s*(.*)/) {
34                 print "$file:$line: $1\n";
35                 $line = undef;
36         }
37         '
38 }
39
40 mode_merge() {
41         git ls-files -u |
42         perl -pe 's/^.*?\t//' |
43         sort -u |
44         while IFS= read fn; do
45                 grep -Hn '^<<<<<<<' "$fn"
46         done
47 }
48
49 # Grep -n generates nice quickfix-looking lines by itself,
50 # but let's clean up extra whitespace, so they look better if the
51 # editor shows them to us in the status bar.
52 mode_grep() {
53         git grep -n "$@" |
54         perl -pe '
55         s/[ \t]+/ /g;
56         s/^ *//;
57         '
58 }
59
60 mode_ws() {
61         git diff --check "$@"
62 }
63
64 if test $# -lt 1; then
65         usage >&2
66         exit 1
67 fi
68 mode=$1; shift
69
70 trap 'rm -f "$tmp"' 0 1 2 3 15
71 tmp=`mktemp -t git-jump.XXXXXX` || exit 1
72 type "mode_$mode" >/dev/null 2>&1 || { usage >&2; exit 1; }
73 "mode_$mode" "$@" >"$tmp"
74 test -s "$tmp" || exit 0
75 open_editor "$tmp"