summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt23
-rw-r--r--color.c41
-rw-r--r--color.h13
-rwxr-xr-xt/t4026-color.sh16
4 files changed, 80 insertions, 13 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 1167e88e34..b168f02dc3 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -262,11 +262,19 @@ color::
colors (at most two, one for foreground and one for background)
and attributes (as many as you want), separated by spaces.
+
-The basic colors accepted are `normal`, `black`, `red`, `green`, `yellow`,
-`blue`, `magenta`, `cyan` and `white`. The first color given is the
-foreground; the second is the background. All the basic colors except
-`normal` have a bright variant that can be specified by prefixing the
-color with `bright`, like `brightred`.
+The basic colors accepted are `normal`, `black`, `red`, `green`,
+`yellow`, `blue`, `magenta`, `cyan`, `white` and `default`. The first
+color given is the foreground; the second is the background. All the
+basic colors except `normal` and `default` have a bright variant that can
+be specified by prefixing the color with `bright`, like `brightred`.
++
+The color `normal` makes no change to the color. It is the same as an
+empty string, but can be used as the foreground color when specifying a
+background color alone (for example, "normal red").
++
+The color `default` explicitly resets the color to the terminal default,
+for example to specify a cleared background. Although it varies between
+terminals, this is usually not the same as setting to "white black".
+
Colors may also be given as numbers between 0 and 255; these use ANSI
256-color mode (but note that not all terminals may support this). If
@@ -280,6 +288,11 @@ The position of any attributes with respect to the colors
be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`,
`no-ul`, etc).
+
+The pseudo-attribute `reset` resets all colors and attributes before
+applying the specified coloring. For example, `reset green` will result
+in a green foreground and default background without any active
+attributes.
++
An empty color string produces no color effect at all. This can be used
to avoid coloring specific elements without disabling color entirely.
+
diff --git a/color.c b/color.c
index 64f52a4f93..4f884c6b3d 100644
--- a/color.c
+++ b/color.c
@@ -40,7 +40,7 @@ struct color {
enum {
COLOR_UNSPECIFIED = 0,
COLOR_NORMAL,
- COLOR_ANSI, /* basic 0-7 ANSI colors */
+ COLOR_ANSI, /* basic 0-7 ANSI colors + "default" (value = 9) */
COLOR_256,
COLOR_RGB
} type;
@@ -83,6 +83,27 @@ static int parse_ansi_color(struct color *out, const char *name, int len)
int i;
int color_offset = COLOR_FOREGROUND_ANSI;
+ if (match_word(name, len, "default")) {
+ /*
+ * Restores to the terminal's default color, which may not be
+ * the same as explicitly setting "white" or "black".
+ *
+ * ECMA-48 - Control Functions \
+ * for Coded Character Sets, 5th edition (June 1991):
+ * > 39 default display colour (implementation-defined)
+ * > 49 default background colour (implementation-defined)
+ *
+ * Although not supported /everywhere/--according to terminfo,
+ * some terminals define "op" (original pair) as a blunt
+ * "set to white on black", or even "send full SGR reset"--
+ * it's standard and well-supported enough that if a user
+ * asks for it in their config this will do the right thing.
+ */
+ out->type = COLOR_ANSI;
+ out->value = 9 + color_offset;
+ return 0;
+ }
+
if (strncasecmp(name, "bright", 6) == 0) {
color_offset = COLOR_FOREGROUND_BRIGHT_ANSI;
name += 6;
@@ -234,6 +255,7 @@ int color_parse_mem(const char *value, int value_len, char *dst)
const char *ptr = value;
int len = value_len;
char *end = dst + COLOR_MAXLEN;
+ unsigned int has_reset = 0;
unsigned int attr = 0;
struct color fg = { COLOR_UNSPECIFIED };
struct color bg = { COLOR_UNSPECIFIED };
@@ -248,12 +270,7 @@ int color_parse_mem(const char *value, int value_len, char *dst)
return 0;
}
- if (!strncasecmp(ptr, "reset", len)) {
- xsnprintf(dst, end - dst, GIT_COLOR_RESET);
- return 0;
- }
-
- /* [fg [bg]] [attr]... */
+ /* [reset] [fg [bg]] [attr]... */
while (len > 0) {
const char *word = ptr;
struct color c = { COLOR_UNSPECIFIED };
@@ -270,6 +287,11 @@ int color_parse_mem(const char *value, int value_len, char *dst)
len--;
}
+ if (match_word(word, wordlen, "reset")) {
+ has_reset = 1;
+ continue;
+ }
+
if (!parse_color(&c, word, wordlen)) {
if (fg.type == COLOR_UNSPECIFIED) {
fg = c;
@@ -295,13 +317,16 @@ int color_parse_mem(const char *value, int value_len, char *dst)
*dst++ = (x); \
} while(0)
- if (attr || !color_empty(&fg) || !color_empty(&bg)) {
+ if (has_reset || attr || !color_empty(&fg) || !color_empty(&bg)) {
int sep = 0;
int i;
OUT('\033');
OUT('[');
+ if (has_reset)
+ sep++;
+
for (i = 0; attr; i++) {
unsigned bit = (1 << i);
if (!(attr & bit))
diff --git a/color.h b/color.h
index 98894d6a17..cfc8f841b2 100644
--- a/color.h
+++ b/color.h
@@ -6,6 +6,7 @@ struct strbuf;
/*
* The maximum length of ANSI color sequence we would generate:
* - leading ESC '[' 2
+ * - reset ';' .................1
* - attr + ';' 2 * num_attr (e.g. "1;")
* - no-attr + ';' 3 * num_attr (e.g. "22;")
* - fg color + ';' 17 (e.g. "38;2;255;255;255;")
@@ -24,30 +25,42 @@ struct strbuf;
#define GIT_COLOR_NORMAL ""
#define GIT_COLOR_RESET "\033[m"
#define GIT_COLOR_BOLD "\033[1m"
+#define GIT_COLOR_BLACK "\033[30m"
#define GIT_COLOR_RED "\033[31m"
#define GIT_COLOR_GREEN "\033[32m"
#define GIT_COLOR_YELLOW "\033[33m"
#define GIT_COLOR_BLUE "\033[34m"
#define GIT_COLOR_MAGENTA "\033[35m"
#define GIT_COLOR_CYAN "\033[36m"
+#define GIT_COLOR_WHITE "\033[37m"
+#define GIT_COLOR_DEFAULT "\033[39m"
+#define GIT_COLOR_BOLD_BLACK "\033[1;30m"
#define GIT_COLOR_BOLD_RED "\033[1;31m"
#define GIT_COLOR_BOLD_GREEN "\033[1;32m"
#define GIT_COLOR_BOLD_YELLOW "\033[1;33m"
#define GIT_COLOR_BOLD_BLUE "\033[1;34m"
#define GIT_COLOR_BOLD_MAGENTA "\033[1;35m"
#define GIT_COLOR_BOLD_CYAN "\033[1;36m"
+#define GIT_COLOR_BOLD_WHITE "\033[1;37m"
+#define GIT_COLOR_BOLD_DEFAULT "\033[1;39m"
+#define GIT_COLOR_FAINT_BLACK "\033[2;30m"
#define GIT_COLOR_FAINT_RED "\033[2;31m"
#define GIT_COLOR_FAINT_GREEN "\033[2;32m"
#define GIT_COLOR_FAINT_YELLOW "\033[2;33m"
#define GIT_COLOR_FAINT_BLUE "\033[2;34m"
#define GIT_COLOR_FAINT_MAGENTA "\033[2;35m"
#define GIT_COLOR_FAINT_CYAN "\033[2;36m"
+#define GIT_COLOR_FAINT_WHITE "\033[2;37m"
+#define GIT_COLOR_FAINT_DEFAULT "\033[2;39m"
+#define GIT_COLOR_BG_BLACK "\033[40m"
#define GIT_COLOR_BG_RED "\033[41m"
#define GIT_COLOR_BG_GREEN "\033[42m"
#define GIT_COLOR_BG_YELLOW "\033[43m"
#define GIT_COLOR_BG_BLUE "\033[44m"
#define GIT_COLOR_BG_MAGENTA "\033[45m"
#define GIT_COLOR_BG_CYAN "\033[46m"
+#define GIT_COLOR_BG_WHITE "\033[47m"
+#define GIT_COLOR_BG_DEFAULT "\033[49m"
#define GIT_COLOR_FAINT "\033[2m"
#define GIT_COLOR_FAINT_ITALIC "\033[2;3m"
#define GIT_COLOR_REVERSE "\033[7m"
diff --git a/t/t4026-color.sh b/t/t4026-color.sh
index cc73161b46..cc3f60d468 100755
--- a/t/t4026-color.sh
+++ b/t/t4026-color.sh
@@ -60,6 +60,10 @@ test_expect_success 'fg bg attr...' '
color "blue bold dim ul blink reverse" "[1;2;4;5;7;34m"
'
+test_expect_success 'reset fg bg attr...' '
+ color "reset blue bold dim ul blink reverse" "[;1;2;4;5;7;34m"
+'
+
# note that nobold and nodim are the same code (22)
test_expect_success 'attr negation' '
color "nobold nodim noul noblink noreverse" "[22;24;25;27m"
@@ -96,6 +100,18 @@ test_expect_success '24-bit colors' '
color "#ff00ff black" "[38;2;255;0;255;40m"
'
+test_expect_success '"default" foreground' '
+ color "default" "[39m"
+'
+
+test_expect_success '"normal default" to clear background' '
+ color "normal default" "[49m"
+'
+
+test_expect_success '"default" can be combined with attributes' '
+ color "default default no-reverse bold" "[1;27;39;49m"
+'
+
test_expect_success '"normal" yields no color at all"' '
color "normal black" "[40m"
'