11
11
#include "tree-walk.h"
12
12
#include "builtin.h"
13
13
#include "parse-options.h"
14
+ #include "string-list.h"
15
+ #include "run-command.h"
14
16
#include "userdiff.h"
15
17
#include "grep.h"
16
18
#include "quote.h"
@@ -556,6 +558,33 @@ static int grep_file(struct grep_opt *opt, const char *filename)
556
558
}
557
559
}
558
560
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 (path_list , xstrndup (data , len ));
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
+
559
588
static int grep_cache (struct grep_opt * opt , const char * * paths , int cached )
560
589
{
561
590
int hit = 0 ;
@@ -590,7 +619,6 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
590
619
if (hit && opt -> status_only )
591
620
break ;
592
621
}
593
- free_grep_patterns (opt );
594
622
return hit ;
595
623
}
596
624
@@ -675,6 +703,25 @@ static int grep_object(struct grep_opt *opt, const char **paths,
675
703
die ("unable to grep from object of type %s" , typename (obj -> type ));
676
704
}
677
705
706
+ static int grep_objects (struct grep_opt * opt , const char * * paths ,
707
+ const struct object_array * list )
708
+ {
709
+ unsigned int i ;
710
+ int hit = 0 ;
711
+ const unsigned int nr = list -> nr ;
712
+
713
+ for (i = 0 ; i < nr ; i ++ ) {
714
+ struct object * real_obj ;
715
+ real_obj = deref_tag (list -> objects [i ].item , NULL , 0 );
716
+ if (grep_object (opt , paths , real_obj , list -> objects [i ].name )) {
717
+ hit = 1 ;
718
+ if (opt -> status_only )
719
+ break ;
720
+ }
721
+ }
722
+ return hit ;
723
+ }
724
+
678
725
static int grep_directory (struct grep_opt * opt , const char * * paths )
679
726
{
680
727
struct dir_struct dir ;
@@ -689,7 +736,6 @@ static int grep_directory(struct grep_opt *opt, const char **paths)
689
736
if (hit && opt -> status_only )
690
737
break ;
691
738
}
692
- free_grep_patterns (opt );
693
739
return hit ;
694
740
}
695
741
@@ -786,9 +832,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
786
832
int cached = 0 ;
787
833
int seen_dashdash = 0 ;
788
834
int external_grep_allowed__ignored ;
835
+ const char * show_in_pager = NULL , * default_pager = "dummy" ;
789
836
struct grep_opt opt ;
790
837
struct object_array list = { 0 , 0 , NULL };
791
838
const char * * paths = NULL ;
839
+ struct string_list path_list = { NULL , 0 , 0 , 0 };
792
840
int i ;
793
841
int dummy ;
794
842
int nongit = 0 , use_index = 1 ;
@@ -872,6 +920,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
872
920
OPT_BOOLEAN (0 , "all-match" , & opt .all_match ,
873
921
"show only matches from files that match all patterns" ),
874
922
OPT_GROUP ("" ),
923
+ { OPTION_STRING , 'O' , "open-files-in-pager" , & show_in_pager ,
924
+ "pager" , "show matching files in the pager" ,
925
+ PARSE_OPT_OPTARG , NULL , (intptr_t )default_pager },
875
926
OPT_BOOLEAN (0 , "ext-grep" , & external_grep_allowed__ignored ,
876
927
"allow calling of grep(1) (ignored by this build)" ),
877
928
{ OPTION_CALLBACK , 0 , "help-all" , & options , NULL , "show usage" ,
@@ -947,6 +998,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
947
998
argc -- ;
948
999
}
949
1000
1001
+ if (show_in_pager == default_pager )
1002
+ show_in_pager = git_pager (1 );
1003
+ if (show_in_pager ) {
1004
+ opt .name_only = 1 ;
1005
+ opt .null_following_name = 1 ;
1006
+ opt .output_priv = & path_list ;
1007
+ opt .output = append_path ;
1008
+ string_list_append (& path_list , show_in_pager );
1009
+ use_threads = 0 ;
1010
+ }
1011
+
950
1012
if (!opt .pattern_list )
951
1013
die ("no pattern given." );
952
1014
if (!opt .fixed && opt .ignore_case )
@@ -1003,44 +1065,51 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1003
1065
paths [1 ] = NULL ;
1004
1066
}
1005
1067
1068
+ if (show_in_pager && (cached || list .nr ))
1069
+ die ("--open-files-in-pager only works on the worktree" );
1070
+
1071
+ if (show_in_pager && opt .pattern_list && !opt .pattern_list -> next ) {
1072
+ const char * pager = path_list .items [0 ].string ;
1073
+ int len = strlen (pager );
1074
+
1075
+ if (len > 4 && is_dir_sep (pager [len - 5 ]))
1076
+ pager += len - 4 ;
1077
+
1078
+ if (!strcmp ("less" , pager ) || !strcmp ("vi" , pager )) {
1079
+ struct strbuf buf = STRBUF_INIT ;
1080
+ strbuf_addf (& buf , "+/%s%s" ,
1081
+ strcmp ("less" , pager ) ? "" : "*" ,
1082
+ opt .pattern_list -> pattern );
1083
+ string_list_append (& path_list , buf .buf );
1084
+ strbuf_detach (& buf , NULL );
1085
+ }
1086
+ }
1087
+
1088
+ if (!show_in_pager )
1089
+ setup_pager ();
1090
+
1091
+
1006
1092
if (!use_index ) {
1007
- int hit ;
1008
1093
if (cached )
1009
1094
die ("--cached cannot be used with --no-index." );
1010
1095
if (list .nr )
1011
1096
die ("--no-index cannot be used with revs." );
1012
1097
hit = grep_directory (& opt , paths );
1013
- if (use_threads )
1014
- hit |= wait_all ();
1015
- return !hit ;
1016
- }
1017
-
1018
- if (!list .nr ) {
1019
- int hit ;
1098
+ } else if (!list .nr ) {
1020
1099
if (!cached )
1021
1100
setup_work_tree ();
1022
1101
1023
1102
hit = grep_cache (& opt , paths , cached );
1024
- if (use_threads )
1025
- hit |= wait_all ();
1026
- return !hit ;
1027
- }
1028
-
1029
- if (cached )
1030
- die ("both --cached and trees are given." );
1031
-
1032
- for (i = 0 ; i < list .nr ; i ++ ) {
1033
- struct object * real_obj ;
1034
- real_obj = deref_tag (list .objects [i ].item , NULL , 0 );
1035
- if (grep_object (& opt , paths , real_obj , list .objects [i ].name )) {
1036
- hit = 1 ;
1037
- if (opt .status_only )
1038
- break ;
1039
- }
1103
+ } else {
1104
+ if (cached )
1105
+ die ("both --cached and trees are given." );
1106
+ hit = grep_objects (& opt , paths , & list );
1040
1107
}
1041
1108
1042
1109
if (use_threads )
1043
1110
hit |= wait_all ();
1111
+ if (hit && show_in_pager )
1112
+ run_pager (& opt , prefix );
1044
1113
free_grep_patterns (& opt );
1045
1114
return !hit ;
1046
1115
}
0 commit comments