@@ -16,13 +16,13 @@ $fatpacked{"DiffHighlight.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'D
16
16
# Highlight by reversing foreground and background. You could do
17
17
# other things like bold or underline if you prefer.
18
18
our @OLD_HIGHLIGHT = (
19
- color_config('color.diff-highlight.oldnormal'),
20
- color_config('color.diff-highlight.oldhighlight', "\x1b[7m "),
19
+ color_config('color.diff-highlight.oldnormal', "\e[1;31m" ),
20
+ color_config('color.diff-highlight.oldhighlight', "\e[1;31;48;5;52m "),
21
21
"\x1b[27m",
22
22
);
23
- our@NEW_HIGHLIGHT = (
24
- color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0] ),
25
- color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1] ),
23
+ our @NEW_HIGHLIGHT = (
24
+ color_config('color.diff-highlight.newnormal', "\e[1;32m" ),
25
+ color_config('color.diff-highlight.newhighlight', "\e[1;32;48;5;22m" ),
26
26
$OLD_HIGHLIGHT[2],
27
27
);
28
28
@@ -289,7 +289,7 @@ unshift @INC, bless \%fatpacked, $class;
289
289
} # END OF FATPACK CODE
290
290
291
291
292
- my $VERSION = " 1.2.0 " ;
292
+ my $VERSION = " 1.2.5 " ;
293
293
294
294
# ################################################################################
295
295
@@ -306,30 +306,42 @@ use warnings FATAL => 'all';
306
306
my $remove_file_add_header = 1;
307
307
my $remove_file_delete_header = 1;
308
308
my $clean_permission_changes = 1;
309
+ my $manually_color_lines = 0; # Usually git/hg colorizes the lines, but for raw patches we use this
309
310
my $change_hunk_indicators = git_config_boolean(" diff-so-fancy.changeHunkIndicators" ," true" );
310
311
my $strip_leading_indicators = git_config_boolean(" diff-so-fancy.stripLeadingSymbols" ," true" );
311
312
my $mark_empty_lines = git_config_boolean(" diff-so-fancy.markEmptyLines" ," true" );
312
313
my $use_unicode_dash_for_ruler = git_config_boolean(" diff-so-fancy.useUnicodeRuler" ," true" );
314
+ my $ruler_width = git_config(" diff-so-fancy.rulerWidth" , undef );
313
315
my $git_strip_prefix = git_config_boolean(" diff.noprefix" ," false" );
314
316
my $has_stdin = has_stdin();
315
317
316
- my $ansi_color_regex = qr / (\e\[ ([0-9]{1,3}(;[0-9]{1,3}){0,3})[mK])?/ ;
317
- my $dim_magenta = " \e [38;5;146m" ;
318
- my $reset_color = " \e [0m" ;
319
- my $bold = " \e [1m" ;
318
+ my $ansi_color_regex = qr / (\e\[ ([0-9]{1,3}(;[0-9]{1,3}){0,10})[mK])?/ ;
319
+ my $reset_color = color(" reset" );
320
+ my $bold = color(" bold" );
320
321
my $meta_color = " " ;
321
322
322
323
my ($file_1 ,$file_2 );
324
+ my $args = argv(); # Hashref of all the ARGV stuff
323
325
my $last_file_seen = " " ;
324
326
my $last_file_mode = " " ;
325
327
my $i = 0;
326
328
my $in_hunk = 0;
327
329
my $columns_to_remove = 0;
330
+ my $is_mercurial = 0;
331
+ my $color_forced = 0; # Has the color been forced on/off
332
+
333
+ # We try and be smart about whether we need to do line coloring, but
334
+ # this is an option to force it on/off
335
+ if ($args -> {color_on }) {
336
+ $manually_color_lines = 1;
337
+ $color_forced = 1;
338
+ } elsif ($args -> {color_off }) {
339
+ $manually_color_lines = 0;
340
+ $color_forced = 1;
341
+ }
328
342
329
343
# We only process ARGV if we don't have STDIN
330
344
if (!$has_stdin ) {
331
- my $args = argv();
332
-
333
345
if ($args -> {v } || $args -> {version }) {
334
346
die (version());
335
347
} elsif ($args -> {' set-defaults' }) {
@@ -367,8 +379,16 @@ if (!$has_stdin) {
367
379
}
368
380
};
369
381
382
+ my $line_count = 0;
370
383
while (my $line = <STDIN >) {
384
+ # If the very first line of the diff doesn't start with ANSI color we're assuming
385
+ # it's a raw patch file, and we have to color the added/removed lines ourself
386
+ if (!$color_forced && $line_count == 0 && starts_with_ansi($line )) {
387
+ $manually_color_lines = 1;
388
+ }
389
+
371
390
my $ok = DiffHighlight::handle_line($line );
391
+ $line_count ++;
372
392
}
373
393
374
394
DiffHighlight::flush();
@@ -405,8 +425,7 @@ sub do_dsf_stuff {
405
425
# ###################################################################
406
426
if ($line =~ / ^${ansi_color_regex} index / ) {
407
427
# Print the line color and then the actual line
408
- $meta_color = $1 || DiffHighlight::color_config(' color.diff.meta' ," \e [38;5;11m" );
409
- print horizontal_rule($meta_color );
428
+ $meta_color = $1 || get_config_color(" meta" );
410
429
411
430
# Get the next line without incrementing counter while loop
412
431
my $next = $input -> [0] || " " ;
@@ -427,20 +446,33 @@ sub do_dsf_stuff {
427
446
}
428
447
429
448
if ($file_1 && $file_2 ) {
449
+ print horizontal_rule($meta_color );
430
450
print $meta_color . file_change_string($file_1 ,$file_2 ) . " \n " ;
431
451
print horizontal_rule($meta_color );
432
452
}
433
453
# ########################
434
454
# Look for the filename #
435
455
# ########################
436
- } elsif ($line =~ / ^${ansi_color_regex} diff --(git|cc) (.*?)(\s |\e |$) / ) {
437
- $last_file_seen = $5 ;
456
+ # $4 $5
457
+ } elsif ($line =~ / ^${ansi_color_regex} diff (-r|--git|--cc) (.+?)(\s |\e |$) / ) {
458
+
459
+ # Mercurial looks like: diff -r 82e55d328c8c hello.c
460
+ if ($4 eq " -r" ) {
461
+ $is_mercurial = 1;
462
+ $meta_color ||= get_config_color(" meta" );
463
+ # Git looks like: diff --git a/diff-so-fancy b/diff-so-fancy
464
+ } else {
465
+ $last_file_seen = $5 ;
466
+ }
467
+
438
468
$last_file_seen =~ s | ^\w /|| ; # Remove a/ (and handle diff.mnemonicPrefix).
439
469
$in_hunk = 0;
440
470
# #######################################
441
471
# Find the first file: --- a/README.md #
442
472
# #######################################
443
473
} elsif (!$in_hunk && $line =~ / ^$ansi_color_regex --- (\w\/ )?(.+?)(\e |\t |$) / ) {
474
+ $meta_color ||= get_config_color(" meta" );
475
+
444
476
if ($git_strip_prefix ) {
445
477
my $file_dir = $4 || " " ;
446
478
$file_1 = $file_dir . $5 ;
@@ -465,6 +497,16 @@ sub do_dsf_stuff {
465
497
$last_file_seen = $file_2 ;
466
498
}
467
499
500
+ # Print out the top horizontal line of the header
501
+ print $reset_color ;
502
+ print horizontal_rule($meta_color );
503
+
504
+ # Mercurial coloring is slightly different so we need to hard reset colors
505
+ if ($is_mercurial ) {
506
+ print $reset_color ;
507
+ }
508
+
509
+ print $meta_color ;
468
510
print file_change_string($file_1 ,$file_2 ) . " \n " ;
469
511
470
512
# Print out the bottom horizontal line of the header
@@ -489,11 +531,14 @@ sub do_dsf_stuff {
489
531
}
490
532
491
533
my ($orig_offset , $orig_count , $new_offset , $new_count ) = parse_hunk_header($hunk_header );
492
- $last_file_seen = basename($last_file_seen );
534
+ # $last_file_seen = basename($last_file_seen);
493
535
494
536
# Figure out the start line
495
537
my $start_line = start_line_calc($new_offset ,$new_count );
496
- print " @ $last_file_seen :$start_line \@ ${bold}${dim_magenta}${remain}${reset_color} \n " ;
538
+
539
+ # Last function has it's own color
540
+ my $last_function_color = get_config_color(" last_function" );
541
+ print " @ $last_file_seen :$start_line \@ ${bold}${last_function_color}${remain}${reset_color} \n " ;
497
542
# ##################################
498
543
# Remove any new file permissions #
499
544
# ##################################
@@ -511,6 +556,7 @@ sub do_dsf_stuff {
511
556
# ###############################
512
557
} elsif ($line =~ / ^Binary files (\w\/ )?(.+?) and (\w\/ )?(.+?) differ/ ) {
513
558
my $change = file_change_string($2 ,$4 );
559
+ print horizontal_rule($meta_color );
514
560
print " $meta_color$change (binary)\n " ;
515
561
print horizontal_rule($meta_color );
516
562
# ####################################################
@@ -548,7 +594,7 @@ sub do_dsf_stuff {
548
594
549
595
if ($file1 && $file2 ) {
550
596
# We may not have extracted this yet, so we pull from the config if not
551
- $meta_color ||= DiffHighlight::color_config( ' color.diff.meta ' , " \e [38;5;11m " );
597
+ $meta_color ||= get_config_color( " meta " );
552
598
553
599
my $change = file_change_string($file1 ,$file2 );
554
600
@@ -714,29 +760,6 @@ sub should_print_unicode {
714
760
return 0;
715
761
}
716
762
717
- # Return git config as a hash
718
- sub get_git_config_hash {
719
- my $out = git_config_raw();
720
-
721
- my %hash ;
722
- foreach my $line (@$out ) {
723
- my ($key ,$value ) = split (" =" ,$line ,2);
724
-
725
- if ($key && $value ) {
726
- $value =~ s /\s +$// ;
727
- my @path = split (/ \. / ,$key );
728
- my $last = pop @path ;
729
- my $p = \%hash ;
730
-
731
- # Build the tree for each section
732
- $p = $p -> {$_ } ||= {} for @path ;
733
- $p -> {$last } = $value ;
734
- }
735
- }
736
-
737
- return \%hash ;
738
- }
739
-
740
763
# Try and be smart about what line the diff hunk starts on
741
764
sub start_line_calc {
742
765
my ($line_num ,$diff_context ) = @_ ;
@@ -774,7 +797,17 @@ sub strip_leading_indicators {
774
797
return $line ; # Nothing to do
775
798
}
776
799
777
- $line =~ s / ^(${ansi_color_regex})[ +-]{${columns_to_remove}}/ $1 / ;
800
+ $line =~ s / ^(${ansi_color_regex})([ +-]){${columns_to_remove}}/ $1 / ;
801
+
802
+ if ($manually_color_lines ) {
803
+ if (defined ($5 ) && $5 eq " +" ) {
804
+ my $add_line_color = get_config_color(" add_line" );
805
+ $line = $add_line_color . $line . $reset_color ;
806
+ } elsif (defined ($5 ) && $5 eq " -" ) {
807
+ my $remove_line_color = get_config_color(" remove_line" );
808
+ $line = $remove_line_color . $line . $reset_color ;
809
+ }
810
+ }
778
811
779
812
return $line ;
780
813
}
@@ -814,7 +847,7 @@ sub trim {
814
847
# Print a line of em-dash or line-drawing chars the full width of the screen
815
848
sub horizontal_rule {
816
849
my $color = $_ [0] || " " ;
817
- my $width = ` tput cols` ;
850
+ my $width = $ruler_width || ` tput cols` ;
818
851
819
852
if (is_windows()) {
820
853
$width --;
@@ -883,8 +916,9 @@ sub argv {
883
916
my $ret = {};
884
917
885
918
for (my $i = 0; $i < scalar (@ARGV ); $i ++) {
919
+
886
920
# If the item starts with "-" it's a key
887
- if ((my ($key ) = $ARGV [$i ] =~ / ^--?([a-zA-Z_] \w *) / ) && ($ARGV [$i ] !~ / ^-\w\w / )) {
921
+ if ((my ($key ) = $ARGV [$i ] =~ / ^--?([a-zA-Z_-]* \w ) $ / ) && ($ARGV [$i ] !~ / ^-\w\w / )) {
888
922
# If the next item does not start with "--" it's the value for this item
889
923
if (defined ($ARGV [$i + 1]) && ($ARGV [$i + 1] !~ / ^--?\D / )) {
890
924
$ret -> {$key } = $ARGV [$i + 1];
@@ -946,22 +980,6 @@ sub version {
946
980
return $ret ;
947
981
}
948
982
949
- # Feed the raw git input through diff-highlight to get line level highlights
950
- sub filter_stdin_through_diff_highlight {
951
- my @dh_lines ;
952
-
953
- # Have DH put the lines it's modified in an array
954
- local $DiffHighlight::line_cb = sub { push (@dh_lines ,@_ ) };
955
-
956
- while (my $line = <STDIN >) {
957
- my $ok = DiffHighlight::handle_line($line );
958
- }
959
-
960
- DiffHighlight::flush();
961
-
962
- return @dh_lines ;
963
- }
964
-
965
983
sub is_windows {
966
984
if ($^O eq ' MSWin32' or $^O eq ' dos' or $^O eq ' os2' or $^O eq ' cygwin' or $^O eq ' msys' ) {
967
985
return 1;
@@ -1029,7 +1047,8 @@ sub set_defaults {
1029
1047
return 1;
1030
1048
}
1031
1049
1032
- # String format: '115', '165_bold', '10_on_140', 'reset', 'on_173', 'red_bold', 'red_on_blue', 'blink', 'italic'
1050
+ # Borrowed from: https://www.perturb.org/display/1167_Perl_ANSI_colors.html
1051
+ # String format: '115', '165_bold', '10_on_140', 'reset', 'on_173', 'red', 'white_on_blue'
1033
1052
sub color {
1034
1053
my $str = shift ();
1035
1054
@@ -1038,15 +1057,15 @@ sub color {
1038
1057
1039
1058
# Some predefined colors
1040
1059
my %color_map = qw( red 160 blue 21 green 34 yellow 226 orange 214 purple 93 white 15 black 0) ;
1041
- $str =~ s / $_ / $ color_map {$_ } / g for keys %color_map ;
1060
+ $str =~ s | ([A-Za-z]+) | $ color_map {$1 } // $1 | eg ;
1042
1061
1043
1062
# Get foreground/background and any commands
1044
- my ($fc ,$cmd ) = $str =~ / ^ (\d +)?_?(\w +)?/g ;
1045
- my ($bc ) = $str =~ / on_?(\d +)$ /g ;
1063
+ my ($fc ,$cmd ) = $str =~ / (\d +)?_?(\w +)?/g ;
1064
+ my ($bc ) = $str =~ / on_?(\d +)/g ;
1046
1065
1047
1066
# Some predefined commands
1048
1067
my %cmd_map = qw( bold 1 italic 3 underline 4 blink 5 inverse 7) ;
1049
- my $cmd_num = $cmd_map {$cmd || 0};
1068
+ my $cmd_num = $cmd_map {$cmd // 0};
1050
1069
1051
1070
my $ret = ' ' ;
1052
1071
if ($cmd_num ) { $ret .= " \e [${cmd_num} m" ; }
@@ -1056,4 +1075,48 @@ sub color {
1056
1075
return $ret ;
1057
1076
}
1058
1077
1078
+ # Get colors used for various output sections (memoized)
1079
+ {
1080
+ my $static_config ;
1081
+
1082
+ sub get_config_color {
1083
+ my $str = shift ();
1084
+
1085
+ my $ret = " " ;
1086
+ if ($static_config -> {$str }) {
1087
+ return $static_config -> {$str };
1088
+ }
1089
+
1090
+ if ($str eq " meta" ) {
1091
+ # Default ANSI yellow
1092
+ $ret = DiffHighlight::color_config(' color.diff.meta' , color(11));
1093
+ } elsif ($str eq " reset" ) {
1094
+ $ret = color(" reset" );
1095
+ } elsif ($str eq " add_line" ) {
1096
+ # Default ANSI green
1097
+ $ret = DiffHighlight::color_config(' color.diff.new' , color(' bold' ) . color(2));
1098
+ } elsif ($str eq " remove_line" ) {
1099
+ # Default ANSI red
1100
+ $ret = DiffHighlight::color_config(' color.diff.old' , color(' bold' ) . color(1));
1101
+ } elsif ($str eq " last_function" ) {
1102
+ $ret = DiffHighlight::color_config(' color.diff.func' , color(146));
1103
+ }
1104
+
1105
+ # Cache (memoize) the entry for later
1106
+ $static_config -> {$str } = $ret ;
1107
+
1108
+ return $ret ;
1109
+ }
1110
+ }
1111
+
1112
+ sub starts_with_ansi {
1113
+ my $str = shift ();
1114
+
1115
+ if ($str =~ / ^$ansi_color_regex / ) {
1116
+ return 1;
1117
+ } else {
1118
+ return 0;
1119
+ }
1120
+ }
1121
+
1059
1122
# vim: tabstop=4 shiftwidth=4 noexpandtab autoindent softtabstop=4
0 commit comments