11# !/usr/bin/perl -w
22
33use strict;
4+ use Git;
5+
6+ # Prompt colors:
7+ my ($prompt_color , $header_color , $help_color , $normal_color );
8+ # Diff colors:
9+ my ($new_color , $old_color , $fraginfo_color , $metainfo_color , $whitespace_color );
10+
11+ my ($use_color , $diff_use_color );
12+ my $repo = Git-> repository();
13+
14+ $use_color = $repo -> get_colorbool(' color.interactive' );
15+
16+ if ($use_color ) {
17+ # Set interactive colors:
18+
19+ # Grab the 3 main colors in git color string format, with sane
20+ # (visible) defaults:
21+ $prompt_color = $repo -> get_color(" color.interactive.prompt" , " bold blue" );
22+ $header_color = $repo -> get_color(" color.interactive.header" , " bold" );
23+ $help_color = $repo -> get_color(" color.interactive.help" , " red bold" );
24+ $normal_color = $repo -> get_color(" " , " reset" );
25+
26+ # Do we also set diff colors?
27+ $diff_use_color = $repo -> get_colorbool(' color.diff' );
28+ if ($diff_use_color ) {
29+ $new_color = $repo -> get_color(" color.diff.new" , " green" );
30+ $old_color = $repo -> get_color(" color.diff.old" , " red" );
31+ $fraginfo_color = $repo -> get_color(" color.diff.frag" , " cyan" );
32+ $metainfo_color = $repo -> get_color(" color.diff.meta" , " bold" );
33+ $whitespace_color = $repo -> get_color(" color.diff.whitespace" , " normal red" );
34+ }
35+ }
36+
37+ sub colored {
38+ my $color = shift ;
39+ my $string = join (" " , @_ );
40+
41+ if ($use_color ) {
42+ # Put a color code at the beginning of each line, a reset at the end
43+ # color after newlines that are not at the end of the string
44+ $string =~ s / (\n +)(.)/ $1 $color$2 / g ;
45+ # reset before newlines
46+ $string =~ s / (\n +)/ $normal_color$1 / g ;
47+ # codes at beginning and end (if necessary):
48+ $string =~ s / ^/ $color / ;
49+ $string =~ s / $/ $normal_color / unless $string =~ / \n $ / ;
50+ }
51+ return $string ;
52+ }
453
554# command line options
655my $patch_mode ;
@@ -246,10 +295,20 @@ sub is_valid_prefix {
246295sub highlight_prefix {
247296 my $prefix = shift ;
248297 my $remainder = shift ;
249- return $remainder unless defined $prefix ;
250- return is_valid_prefix($prefix ) ?
251- " [$prefix ]$remainder " :
252- " $prefix$remainder " ;
298+
299+ if (!defined $prefix ) {
300+ return $remainder ;
301+ }
302+
303+ if (!is_valid_prefix($prefix )) {
304+ return " $prefix$remainder " ;
305+ }
306+
307+ if (!$use_color ) {
308+ return " [$prefix ]$remainder " ;
309+ }
310+
311+ return " $prompt_color$prefix$normal_color$remainder " ;
253312}
254313
255314sub list_and_choose {
@@ -266,7 +325,7 @@ sub list_and_choose {
266325 if (!$opts -> {LIST_FLAT }) {
267326 print " " ;
268327 }
269- print " $opts ->{HEADER}\n " ;
328+ print colored $header_color , " $opts ->{HEADER}\n " ;
270329 }
271330 for ($i = 0; $i < @stuff ; $i ++) {
272331 my $chosen = $chosen [$i ] ? ' *' : ' ' ;
@@ -304,7 +363,7 @@ sub list_and_choose {
304363
305364 return if ($opts -> {LIST_ONLY });
306365
307- print $opts -> {PROMPT };
366+ print colored $prompt_color , $opts -> {PROMPT };
308367 if ($opts -> {SINGLETON }) {
309368 print " > " ;
310369 }
@@ -371,7 +430,7 @@ sub list_and_choose {
371430}
372431
373432sub singleton_prompt_help_cmd {
374- print <<\EOF ;
433+ print colored $help_color , <<\EOF ;
375434Prompt help:
3764351 - select a numbered item
377436foo - select item based on unique prefix
@@ -380,7 +439,7 @@ sub singleton_prompt_help_cmd {
380439}
381440
382441sub prompt_help_cmd {
383- print <<\EOF ;
442+ print colored $help_color , <<\EOF ;
384443Prompt help:
3854441 - select a single item
3864453-5 - select a range of items
@@ -477,6 +536,31 @@ sub parse_diff {
477536 return @hunk ;
478537}
479538
539+ sub colored_diff_hunk {
540+ my ($text ) = @_ ;
541+ # return the text, so that it can be passed to print()
542+ my @ret ;
543+ for (@$text ) {
544+ if (!$diff_use_color ) {
545+ push @ret , $_ ;
546+ next ;
547+ }
548+
549+ if (/ ^\+ / ) {
550+ push @ret , colored($new_color , $_ );
551+ } elsif (/ ^\- / ) {
552+ push @ret , colored($old_color , $_ );
553+ } elsif (/ ^\@ / ) {
554+ push @ret , colored($fraginfo_color , $_ );
555+ } elsif (/ ^ / ) {
556+ push @ret , colored($normal_color , $_ );
557+ } else {
558+ push @ret , colored($metainfo_color , $_ );
559+ }
560+ }
561+ return @ret ;
562+ }
563+
480564sub hunk_splittable {
481565 my ($text ) = @_ ;
482566
@@ -671,7 +755,7 @@ sub coalesce_overlapping_hunks {
671755}
672756
673757sub help_patch_cmd {
674- print <<\EOF ;
758+ print colored $help_color , <<\EOF ;
675759y - stage this hunk
676760n - do not stage this hunk
677761a - stage this and all the remaining hunks in the file
@@ -710,9 +794,7 @@ sub patch_update_file {
710794 my ($ix , $num );
711795 my $path = shift ;
712796 my ($head , @hunk ) = parse_diff($path );
713- for (@{$head -> {TEXT }}) {
714- print ;
715- }
797+ print colored_diff_hunk($head -> {TEXT });
716798 $num = scalar @hunk ;
717799 $ix = 0;
718800
@@ -754,10 +836,8 @@ sub patch_update_file {
754836 if (hunk_splittable($hunk [$ix ]{TEXT })) {
755837 $other .= ' /s' ;
756838 }
757- for (@{$hunk [$ix ]{TEXT }}) {
758- print ;
759- }
760- print " Stage this hunk [y/n/a/d$other /?]? " ;
839+ print colored_diff_hunk($hunk [$ix ]{TEXT });
840+ print colored $prompt_color , " Stage this hunk [y/n/a/d$other /?]? " ;
761841 my $line = <STDIN >;
762842 if ($line ) {
763843 if ($line =~ / ^y/i ) {
@@ -811,7 +891,7 @@ sub patch_update_file {
811891 elsif ($other =~ / s/ && $line =~ / ^s/ ) {
812892 my @split = split_hunk($hunk [$ix ]{TEXT });
813893 if (1 < @split ) {
814- print " Split into " ,
894+ print colored $header_color , " Split into " ,
815895 scalar (@split ), " hunks.\n " ;
816896 }
817897 splice (@hunk , $ix , 1,
@@ -894,8 +974,7 @@ sub diff_cmd {
894974 HEADER => $status_head , },
895975 @mods );
896976 return if (!@them );
897- system (qw( git diff-index -p --cached HEAD --) ,
898- map { $_ -> {VALUE } } @them );
977+ system (qw( git diff -p --cached HEAD --) , map { $_ -> {VALUE } } @them );
899978}
900979
901980sub quit_cmd {
@@ -904,7 +983,7 @@ sub quit_cmd {
904983}
905984
906985sub help_cmd {
907- print <<\EOF ;
986+ print colored $help_color , <<\EOF ;
908987status - show paths with changes
909988update - add working tree state to the staged set of changes
910989revert - revert staged set of changes back to the HEAD version
0 commit comments