{"thread":{"id":"17460","subject":"[TOY PATCH] grep: Add the option '--show-in-pager'","startedAt":"2009-01-30T16:04:32Z","lastAt":"2009-01-30T16:04:32Z","messageCount":1,"participants":["Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"102609","messageId":"alpine.DEB.1.00.0901301702130.3586@pacific.mpi-cbg.de","threadId":"17460","inReplyTo":"cover.1233330920u.git.johannes.schindelin@gmx.de","subject":"[TOY PATCH] grep: Add the option '--show-in-pager'","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-01-30T16:04:32Z","receivedAt":"2009-01-30T16:04:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"This adds an option to open the matching files in the pager, and if the\npager happens to be \"less\" and there is only one grep pattern, it also\njumps to the first match right away.\n\nSo, 'git grep -p abc' is a short form for 'less +/abc $(grep -l abc)'\nexcept that it works also with spaces in file names, and it does not\nstart the pager if there was no matching file.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tYes, the name '--show-in-pager' sucks, but I have no idea how to \n\tmake the intention of the option clearer.\n\n builtin-grep.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++\n git.c          |    2 +-\n grep.c         |    6 +++++-\n grep.h         |    1 +\n 4 files changed, 57 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex bebf15c..9d17cea 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -11,6 +11,7 @@\n #include \"tree-walk.h\"\n #include \"builtin.h\"\n #include \"grep.h\"\n+#include \"string-list.h\"\n \n #ifndef NO_EXTERNAL_GREP\n #ifdef __unix__\n@@ -379,6 +380,19 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)\n }\n #endif\n \n+static void run_pager(struct grep_opt *opt)\n+{\n+\tchar **argv = xmalloc(sizeof(const char *)\n+\t\t\t* (opt->collect_file_names->nr + 1));\n+\tint i;\n+\n+\tfor (i = 0; i < opt->collect_file_names->nr; i++)\n+\t\targv[i] = opt->collect_file_names->items[i].string;\n+\targv[opt->collect_file_names->nr] = NULL;\n+\n+\texecvp(argv[0], argv);\n+}\n+\n static int grep_cache(struct grep_opt *opt, const char **paths, int cached)\n {\n \tint hit = 0;\n@@ -424,6 +438,8 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)\n \t\t\tnr--; /* compensate for loop control */\n \t\t}\n \t}\n+\tif (hit && opt->collect_file_names)\n+\t\trun_pager(opt);\n \tfree_grep_patterns(opt);\n \treturn hit;\n }\n@@ -525,6 +541,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \tstruct grep_opt opt;\n \tstruct object_array list = { 0, 0, NULL };\n \tconst char **paths = NULL;\n+\tstruct string_list show_in_pager = { NULL, 0, 0, 1 };\n \tint i;\n \n \tmemset(&opt, 0, sizeof(opt));\n@@ -613,6 +630,19 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\topt.unmatch_name_only = 1;\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!strcmp(\"-p\", arg) ||\n+\t\t    !strcmp(\"--show-in-pager\", arg)) {\n+\t\t\tconst char *pager = getenv(\"GIT_PAGER\");\n+\t\t\tif (!pager)\n+\t\t\t\tpager = getenv(\"PAGER\");\n+\t\t\tif (!pager)\n+\t\t\t\tpager = \"less\";\n+\t\t\tbuiltin_grep = 1;\n+\t\t\topt.name_only = 1;\n+\t\t\topt.collect_file_names = &show_in_pager;\n+\t\t\tstring_list_append(pager, &show_in_pager);\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(\"-z\", arg) ||\n \t\t    !strcmp(\"--null\", arg)) {\n \t\t\topt.null_following_name = 1;\n@@ -802,6 +832,24 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\tpaths[1] = NULL;\n \t}\n \n+\tif (show_in_pager.nr && opt.pattern_list && !opt.pattern_list->next) {\n+\t\tconst char *pager = show_in_pager.items[0].string;\n+\t\tint len = strlen(pager);\n+\n+\t\tif (len > 4 && is_dir_sep(pager[len - 5]))\n+\t\t\tpager += len - 4;\n+\n+\t\tif (!strcmp(\"less\", pager)) {\n+\t\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\t\tstrbuf_addf(&buf, \"+/%s\", opt.pattern_list->pattern);\n+\t\t\tstring_list_append(buf.buf, &show_in_pager);\n+\t\t\tstrbuf_release(&buf);\n+\t\t}\n+\t}\n+\n+\tif (!show_in_pager.nr)\n+\t\tsetup_pager();\n+\n \tif (!list.nr) {\n \t\tif (!cached)\n \t\t\tsetup_work_tree();\n@@ -817,6 +865,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\tif (grep_object(&opt, paths, real_obj, list.objects[i].name))\n \t\t\thit = 1;\n \t}\n+\tif (hit && show_in_pager.nr)\n+\t\trun_pager(&opt);\n \tfree_grep_patterns(&opt);\n \treturn !hit;\n }\ndiff --git a/git.c b/git.c\nindex 3c07567..dbd86ba 100644\n--- a/git.c\n+++ b/git.c\n@@ -305,7 +305,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n \t\t{ \"gc\", cmd_gc, RUN_SETUP },\n \t\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n-\t\t{ \"grep\", cmd_grep, RUN_SETUP | USE_PAGER },\n+\t\t{ \"grep\", cmd_grep, RUN_SETUP },\n \t\t{ \"help\", cmd_help },\n #ifndef NO_CURL\n \t\t{ \"http-fetch\", cmd_http_fetch, RUN_SETUP },\ndiff --git a/grep.c b/grep.c\nindex 062b2b6..051f78d 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"grep.h\"\n #include \"xdiff-interface.h\"\n+#include \"string-list.h\"\n \n void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)\n {\n@@ -265,7 +266,10 @@ static void show_line(struct grep_opt *opt, const char *bol, const char *eol,\n \n static void show_name(struct grep_opt *opt, const char *name)\n {\n-\tprintf(\"%s%c\", name, opt->null_following_name ? '\\0' : '\\n');\n+\tif (opt->collect_file_names)\n+\t\tstring_list_append(name, opt->collect_file_names);\n+\telse\n+\t\tprintf(\"%s%c\", name, opt->null_following_name ? '\\0' : '\\n');\n }\n \n static int fixmatch(const char *pattern, char *line, regmatch_t *match)\ndiff --git a/grep.h b/grep.h\nindex 5102ce3..2b5aa06 100644\n--- a/grep.h\n+++ b/grep.h\n@@ -79,6 +79,7 @@ struct grep_opt {\n \tint regflags;\n \tunsigned pre_context;\n \tunsigned post_context;\n+\tstruct string_list *collect_file_names;\n };\n \n extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);\n-- \n1.6.1.2.531.g6f52\n"}]}