@@ -102,6 +102,10 @@ function show_usage(): void
102102 seconds. The default value is 60 seconds, or 300 seconds when
103103 testing for memory leaks.
104104
105+ --context [n]
106+ Sets the number of lines of surrounding context to print for diffs.
107+ The default value is 3.
108+
105109 --show-[all|php|skip|clean|exp|diff|out|mem]
106110 Show 'all' files, 'php' test file, 'skip' or 'clean' file. You
107111 can also use this to show the output 'out', the expected result
@@ -146,6 +150,7 @@ function main(): void
146150 $ user_tests , $ valgrind , $ sum_results , $ shuffle , $ file_cache ;
147151 // Parallel testing
148152 global $ workers , $ workerID ;
153+ global $ context_line_count ;
149154
150155 define ('IS_WINDOWS ' , substr (PHP_OS , 0 , 3 ) == "WIN " );
151156
@@ -400,6 +405,7 @@ function main(): void
400405 $ file_cache = null ;
401406 $ shuffle = false ;
402407 $ workers = null ;
408+ $ context_line_count = 3 ;
403409
404410 $ cfgtypes = ['show ' , 'keep ' ];
405411 $ cfgfiles = ['skip ' , 'php ' , 'clean ' , 'out ' , 'diff ' , 'exp ' , 'mem ' ];
@@ -568,6 +574,13 @@ function main(): void
568574 case '--set-timeout ' :
569575 $ environment ['TEST_TIMEOUT ' ] = $ argv [++$ i ];
570576 break ;
577+ case '--context ' :
578+ $ context_line_count = $ argv [++$ i ] ?? '' ;
579+ if (!preg_match ('/^\d+$/ ' , $ context_line_count )) {
580+ error ("' $ context_line_count' is not a valid number of lines of context, try e.g. --context 3 for 3 lines " );
581+ }
582+ $ context_line_count = intval ($ context_line_count , 10 );
583+ break ;
571584 case '--show-all ' :
572585 foreach ($ cfgfiles as $ file ) {
573586 $ cfg ['show ' ][$ file ] = true ;
@@ -2890,15 +2903,22 @@ function count_array_diff(
28902903
28912904function generate_array_diff (array $ ar1 , array $ ar2 , bool $ is_reg , array $ w ): array
28922905{
2906+ global $ context_line_count ;
28932907 $ idx1 = 0 ;
28942908 $ cnt1 = @count ($ ar1 );
28952909 $ idx2 = 0 ;
28962910 $ cnt2 = @count ($ ar2 );
28972911 $ diff = [];
28982912 $ old1 = [];
28992913 $ old2 = [];
2914+ $ number_len = max (3 , strlen ((string )max ($ cnt1 + 1 , $ cnt2 + 1 )));
2915+ $ line_number_spec = '%0 ' . $ number_len . 'd ' ;
2916+
2917+ /** Mapping from $idx2 to $idx1, including indexes of idx2 that are identical to idx1 as well as entries that don't have matches */
2918+ $ mapping = [];
29002919
29012920 while ($ idx1 < $ cnt1 && $ idx2 < $ cnt2 ) {
2921+ $ mapping [$ idx2 ] = $ idx1 ;
29022922 if (comp_line ($ ar1 [$ idx1 ], $ ar2 [$ idx2 ], $ is_reg )) {
29032923 $ idx1 ++;
29042924 $ idx2 ++;
@@ -2908,49 +2928,90 @@ function generate_array_diff(array $ar1, array $ar2, bool $is_reg, array $w): ar
29082928 $ c2 = @count_array_diff ($ ar1 , $ ar2 , $ is_reg , $ w , $ idx1 , $ idx2 + 1 , $ cnt1 , $ cnt2 , 10 );
29092929
29102930 if ($ c1 > $ c2 ) {
2911- $ old1 [$ idx1 ] = sprintf ("%03d - " , $ idx1 + 1 ) . $ w [$ idx1 ++];
2931+ $ old1 [$ idx1 ] = sprintf ("{ $ line_number_spec } - " , $ idx1 + 1 ) . $ w [$ idx1 ++];
29122932 } elseif ($ c2 > 0 ) {
2913- $ old2 [$ idx2 ] = sprintf ("%03d + " , $ idx2 + 1 ) . $ ar2 [$ idx2 ++];
2933+ $ old2 [$ idx2 ] = sprintf ("{ $ line_number_spec } + " , $ idx2 + 1 ) . $ ar2 [$ idx2 ++];
29142934 } else {
2915- $ old1 [$ idx1 ] = sprintf ("%03d - " , $ idx1 + 1 ) . $ w [$ idx1 ++];
2916- $ old2 [$ idx2 ] = sprintf ("%03d + " , $ idx2 + 1 ) . $ ar2 [$ idx2 ++];
2935+ $ old1 [$ idx1 ] = sprintf ("{ $ line_number_spec } - " , $ idx1 + 1 ) . $ w [$ idx1 ++];
2936+ $ old2 [$ idx2 ] = sprintf ("{ $ line_number_spec } + " , $ idx2 + 1 ) . $ ar2 [$ idx2 ++];
29172937 }
2938+ $ last_printed_context_line = $ idx1 ;
29182939 }
29192940 }
2941+ $ mapping [$ idx2 ] = $ idx1 ;
29202942
29212943 reset ($ old1 );
29222944 $ k1 = key ($ old1 );
29232945 $ l1 = -2 ;
29242946 reset ($ old2 );
29252947 $ k2 = key ($ old2 );
29262948 $ l2 = -2 ;
2949+ $ old_k1 = -1 ;
2950+ $ add_context_lines = function (int $ new_k1 ) use (&$ old_k1 , &$ diff , $ w , $ context_line_count , $ number_len ) {
2951+ if ($ old_k1 >= $ new_k1 || !$ context_line_count ) {
2952+ return ;
2953+ }
2954+ $ end = $ new_k1 - 1 ;
2955+ $ range_end = min ($ end , $ old_k1 + $ context_line_count );
2956+ if ($ old_k1 >= 0 ) {
2957+ while ($ old_k1 < $ range_end ) {
2958+ $ diff [] = str_repeat (' ' , $ number_len + 2 ) . $ w [$ old_k1 ++];
2959+ }
2960+ }
2961+ if ($ end - $ context_line_count > $ old_k1 ) {
2962+ $ old_k1 = $ end - $ context_line_count ;
2963+ if ($ old_k1 > 0 ) {
2964+ // Add a '--' to mark sections where the common areas were truncated
2965+ $ diff [] = '-- ' ;
2966+ }
2967+ }
2968+ $ old_k1 = max ($ old_k1 , 0 );
2969+ while ($ old_k1 < $ end ) {
2970+ $ diff [] = str_repeat (' ' , $ number_len + 2 ) . $ w [$ old_k1 ++];
2971+ }
2972+ $ old_k1 = $ new_k1 ;
2973+ };
29272974
29282975 while ($ k1 !== null || $ k2 !== null ) {
29292976 if ($ k1 == $ l1 + 1 || $ k2 === null ) {
2977+ $ add_context_lines ($ k1 );
29302978 $ l1 = $ k1 ;
29312979 $ diff [] = current ($ old1 );
2980+ $ old_k1 = $ k1 ;
29322981 $ k1 = next ($ old1 ) ? key ($ old1 ) : null ;
29332982 } elseif ($ k2 == $ l2 + 1 || $ k1 === null ) {
2983+ $ add_context_lines ($ mapping [$ k2 ]);
29342984 $ l2 = $ k2 ;
29352985 $ diff [] = current ($ old2 );
29362986 $ k2 = next ($ old2 ) ? key ($ old2 ) : null ;
2937- } elseif ($ k1 < $ k2 ) {
2987+ } elseif ($ k1 < $ mapping [$ k2 ]) {
2988+ $ add_context_lines ($ k1 );
29382989 $ l1 = $ k1 ;
29392990 $ diff [] = current ($ old1 );
29402991 $ k1 = next ($ old1 ) ? key ($ old1 ) : null ;
29412992 } else {
2993+ $ add_context_lines ($ mapping [$ k2 ]);
29422994 $ l2 = $ k2 ;
29432995 $ diff [] = current ($ old2 );
29442996 $ k2 = next ($ old2 ) ? key ($ old2 ) : null ;
29452997 }
29462998 }
29472999
29483000 while ($ idx1 < $ cnt1 ) {
2949- $ diff [] = sprintf ("%03d- " , $ idx1 + 1 ) . $ w [$ idx1 ++];
3001+ $ add_context_lines ($ idx1 + 1 );
3002+ $ diff [] = sprintf ("{$ line_number_spec }- " , $ idx1 + 1 ) . $ w [$ idx1 ++];
29503003 }
29513004
29523005 while ($ idx2 < $ cnt2 ) {
2953- $ diff [] = sprintf ("%03d+ " , $ idx2 + 1 ) . $ ar2 [$ idx2 ++];
3006+ if (isset ($ mapping [$ idx2 ])) {
3007+ $ add_context_lines ($ mapping [$ idx2 ] + 1 );
3008+ }
3009+ $ diff [] = sprintf ("{$ line_number_spec }+ " , $ idx2 + 1 ) . $ ar2 [$ idx2 ++];
3010+ }
3011+ $ add_context_lines (min ($ old_k1 + $ context_line_count + 1 , $ cnt1 + 1 ));
3012+ if ($ context_line_count && $ old_k1 < $ cnt1 + 1 ) {
3013+ // Add a '--' to mark sections where the common areas were truncated
3014+ $ diff [] = '-- ' ;
29543015 }
29553016
29563017 return $ diff ;
0 commit comments