Skip to content

Commit ca73256

Browse files
committed
Merge branch 'jc/addi-color'
* jc/addi-color: config --get-colorbool: diff.color is a deprecated synonym to color.diff Color support for "git-add -i" git config --get-colorbool
2 parents 9539a56 + 69243c2 commit ca73256

File tree

10 files changed

+218
-27
lines changed

10 files changed

+218
-27
lines changed

Documentation/config.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,18 @@ color.diff.<slot>::
391391
whitespace). The values of these variables may be specified as
392392
in color.branch.<slot>.
393393

394+
color.interactive::
395+
When set to `always`, always use colors in `git add --interactive`.
396+
When false (or `never`), never. When set to `true` or `auto`, use
397+
colors only when the output is to the terminal. Defaults to false.
398+
399+
color.interactive.<slot>::
400+
Use customized color for `git add --interactive`
401+
output. `<slot>` may be `prompt`, `header`, or `help`, for
402+
three distinct types of normal output from interactive
403+
programs. The values of these variables may be specified as
404+
in color.branch.<slot>.
405+
394406
color.pager::
395407
A boolean to enable/disable colored output when the pager is in
396408
use (default is true).

Documentation/git-config.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ SYNOPSIS
2121
'git-config' [<file-option>] --remove-section name
2222
'git-config' [<file-option>] [-z|--null] -l | --list
2323
'git-config' [<file-option>] --get-color name [default]
24+
'git-config' [<file-option>] --get-colorbool name [stdout-is-tty]
2425

2526
DESCRIPTION
2627
-----------
@@ -135,6 +136,15 @@ See also <<FILES>>.
135136
output without getting confused e.g. by values that
136137
contain line breaks.
137138

139+
--get-colorbool name [stdout-is-tty]::
140+
141+
Find the color setting for `name` (e.g. `color.diff`) and output
142+
"true" or "false". `stdout-is-tty` should be either "true" or
143+
"false", and is taken into account when configuration says
144+
"auto". If `stdout-is-tty` is missing, then checks the standard
145+
output of the command itself, and exits with status 0 if color
146+
is to be used, or exits with status 1 otherwise.
147+
138148
--get-color name default::
139149

140150
Find the color configured for `name` (e.g. `color.diff.new`) and

builtin-branch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static int parse_branch_color_slot(const char *var, int ofs)
6565
static int git_branch_config(const char *var, const char *value)
6666
{
6767
if (!strcmp(var, "color.branch")) {
68-
branch_use_color = git_config_colorbool(var, value);
68+
branch_use_color = git_config_colorbool(var, value, -1);
6969
return 0;
7070
}
7171
if (!prefixcmp(var, "color.branch.")) {

builtin-config.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include "color.h"
44

55
static const char git_config_set_usage[] =
6-
"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default]";
6+
"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
77

88
static char *key;
99
static regex_t *key_regexp;
@@ -208,6 +208,57 @@ static int get_color(int argc, const char **argv)
208208
return 0;
209209
}
210210

211+
static int stdout_is_tty;
212+
static int get_colorbool_found;
213+
static int get_diff_color_found;
214+
static int git_get_colorbool_config(const char *var, const char *value)
215+
{
216+
if (!strcmp(var, get_color_slot)) {
217+
get_colorbool_found =
218+
git_config_colorbool(var, value, stdout_is_tty);
219+
}
220+
if (!strcmp(var, "diff.color")) {
221+
get_diff_color_found =
222+
git_config_colorbool(var, value, stdout_is_tty);
223+
}
224+
return 0;
225+
}
226+
227+
static int get_colorbool(int argc, const char **argv)
228+
{
229+
/*
230+
* git config --get-colorbool <slot> [<stdout-is-tty>]
231+
*
232+
* returns "true" or "false" depending on how <slot>
233+
* is configured.
234+
*/
235+
236+
if (argc == 2)
237+
stdout_is_tty = git_config_bool("command line", argv[1]);
238+
else if (argc == 1)
239+
stdout_is_tty = isatty(1);
240+
else
241+
usage(git_config_set_usage);
242+
get_colorbool_found = -1;
243+
get_diff_color_found = -1;
244+
get_color_slot = argv[0];
245+
git_config(git_get_colorbool_config);
246+
247+
if (get_colorbool_found < 0) {
248+
if (!strcmp(get_color_slot, "color.diff"))
249+
get_colorbool_found = get_diff_color_found;
250+
if (get_colorbool_found < 0)
251+
get_colorbool_found = 0;
252+
}
253+
254+
if (argc == 1) {
255+
return get_colorbool_found ? 0 : 1;
256+
} else {
257+
printf("%s\n", get_colorbool_found ? "true" : "false");
258+
return 0;
259+
}
260+
}
261+
211262
int cmd_config(int argc, const char **argv, const char *prefix)
212263
{
213264
int nongit = 0;
@@ -283,6 +334,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
283334
return 0;
284335
} else if (!strcmp(argv[1], "--get-color")) {
285336
return get_color(argc-2, argv+2);
337+
} else if (!strcmp(argv[1], "--get-colorbool")) {
338+
return get_colorbool(argc-2, argv+2);
286339
} else
287340
break;
288341
argc--;

color.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ void color_parse(const char *value, const char *var, char *dst)
116116
die("bad config value '%s' for variable '%s'", value, var);
117117
}
118118

