Teach 'git-grep(1)' a new option, '--column', to show the column
number of the first match on a non-context line. This makes it possible
to teach 'contrib/git-jump/git-jump' how to seek to the first matching
position of a grep match in your editor, and allows similar additional
scripting capabilities.

For example:

  $ git grep -n --column foo | head -n3
  .clang-format:51:14:# myFunction(foo, bar, baz);
  .clang-format:64:7:# int foo();
  .clang-format:75:8:# void foo()

Signed-off-by: Taylor Blau <m...@ttaylorr.com>
---
 Documentation/git-grep.txt |  6 ++-
 builtin/grep.c             |  1 +
 t/t7810-grep.sh            | 95 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 312409a607..31dc0392a6 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -13,7 +13,7 @@ SYNOPSIS
           [-v | --invert-match] [-h|-H] [--full-name]
           [-E | --extended-regexp] [-G | --basic-regexp]
           [-P | --perl-regexp]
-          [-F | --fixed-strings] [-n | --line-number]
+          [-F | --fixed-strings] [-n | --line-number] [--column]
           [-l | --files-with-matches] [-L | --files-without-match]
           [(-O | --open-files-in-pager) [<pager>]]
           [-z | --null]
@@ -169,6 +169,10 @@ providing this option will cause it to die.
 --line-number::
        Prefix the line number to matching lines.
 
+--column::
+       Prefix the 1-indexed byte-offset of the first match from the start of 
the
+       matching line.
+
 -l::
 --files-with-matches::
 --name-only::
diff --git a/builtin/grep.c b/builtin/grep.c
index ee753a403e..61bcaf6e58 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -828,6 +828,7 @@ int cmd_grep(int argc, const char **argv, const char 
*prefix)
                            GREP_PATTERN_TYPE_PCRE),
                OPT_GROUP(""),
                OPT_BOOL('n', "line-number", &opt.linenum, N_("show line 
numbers")),
+               OPT_BOOL(0, "column", &opt.columnnum, N_("show column number of 
first match")),
                OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show 
filenames"), 1),
                OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
                OPT_NEGBIT(0, "full-name", &opt.relative,
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 1797f632a3..9312c8daf5 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -99,6 +99,101 @@ do
                test_cmp expected actual
        '
 
+       test_expect_success "grep -w $L (with --column)" '
+               {
+                       echo ${HC}file:5:foo mmap bar
+                       echo ${HC}file:14:foo_mmap bar mmap
+                       echo ${HC}file:5:foo mmap bar_mmap
+                       echo ${HC}file:14:foo_mmap bar mmap baz
+               } >expected &&
+               git grep --column -w -e mmap $H >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep -w $L (with --column, extended OR)" '
+               {
+                       echo ${HC}file:14:foo_mmap bar mmap
+                       echo ${HC}file:19:foo_mmap bar mmap baz
+               } >expected &&
+               git grep --column -w -e mmap$ --or -e baz $H >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep -w $L (with --column, --invert)" '
+               {
+                       echo ${HC}file:1:foo mmap bar
+                       echo ${HC}file:1:foo_mmap bar
+                       echo ${HC}file:1:foo_mmap bar mmap
+                       echo ${HC}file:1:foo mmap bar_mmap
+               } >expected &&
+               git grep --column --invert -w -e baz $H -- file >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep $L (with --column, --invert, extended OR)" '
+               {
+                       echo ${HC}hello_world:6:HeLLo_world
+               } >expected &&
+               git grep --column --invert -e ll --or --not -e _ $H -- 
hello_world \
+                       >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep $L (with --column, --invert, extended AND)" '
+               {
+                       echo ${HC}hello_world:3:Hello world
+                       echo ${HC}hello_world:3:Hello_world
+                       echo ${HC}hello_world:6:HeLLo_world
+               } >expected &&
+               git grep --column --invert --not -e _ --and --not -e ll $H -- 
hello_world \
+                       >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep $L (with --column, double-negation)" '
+               {
+                       echo ${HC}file:1:foo_mmap bar mmap baz
+               } >expected &&
+               git grep --column --not \( --not -e foo --or --not -e baz \) $H 
-- file \
+                       >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep -w $L (with --column, -C)" '
+               {
+                       echo ${HC}file:5:foo mmap bar
+                       echo ${HC}file-foo_mmap bar
+                       echo ${HC}file:14:foo_mmap bar mmap
+                       echo ${HC}file:5:foo mmap bar_mmap
+                       echo ${HC}file:14:foo_mmap bar mmap baz
+               } >expected &&
+               git grep --column -w -C1 -e mmap $H >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep -w $L (with --line-number, --column)" '
+               {
+                       echo ${HC}file:1:5:foo mmap bar
+                       echo ${HC}file:3:14:foo_mmap bar mmap
+                       echo ${HC}file:4:5:foo mmap bar_mmap
+                       echo ${HC}file:5:14:foo_mmap bar mmap baz
+               } >expected &&
+               git grep -n --column -w -e mmap $H >actual &&
+               test_cmp expected actual
+       '
+
+       test_expect_success "grep -w $L (with non-extended patterns, --column)" 
'
+               {
+                       echo ${HC}file:5:foo mmap bar
+                       echo ${HC}file:10:foo_mmap bar
+                       echo ${HC}file:10:foo_mmap bar mmap
+                       echo ${HC}file:5:foo mmap bar_mmap
+                       echo ${HC}file:10:foo_mmap bar mmap baz
+               } >expected &&
+               git grep --column -w -e bar -e mmap $H >actual &&
+               test_cmp expected actual
+       '
+
        test_expect_success "grep -w $L" '
                {
                        echo ${HC}file:1:foo mmap bar
-- 
2.18.0

Reply via email to