@@ -903,6 +903,54 @@ static int edit_hunk_loop(struct add_p_state *s,
903903 }
904904}
905905
906+ #define SUMMARY_HEADER_WIDTH 20
907+ #define SUMMARY_LINE_WIDTH 80
908+ static void summarize_hunk (struct add_p_state * s , struct hunk * hunk ,
909+ struct strbuf * out )
910+ {
911+ struct hunk_header * header = & hunk -> header ;
912+ struct strbuf * plain = & s -> plain ;
913+ size_t len = out -> len , i ;
914+
915+ strbuf_addf (out , " -%lu,%lu +%lu,%lu " ,
916+ header -> old_offset , header -> old_count ,
917+ header -> new_offset , header -> new_count );
918+ if (out -> len - len < SUMMARY_HEADER_WIDTH )
919+ strbuf_addchars (out , ' ' ,
920+ SUMMARY_HEADER_WIDTH + len - out -> len );
921+ for (i = hunk -> start ; i < hunk -> end ; i = find_next_line (plain , i ))
922+ if (plain -> buf [i ] != ' ' )
923+ break ;
924+ if (i < hunk -> end )
925+ strbuf_add (out , plain -> buf + i , find_next_line (plain , i ) - i );
926+ if (out -> len - len > SUMMARY_LINE_WIDTH )
927+ strbuf_setlen (out , len + SUMMARY_LINE_WIDTH );
928+ strbuf_complete_line (out );
929+ }
930+
931+ #define DISPLAY_HUNKS_LINES 20
932+ static size_t display_hunks (struct add_p_state * s ,
933+ struct file_diff * file_diff , size_t start_index )
934+ {
935+ size_t end_index = start_index + DISPLAY_HUNKS_LINES ;
936+
937+ if (end_index > file_diff -> hunk_nr )
938+ end_index = file_diff -> hunk_nr ;
939+
940+ while (start_index < end_index ) {
941+ struct hunk * hunk = file_diff -> hunk + start_index ++ ;
942+
943+ strbuf_reset (& s -> buf );
944+ strbuf_addf (& s -> buf , "%c%2d: " , hunk -> use == USE_HUNK ? '+'
945+ : hunk -> use == SKIP_HUNK ? '-' : ' ' ,
946+ (int )start_index );
947+ summarize_hunk (s , hunk , & s -> buf );
948+ fputs (s -> buf .buf , stdout );
949+ }
950+
951+ return end_index ;
952+ }
953+
906954static const char help_patch_text [] =
907955N_ ("y - stage this hunk\n"
908956 "n - do not stage this hunk\n"
@@ -912,6 +960,7 @@ N_("y - stage this hunk\n"
912960 "J - leave this hunk undecided, see next hunk\n"
913961 "k - leave this hunk undecided, see previous undecided hunk\n"
914962 "K - leave this hunk undecided, see previous hunk\n"
963+ "g - select a hunk to go to\n"
915964 "s - split the current hunk into smaller hunks\n"
916965 "e - manually edit the current hunk\n"
917966 "? - print help\n" );
@@ -970,6 +1019,8 @@ static int patch_update_file(struct add_p_state *s,
9701019 strbuf_addstr (& s -> buf , ",j" );
9711020 if (hunk_index + 1 < file_diff -> hunk_nr )
9721021 strbuf_addstr (& s -> buf , ",J" );
1022+ if (file_diff -> hunk_nr > 1 )
1023+ strbuf_addstr (& s -> buf , ",g" );
9731024 if (hunk -> splittable_into > 1 )
9741025 strbuf_addstr (& s -> buf , ",s" );
9751026 if (hunk_index + 1 > file_diff -> mode_change &&
@@ -1035,6 +1086,41 @@ static int patch_update_file(struct add_p_state *s,
10351086 hunk_index = undecided_next ;
10361087 else
10371088 err (s , _ ("No next hunk" ));
1089+ } else if (s -> answer .buf [0 ] == 'g' ) {
1090+ char * pend ;
1091+ unsigned long response ;
1092+
1093+ if (file_diff -> hunk_nr < 2 ) {
1094+ err (s , _ ("No other hunks to goto" ));
1095+ continue ;
1096+ }
1097+ strbuf_remove (& s -> answer , 0 , 1 );
1098+ strbuf_trim (& s -> answer );
1099+ i = hunk_index > 10 ? hunk_index - 10 : 0 ;
1100+ while (s -> answer .len == 0 ) {
1101+ i = display_hunks (s , file_diff , i );
1102+ printf ("%s" , i < file_diff -> hunk_nr ?
1103+ _ ("go to which hunk (<ret> to see "
1104+ "more)? " ) : _ ("go to which hunk? " ));
1105+ fflush (stdout );
1106+ if (strbuf_getline (& s -> answer ,
1107+ stdin ) == EOF )
1108+ break ;
1109+ strbuf_trim_trailing_newline (& s -> answer );
1110+ }
1111+
1112+ strbuf_trim (& s -> answer );
1113+ response = strtoul (s -> answer .buf , & pend , 10 );
1114+ if (* pend || pend == s -> answer .buf )
1115+ err (s , _ ("Invalid number: '%s'" ),
1116+ s -> answer .buf );
1117+ else if (0 < response && response <= file_diff -> hunk_nr )
1118+ hunk_index = response - 1 ;
1119+ else
1120+ err (s , Q_ ("Sorry, only %d hunk available." ,
1121+ "Sorry, only %d hunks available." ,
1122+ file_diff -> hunk_nr ),
1123+ (int )file_diff -> hunk_nr );
10381124 } else if (s -> answer .buf [0 ] == 's' ) {
10391125 size_t splittable_into = hunk -> splittable_into ;
10401126 if (splittable_into < 2 )
0 commit comments