2006-09-08 12:03:18 +04:00
|
|
|
#include "cache.h"
|
2006-12-20 01:34:12 +03:00
|
|
|
#include "color.h"
|
2006-09-08 12:03:18 +04:00
|
|
|
|
make color.ui default to 'auto'
Most users seem to like having colors enabled, and colors can help
beginners to understand the output of some commands (e.g. notice
immediately the boundary between commits in the output of "git log").
Many tutorials tell the users to set color.ui=auto as a very first step,
which tend to indicate that color.ui=none is not the recommanded value,
hence should not be the default.
These tutorials would benefit from skipping this step and starting the
real Git manipulations earlier. Other beginners do not know about
color.ui=auto, and may not discover it by themselves, hence live with
black&white outputs while they may have preferred colors.
A few people (e.g. color-blind) prefer having no colors, but they can
easily set color.ui=never for this (and googling "disable colors in git"
already tells them how to do so), but this needs not occupy space in
beginner-oriented documentations.
A transition period with Git emitting a warning when color.ui is unset
would be possible, but the discomfort of having the warning seems
superior to the benefit: users may be surprised by the change, but not
harmed by it.
The default value is changed, and the documentation is reworded to
mention "color.ui=false" first, since the primary use of color.ui after
this change is to disable colors, not to enable it.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-06-10 18:26:09 +04:00
|
|
|
static int git_use_color_default = GIT_COLOR_AUTO;
|
2011-08-18 09:03:48 +04:00
|
|
|
int color_stdout_is_tty = -1;
|
2008-02-18 10:26:03 +03:00
|
|
|
|
2011-04-05 09:40:23 +04:00
|
|
|
/*
|
|
|
|
* The list of available column colors.
|
|
|
|
*/
|
|
|
|
const char *column_colors_ansi[] = {
|
|
|
|
GIT_COLOR_RED,
|
|
|
|
GIT_COLOR_GREEN,
|
|
|
|
GIT_COLOR_YELLOW,
|
|
|
|
GIT_COLOR_BLUE,
|
|
|
|
GIT_COLOR_MAGENTA,
|
|
|
|
GIT_COLOR_CYAN,
|
|
|
|
GIT_COLOR_BOLD_RED,
|
|
|
|
GIT_COLOR_BOLD_GREEN,
|
|
|
|
GIT_COLOR_BOLD_YELLOW,
|
|
|
|
GIT_COLOR_BOLD_BLUE,
|
|
|
|
GIT_COLOR_BOLD_MAGENTA,
|
|
|
|
GIT_COLOR_BOLD_CYAN,
|
|
|
|
GIT_COLOR_RESET,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Ignore the RESET at the end when giving the size */
|
|
|
|
const int column_colors_ansi_max = ARRAY_SIZE(column_colors_ansi) - 1;
|
|
|
|
|
2006-09-08 12:03:18 +04:00
|
|
|
static int parse_color(const char *name, int len)
|
|
|
|
{
|
|
|
|
static const char * const color_names[] = {
|
|
|
|
"normal", "black", "red", "green", "yellow",
|
|
|
|
"blue", "magenta", "cyan", "white"
|
|
|
|
};
|
|
|
|
char *end;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(color_names); i++) {
|
|
|
|
const char *str = color_names[i];
|
|
|
|
if (!strncasecmp(name, str, len) && !str[len])
|
|
|
|
return i - 1;
|
|
|
|
}
|
|
|
|
i = strtol(name, &end, 10);
|
2008-02-06 15:16:08 +03:00
|
|
|
if (end - name == len && i >= -1 && i <= 255)
|
2006-09-08 12:03:18 +04:00
|
|
|
return i;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_attr(const char *name, int len)
|
|
|
|
{
|
|
|
|
static const int attr_values[] = { 1, 2, 4, 5, 7 };
|
|
|
|
static const char * const attr_names[] = {
|
|
|
|
"bold", "dim", "ul", "blink", "reverse"
|
|
|
|
};
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
|
|
|
|
const char *str = attr_names[i];
|
|
|
|
if (!strncasecmp(name, str, len) && !str[len])
|
|
|
|
return attr_values[i];
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void color_parse(const char *value, const char *var, char *dst)
|
2009-01-20 07:30:30 +03:00
|
|
|
{
|
|
|
|
color_parse_mem(value, strlen(value), var, dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
void color_parse_mem(const char *value, int value_len, const char *var,
|
|
|
|
char *dst)
|
2006-09-08 12:03:18 +04:00
|
|
|
{
|
|
|
|
const char *ptr = value;
|
2009-01-20 07:30:30 +03:00
|
|
|
int len = value_len;
|
2010-02-28 05:56:38 +03:00
|
|
|
unsigned int attr = 0;
|
2006-09-08 12:03:18 +04:00
|
|
|
int fg = -2;
|
|
|
|
int bg = -2;
|
|
|
|
|
2009-01-20 07:30:30 +03:00
|
|
|
if (!strncasecmp(value, "reset", len)) {
|
2009-02-14 00:53:40 +03:00
|
|
|
strcpy(dst, GIT_COLOR_RESET);
|
2006-09-08 12:03:18 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-02-28 05:56:38 +03:00
|
|
|
/* [fg [bg]] [attr]... */
|
2009-01-20 07:30:30 +03:00
|
|
|
while (len > 0) {
|
2006-09-08 12:03:18 +04:00
|
|
|
const char *word = ptr;
|
2009-01-20 07:30:30 +03:00
|
|
|
int val, wordlen = 0;
|
2006-09-08 12:03:18 +04:00
|
|
|
|
2009-01-20 07:30:30 +03:00
|
|
|
while (len > 0 && !isspace(word[wordlen])) {
|
|
|
|
wordlen++;
|
|
|
|
len--;
|
|
|
|
}
|
2006-09-08 12:03:18 +04:00
|
|
|
|
2009-01-20 07:30:30 +03:00
|
|
|
ptr = word + wordlen;
|
|
|
|
while (len > 0 && isspace(*ptr)) {
|
2006-09-08 12:03:18 +04:00
|
|
|
ptr++;
|
2009-01-20 07:30:30 +03:00
|
|
|
len--;
|
|
|
|
}
|
2006-09-08 12:03:18 +04:00
|
|
|
|
2009-01-20 07:30:30 +03:00
|
|
|
val = parse_color(word, wordlen);
|
2006-09-08 12:03:18 +04:00
|
|
|
if (val >= -1) {
|
|
|
|
if (fg == -2) {
|
|
|
|
fg = val;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (bg == -2) {
|
|
|
|
bg = val;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
goto bad;
|
|
|
|
}
|
2009-01-20 07:30:30 +03:00
|
|
|
val = parse_attr(word, wordlen);
|
2010-02-28 05:56:38 +03:00
|
|
|
if (0 <= val)
|
|
|
|
attr |= (1 << val);
|
|
|
|
else
|
2006-09-08 12:03:18 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
2010-02-28 05:56:38 +03:00
|
|
|
if (attr || fg >= 0 || bg >= 0) {
|
2006-09-08 12:03:18 +04:00
|
|
|
int sep = 0;
|
2010-02-28 05:56:38 +03:00
|
|
|
int i;
|
2006-09-08 12:03:18 +04:00
|
|
|
|
|
|
|
*dst++ = '\033';
|
|
|
|
*dst++ = '[';
|
2010-02-28 05:56:38 +03:00
|
|
|
|
|
|
|
for (i = 0; attr; i++) {
|
|
|
|
unsigned bit = (1 << i);
|
|
|
|
if (!(attr & bit))
|
|
|
|
continue;
|
|
|
|
attr &= ~bit;
|
|
|
|
if (sep++)
|
|
|
|
*dst++ = ';';
|
|
|
|
*dst++ = '0' + i;
|
2006-09-08 12:03:18 +04:00
|
|
|
}
|
|
|
|
if (fg >= 0) {
|
|
|
|
if (sep++)
|
|
|
|
*dst++ = ';';
|
|
|
|
if (fg < 8) {
|
|
|
|
*dst++ = '3';
|
|
|
|
*dst++ = '0' + fg;
|
|
|
|
} else {
|
|
|
|
dst += sprintf(dst, "38;5;%d", fg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bg >= 0) {
|
|
|
|
if (sep++)
|
|
|
|
*dst++ = ';';
|
|
|
|
if (bg < 8) {
|
|
|
|
*dst++ = '4';
|
|
|
|
*dst++ = '0' + bg;
|
|
|
|
} else {
|
|
|
|
dst += sprintf(dst, "48;5;%d", bg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*dst++ = 'm';
|
|
|
|
}
|
|
|
|
*dst = 0;
|
|
|
|
return;
|
|
|
|
bad:
|
2009-01-20 07:30:30 +03:00
|
|
|
die("bad color value '%.*s' for variable '%s'", value_len, value, var);
|
2006-09-08 12:03:18 +04:00
|
|
|
}
|
|
|
|
|
2011-08-18 09:03:48 +04:00
|
|
|
int git_config_colorbool(const char *var, const char *value)
|
2006-09-08 12:03:18 +04:00
|
|
|
{
|
2007-11-27 01:30:28 +03:00
|
|
|
if (value) {
|
|
|
|
if (!strcasecmp(value, "never"))
|
|
|
|
return 0;
|
|
|
|
if (!strcasecmp(value, "always"))
|
|
|
|
return 1;
|
|
|
|
if (!strcasecmp(value, "auto"))
|
color: delay auto-color decision until point of use
When we read a color value either from a config file or from
the command line, we use git_config_colorbool to convert it
from the tristate always/never/auto into a single yes/no
boolean value.
This has some timing implications with respect to starting
a pager.
If we start (or decide not to start) the pager before
checking the colorbool, everything is fine. Either isatty(1)
will give us the right information, or we will properly
check for pager_in_use().
However, if we decide to start a pager after we have checked
the colorbool, things are not so simple. If stdout is a tty,
then we will have already decided to use color. However, the
user may also have configured color.pager not to use color
with the pager. In this case, we need to actually turn off
color. Unfortunately, the pager code has no idea which color
variables were turned on (and there are many of them
throughout the code, and they may even have been manipulated
after the colorbool selection by something like "--color" on
the command line).
This bug can be seen any time a pager is started after
config and command line options are checked. This has
affected "git diff" since 89d07f7 (diff: don't run pager if
user asked for a diff style exit code, 2007-08-12). It has
also affect the log family since 1fda91b (Fix 'git log'
early pager startup error case, 2010-08-24).
This patch splits the notion of parsing a colorbool and
actually checking the configuration. The "use_color"
variables now have an additional possible value,
GIT_COLOR_AUTO. Users of the variable should use the new
"want_color()" wrapper, which will lazily determine and
cache the auto-color decision.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 09:04:23 +04:00
|
|
|
return GIT_COLOR_AUTO;
|
2006-09-08 12:03:18 +04:00
|
|
|
}
|
2007-11-27 01:30:28 +03:00
|
|
|
|
Add an optional argument for --color options
Make git-branch, git-show-branch, git-grep, and all the diff-based
programs accept an optional argument <when> for --color. The argument
is a colorbool: "always", "never", or "auto". If no argument is given,
"always" is used; --no-color is an alias for --color=never. This makes
the command-line interface consistent with other GNU tools, such as `ls'
and `grep', and with the git-config color options. Note that, without
an argument, --color and --no-color work exactly as before.
To implement this, two internal changes were made:
1. Allow the first argument of git_config_colorbool() to be NULL,
in which case it returns -1 if the argument isn't "always", "never",
or "auto".
2. Add OPT_COLOR_FLAG(), OPT__COLOR(), and parse_opt_color_flag_cb()
to the option parsing library. The callback uses
git_config_colorbool(), so color.h is now a dependency
of parse-options.c.
Signed-off-by: Mark Lodato <lodatom@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-02-17 07:55:58 +03:00
|
|
|
if (!var)
|
|
|
|
return -1;
|
|
|
|
|
2007-11-27 01:30:28 +03:00
|
|
|
/* Missing or explicit false to turn off colorization */
|
|
|
|
if (!git_config_bool(var, value))
|
2006-09-08 12:03:18 +04:00
|
|
|
return 0;
|
2007-11-27 01:30:28 +03:00
|
|
|
|
|
|
|
/* any normal truth value defaults to 'auto' */
|
color: delay auto-color decision until point of use
When we read a color value either from a config file or from
the command line, we use git_config_colorbool to convert it
from the tristate always/never/auto into a single yes/no
boolean value.
This has some timing implications with respect to starting
a pager.
If we start (or decide not to start) the pager before
checking the colorbool, everything is fine. Either isatty(1)
will give us the right information, or we will properly
check for pager_in_use().
However, if we decide to start a pager after we have checked
the colorbool, things are not so simple. If stdout is a tty,
then we will have already decided to use color. However, the
user may also have configured color.pager not to use color
with the pager. In this case, we need to actually turn off
color. Unfortunately, the pager code has no idea which color
variables were turned on (and there are many of them
throughout the code, and they may even have been manipulated
after the colorbool selection by something like "--color" on
the command line).
This bug can be seen any time a pager is started after
config and command line options are checked. This has
affected "git diff" since 89d07f7 (diff: don't run pager if
user asked for a diff style exit code, 2007-08-12). It has
also affect the log family since 1fda91b (Fix 'git log'
early pager startup error case, 2010-08-24).
This patch splits the notion of parsing a colorbool and
actually checking the configuration. The "use_color"
variables now have an additional possible value,
GIT_COLOR_AUTO. Users of the variable should use the new
"want_color()" wrapper, which will lazily determine and
cache the auto-color decision.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 09:04:23 +04:00
|
|
|
return GIT_COLOR_AUTO;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int check_auto_color(void)
|
|
|
|
{
|
2011-08-18 09:03:48 +04:00
|
|
|
if (color_stdout_is_tty < 0)
|
|
|
|
color_stdout_is_tty = isatty(1);
|
|
|
|
if (color_stdout_is_tty || (pager_in_use() && pager_use_color)) {
|
2007-11-27 01:30:28 +03:00
|
|
|
char *term = getenv("TERM");
|
|
|
|
if (term && strcmp(term, "dumb"))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
2006-09-08 12:03:18 +04:00
|
|
|
}
|
|
|
|
|
color: delay auto-color decision until point of use
When we read a color value either from a config file or from
the command line, we use git_config_colorbool to convert it
from the tristate always/never/auto into a single yes/no
boolean value.
This has some timing implications with respect to starting
a pager.
If we start (or decide not to start) the pager before
checking the colorbool, everything is fine. Either isatty(1)
will give us the right information, or we will properly
check for pager_in_use().
However, if we decide to start a pager after we have checked
the colorbool, things are not so simple. If stdout is a tty,
then we will have already decided to use color. However, the
user may also have configured color.pager not to use color
with the pager. In this case, we need to actually turn off
color. Unfortunately, the pager code has no idea which color
variables were turned on (and there are many of them
throughout the code, and they may even have been manipulated
after the colorbool selection by something like "--color" on
the command line).
This bug can be seen any time a pager is started after
config and command line options are checked. This has
affected "git diff" since 89d07f7 (diff: don't run pager if
user asked for a diff style exit code, 2007-08-12). It has
also affect the log family since 1fda91b (Fix 'git log'
early pager startup error case, 2010-08-24).
This patch splits the notion of parsing a colorbool and
actually checking the configuration. The "use_color"
variables now have an additional possible value,
GIT_COLOR_AUTO. Users of the variable should use the new
"want_color()" wrapper, which will lazily determine and
cache the auto-color decision.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 09:04:23 +04:00
|
|
|
int want_color(int var)
|
|
|
|
{
|
|
|
|
static int want_auto = -1;
|
|
|
|
|
2011-08-18 09:05:35 +04:00
|
|
|
if (var < 0)
|
|
|
|
var = git_use_color_default;
|
|
|
|
|
color: delay auto-color decision until point of use
When we read a color value either from a config file or from
the command line, we use git_config_colorbool to convert it
from the tristate always/never/auto into a single yes/no
boolean value.
This has some timing implications with respect to starting
a pager.
If we start (or decide not to start) the pager before
checking the colorbool, everything is fine. Either isatty(1)
will give us the right information, or we will properly
check for pager_in_use().
However, if we decide to start a pager after we have checked
the colorbool, things are not so simple. If stdout is a tty,
then we will have already decided to use color. However, the
user may also have configured color.pager not to use color
with the pager. In this case, we need to actually turn off
color. Unfortunately, the pager code has no idea which color
variables were turned on (and there are many of them
throughout the code, and they may even have been manipulated
after the colorbool selection by something like "--color" on
the command line).
This bug can be seen any time a pager is started after
config and command line options are checked. This has
affected "git diff" since 89d07f7 (diff: don't run pager if
user asked for a diff style exit code, 2007-08-12). It has
also affect the log family since 1fda91b (Fix 'git log'
early pager startup error case, 2010-08-24).
This patch splits the notion of parsing a colorbool and
actually checking the configuration. The "use_color"
variables now have an additional possible value,
GIT_COLOR_AUTO. Users of the variable should use the new
"want_color()" wrapper, which will lazily determine and
cache the auto-color decision.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 09:04:23 +04:00
|
|
|
if (var == GIT_COLOR_AUTO) {
|
|
|
|
if (want_auto < 0)
|
|
|
|
want_auto = check_auto_color();
|
|
|
|
return want_auto;
|
|
|
|
}
|
2011-08-18 09:05:35 +04:00
|
|
|
return var;
|
color: delay auto-color decision until point of use
When we read a color value either from a config file or from
the command line, we use git_config_colorbool to convert it
from the tristate always/never/auto into a single yes/no
boolean value.
This has some timing implications with respect to starting
a pager.
If we start (or decide not to start) the pager before
checking the colorbool, everything is fine. Either isatty(1)
will give us the right information, or we will properly
check for pager_in_use().
However, if we decide to start a pager after we have checked
the colorbool, things are not so simple. If stdout is a tty,
then we will have already decided to use color. However, the
user may also have configured color.pager not to use color
with the pager. In this case, we need to actually turn off
color. Unfortunately, the pager code has no idea which color
variables were turned on (and there are many of them
throughout the code, and they may even have been manipulated
after the colorbool selection by something like "--color" on
the command line).
This bug can be seen any time a pager is started after
config and command line options are checked. This has
affected "git diff" since 89d07f7 (diff: don't run pager if
user asked for a diff style exit code, 2007-08-12). It has
also affect the log family since 1fda91b (Fix 'git log'
early pager startup error case, 2010-08-24).
This patch splits the notion of parsing a colorbool and
actually checking the configuration. The "use_color"
variables now have an additional possible value,
GIT_COLOR_AUTO. Users of the variable should use the new
"want_color()" wrapper, which will lazily determine and
cache the auto-color decision.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 09:04:23 +04:00
|
|
|
}
|
|
|
|
|
2011-08-18 09:05:08 +04:00
|
|
|
int git_color_config(const char *var, const char *value, void *cb)
|
2008-02-18 10:26:03 +03:00
|
|
|
{
|
|
|
|
if (!strcmp(var, "color.ui")) {
|
2011-08-18 09:03:48 +04:00
|
|
|
git_use_color_default = git_config_colorbool(var, value);
|
2008-02-18 10:26:03 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-18 09:05:08 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int git_color_default_config(const char *var, const char *value, void *cb)
|
|
|
|
{
|
|
|
|
if (git_color_config(var, value, cb) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2008-05-14 21:46:53 +04:00
|
|
|
return git_default_config(var, value, cb);
|
2008-02-18 10:26:03 +03:00
|
|
|
}
|
|
|
|
|
2011-02-26 08:09:41 +03:00
|
|
|
void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb)
|
|
|
|
{
|
|
|
|
if (*color)
|
|
|
|
fprintf(fp, "%s", color);
|
|
|
|
fprintf(fp, "%s", sb->buf);
|
|
|
|
if (*color)
|
|
|
|
fprintf(fp, "%s", GIT_COLOR_RESET);
|
|
|
|
}
|
|
|
|
|
2007-09-18 04:06:42 +04:00
|
|
|
static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
|
2006-09-08 12:03:18 +04:00
|
|
|
va_list args, const char *trail)
|
|
|
|
{
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
if (*color)
|
2007-09-18 04:06:42 +04:00
|
|
|
r += fprintf(fp, "%s", color);
|
|
|
|
r += vfprintf(fp, fmt, args);
|
2006-09-08 12:03:18 +04:00
|
|
|
if (*color)
|
2009-02-14 00:53:40 +03:00
|
|
|
r += fprintf(fp, "%s", GIT_COLOR_RESET);
|
2006-09-08 12:03:18 +04:00
|
|
|
if (trail)
|
2007-09-18 04:06:42 +04:00
|
|
|
r += fprintf(fp, "%s", trail);
|
2006-09-08 12:03:18 +04:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-09-18 04:06:42 +04:00
|
|
|
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
|
2006-09-08 12:03:18 +04:00
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
int r;
|
|
|
|
va_start(args, fmt);
|
2007-09-18 04:06:42 +04:00
|
|
|
r = color_vfprintf(fp, color, fmt, args, NULL);
|
2006-09-08 12:03:18 +04:00
|
|
|
va_end(args);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2007-09-18 04:06:42 +04:00
|
|
|
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
|
2006-09-08 12:03:18 +04:00
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
int r;
|
|
|
|
va_start(args, fmt);
|
2007-09-18 04:06:42 +04:00
|
|
|
r = color_vfprintf(fp, color, fmt, args, "\n");
|
2006-09-08 12:03:18 +04:00
|
|
|
va_end(args);
|
|
|
|
return r;
|
|
|
|
}
|
2010-12-09 20:27:08 +03:00
|
|
|
|
|
|
|
int color_is_nil(const char *c)
|
|
|
|
{
|
|
|
|
return !strcmp(c, "NIL");
|
|
|
|
}
|