119-
int git_config_colorbool(const char *var, const char *value)
119+
int git_config_colorbool(const char *var, const char *value, int stdout_is_tty)
120120
{
121121
if (value) {
122122
if (!strcasecmp(value, "never"))
@@ -133,7 +133,9 @@ int git_config_colorbool(const char *var, const char *value)
133133

134134
/* any normal truth value defaults to 'auto' */
135135
auto_color:
136-
if (isatty(1) || (pager_in_use && pager_use_color)) {
136+
if (stdout_is_tty < 0)
137+
stdout_is_tty = isatty(1);
138+
if (stdout_is_tty || (pager_in_use && pager_use_color)) {
137139
char *term = getenv("TERM");
138140
if (term && strcmp(term, "dumb"))
139141
return 1;

color.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
55
#define COLOR_MAXLEN 24
66

7-
int git_config_colorbool(const char *var, const char *value);
7+
int git_config_colorbool(const char *var, const char *value, int stdout_is_tty);
88
void color_parse(const char *var, const char *value, char *dst);
99
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
1010
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);

diff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ int git_diff_ui_config(const char *var, const char *value)
146146
return 0;
147147
}
148148
if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
149-
diff_use_color_default = git_config_colorbool(var, value);
149+
diff_use_color_default = git_config_colorbool(var, value, -1);
150150
return 0;
151151
}
152152
if (!strcmp(var, "diff.renames")) {

git-add--interactive.perl

Lines changed: 99 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,55 @@
11
#!/usr/bin/perl -w
22

33
use 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
655
my $patch_mode;
@@ -246,10 +295,20 @@ sub is_valid_prefix {
246295
sub 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

255314
sub 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

373432
sub singleton_prompt_help_cmd {
374-
print <<\EOF ;
433+
print colored $help_color, <<\EOF ;
375434
Prompt help:
376435
1 - select a numbered item
377436
foo - select item based on unique prefix
@@ -380,7 +439,7 @@ sub singleton_prompt_help_cmd {
380439
}
381440

382441
sub prompt_help_cmd {
383-
print <<\EOF ;
442+
print colored $help_color, <<\EOF ;
384443
Prompt help:
385444
1 - select a single item
386445
3-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+
480564
sub hunk_splittable {
481565
my ($text) = @_;
482566

@@ -671,7 +755,7 @@ sub coalesce_overlapping_hunks {
671755
}
672756

673757
sub help_patch_cmd {
674-
print <<\EOF ;
758+
print colored $help_color, <<\EOF ;
675759
y - stage this hunk
676760
n - do not stage this hunk
677761
a - 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

901980
sub quit_cmd {
@@ -904,7 +983,7 @@ sub quit_cmd {
904983
}
905984

906985
sub help_cmd {
907-
print <<\EOF ;
986+
print colored $help_color, <<\EOF ;
908987
status - show paths with changes
909988
update - add working tree state to the staged set of changes
910989
revert - revert staged set of changes back to the HEAD version

0 commit comments

Comments
 (0)