contrib: add git-jump script

This is a small script for helping your editor jump to specific points of interest. See the README for details. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Oct 21, 2011 at 13:28 UTC 21e4631c076f4b7defcdbe3876873486352310f1
2 files changed +161
contrib/git-jump/README new
+92
@@ -0,0 +1,92 @@
1 +git-jump
2 +========
3 +
4 +Git-jump is a script for helping you jump to "interesting" parts of your
5 +project in your editor. It works by outputting a set of interesting
6 +spots in the "quickfix" format, which editors like vim can use as a
7 +queue of places to visit (this feature is usually used to jump to errors
8 +produced by a compiler). For example, given a diff like this:
9 +
10 +------------------------------------
11 +diff --git a/foo.c b/foo.c
12 +index a655540..5a59044 100644
13 +--- a/foo.c
14 ++++ b/foo.c
15 +@@ -1,3 +1,3 @@
16 + int main(void) {
17 +- printf("hello word!\n");
18 ++ printf("hello world!\n");
19 + }
20 +-----------------------------------
21 +
22 +git-jump will feed this to the editor:
23 +
24 +-----------------------------------
25 +foo.c:2: printf("hello word!\n");
26 +-----------------------------------
27 +
28 +Obviously this trivial case isn't that interesting; you could just open
29 +`foo.c` yourself. But when you have many changes scattered across a
30 +project, you can use the editor's support to "jump" from point to point.
31 +
32 +Git-jump can generate three types of interesting lists:
33 +
34 + 1. The beginning of any diff hunks.
35 +
36 + 2. The beginning of any merge conflict markers.
37 +
38 + 3. Any grep matches.
39 +
40 +
41 +Using git-jump
42 +--------------
43 +
44 +To use it, just drop git-jump in your PATH, and then invoke it like
45 +this:
46 +
47 +--------------------------------------------------
48 +# jump to changes not yet staged for commit
49 +git jump diff
50 +
51 +# jump to changes that are staged for commit; you can give
52 +# arbitrary diff options
53 +git jump diff --cached
54 +
55 +# jump to merge conflicts
56 +git jump merge
57 +
58 +# jump to all instances of foo_bar
59 +git jump grep foo_bar
60 +
61 +# same as above, but case-insensitive; you can give
62 +# arbitrary grep options
63 +git jump grep -i foo_bar
64 +--------------------------------------------------
65 +
66 +
67 +Related Programs
68 +----------------
69 +
70 +You can accomplish some of the same things with individual tools. For
71 +example, you can use `git mergetool` to start vimdiff on each unmerged
72 +file. `git jump merge` is for the vim-wielding luddite who just wants to
73 +jump straight to the conflict text with no fanfare.
74 +
75 +As of git v1.7.2, `git grep` knows the `--open-files-in-pager` option,
76 +which does something similar to `git jump grep`. However, it is limited
77 +to positioning the cursor to the correct line in only the first file,
78 +leaving you to locate subsequent hits in that file or other files using
79 +the editor or pager. By contrast, git-jump provides the editor with a
80 +complete list of files and line numbers for each match.
81 +
82 +
83 +Limitations
84 +-----------
85 +
86 +This scripts was written and tested with vim. Given that the quickfix
87 +format is the same as what gcc produces, I expect emacs users have a
88 +similar feature for iterating through the list, but I know nothing about
89 +how to activate it.
90 +
91 +The shell snippets to generate the quickfix lines will almost certainly
92 +choke on filenames with exotic characters (like newlines).
contrib/git-jump/git-jump new
+69
@@ -0,0 +1,69 @@
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 +EOF
16 +}
17 +
18 +open_editor() {
19 + editor=`git var GIT_EDITOR`
20 + eval "$editor -q \$1"
21 +}
22 +
23 +mode_diff() {
24 + git diff --relative "$@" |
25 + perl -ne '
26 + if (m{^\+\+\+ b/(.*)}) { $file = $1; next }
27 + defined($file) or next;
28 + if (m/^@@ .*\+(\d+)/) { $line = $1; next }
29 + defined($line) or next;
30 + if (/^ /) { $line++; next }
31 + if (/^[-+]\s*(.*)/) {
32 + print "$file:$line: $1\n";
33 + $line = undef;
34 + }
35 + '
36 +}
37 +
38 +mode_merge() {
39 + git ls-files -u |
40 + perl -pe 's/^.*?\t//' |
41 + sort -u |
42 + while IFS= read fn; do
43 + grep -Hn '^<<<<<<<' "$fn"
44 + done
45 +}
46 +
47 +# Grep -n generates nice quickfix-looking lines by itself,
48 +# but let's clean up extra whitespace, so they look better if the
49 +# editor shows them to us in the status bar.
50 +mode_grep() {
51 + git grep -n "$@" |
52 + perl -pe '
53 + s/[ \t]+/ /g;
54 + s/^ *//;
55 + '
56 +}
57 +
58 +if test $# -lt 1; then
59 + usage >&2
60 + exit 1
61 +fi
62 +mode=$1; shift
63 +
64 +trap 'rm -f "$tmp"' 0 1 2 3 15
65 +tmp=`mktemp -t git-jump.XXXXXX` || exit 1
66 +type "mode_$mode" >/dev/null 2>&1 || { usage >&2; exit 1; }
67 +"mode_$mode" "$@" >"$tmp"
68 +test -s "$tmp" || exit 0
69 +open_editor "$tmp"