1111#include "tree-walk.h"
1212#include "builtin.h"
1313#include "parse-options.h"
14+ #include "string-list.h"
15+ #include "run-command.h"
1416#include "userdiff.h"
1517#include "grep.h"
1618#include "quote.h"
@@ -556,6 +558,33 @@ static int grep_file(struct grep_opt *opt, const char *filename)
556558 }
557559}
558560
561+ static void append_path (struct grep_opt * opt , const void * data , size_t len )
562+ {
563+ struct string_list * path_list = opt -> output_priv ;
564+
565+ if (len == 1 && * (const char * )data == '\0' )
566+ return ;
567+ string_list_append (xstrndup (data , len ), path_list );
568+ }
569+
570+ static void run_pager (struct grep_opt * opt , const char * prefix )
571+ {
572+ struct string_list * path_list = opt -> output_priv ;
573+ const char * * argv = xmalloc (sizeof (const char * ) * (path_list -> nr + 1 ));
574+ int i , status ;
575+
576+ for (i = 0 ; i < path_list -> nr ; i ++ )
577+ argv [i ] = path_list -> items [i ].string ;
578+ argv [path_list -> nr ] = NULL ;
579+
580+ if (prefix && chdir (prefix ))
581+ die ("Failed to chdir: %s" , prefix );
582+ status = run_command_v_opt (argv , RUN_USING_SHELL );
583+ if (status )
584+ exit (status );
585+ free (argv );
586+ }
587+
559588static int grep_cache (struct grep_opt * opt , const char * * paths , int cached )
560589{
561590 int hit = 0 ;
@@ -799,9 +828,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
799828 int cached = 0 ;
800829 int seen_dashdash = 0 ;
801830 int external_grep_allowed__ignored ;
831+ int show_in_pager = 0 ;
802832 struct grep_opt opt ;
803833 struct object_array list = { 0 , 0 , NULL };
804834 const char * * paths = NULL ;
835+ struct string_list path_list = { NULL , 0 , 0 , 0 };
805836 int i ;
806837 int dummy ;
807838 int nongit = 0 , use_index = 1 ;
@@ -885,6 +916,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
885916 OPT_BOOLEAN (0 , "all-match" , & opt .all_match ,
886917 "show only matches from files that match all patterns" ),
887918 OPT_GROUP ("" ),
919+ OPT_BOOLEAN ('O' , "open-files-in-pager" , & show_in_pager ,
920+ "show matching files in the pager" ),
888921 OPT_BOOLEAN (0 , "ext-grep" , & external_grep_allowed__ignored ,
889922 "allow calling of grep(1) (ignored by this build)" ),
890923 { OPTION_CALLBACK , 0 , "help-all" , & options , NULL , "show usage" ,
@@ -960,6 +993,20 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
960993 argc -- ;
961994 }
962995
996+ if (show_in_pager ) {
997+ const char * pager = git_pager (1 );
998+ if (!pager ) {
999+ show_in_pager = 0 ;
1000+ } else {
1001+ opt .name_only = 1 ;
1002+ opt .null_following_name = 1 ;
1003+ opt .output_priv = & path_list ;
1004+ opt .output = append_path ;
1005+ string_list_append (pager , & path_list );
1006+ use_threads = 0 ;
1007+ }
1008+ }
1009+
9631010 if (!opt .pattern_list )
9641011 die ("no pattern given." );
9651012 if (!opt .fixed && opt .ignore_case )
@@ -1016,6 +1063,30 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10161063 paths [1 ] = NULL ;
10171064 }
10181065
1066+ if (show_in_pager && (cached || list .nr ))
1067+ die ("--open-files-in-pager only works on the worktree" );
1068+
1069+ if (show_in_pager && opt .pattern_list && !opt .pattern_list -> next ) {
1070+ const char * pager = path_list .items [0 ].string ;
1071+ int len = strlen (pager );
1072+
1073+ if (len > 4 && is_dir_sep (pager [len - 5 ]))
1074+ pager += len - 4 ;
1075+
1076+ if (!strcmp ("less" , pager ) || !strcmp ("vi" , pager )) {
1077+ struct strbuf buf = STRBUF_INIT ;
1078+ strbuf_addf (& buf , "+/%s%s" ,
1079+ strcmp ("less" , pager ) ? "" : "*" ,
1080+ opt .pattern_list -> pattern );
1081+ string_list_append (buf .buf , & path_list );
1082+ strbuf_detach (& buf , NULL );
1083+ }
1084+ }
1085+
1086+ if (!show_in_pager )
1087+ setup_pager ();
1088+
1089+
10191090 if (!use_index ) {
10201091 if (cached )
10211092 die ("--cached cannot be used with --no-index." );
@@ -1035,6 +1106,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10351106
10361107 if (use_threads )
10371108 hit |= wait_all ();
1109+ if (hit && show_in_pager )
1110+ run_pager (& opt , prefix );
10381111 free_grep_patterns (& opt );
10391112 return !hit ;
10401113}
0 commit comments