author | Junio C Hamano <gitster@pobox.com> | |
Wed, 24 Mar 2010 23:24:13 +0000 (16:24 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Wed, 24 Mar 2010 23:24:13 +0000 (16:24 -0700) |
* jc/color-attrs:
color: allow multiple attributes
color: allow multiple attributes
1 | 2 | |||
---|---|---|---|---|
color.c | patch | | diff1 | | diff2 | | blob | history |
color.h | patch | | diff1 | | diff2 | | blob | history |
t/t4026-color.sh | patch | | diff1 | | diff2 | | blob | history |
diff --combined color.c
index 62977f4808ae339fdfe797e16b4eb28dc6abb85d,90268fb3c63d340e615f8c54af009e347a654e8b..e8bcac0a79a27ee093f3d5a92013780cf52eb9da
+++ b/color.c
#include "cache.h"
#include "color.h"
-#define COLOR_RESET "\033[m"
-
int git_use_color_default = 0;
static int parse_color(const char *name, int len)
{
const char *ptr = value;
int len = value_len;
- int attr = -1;
+ unsigned int attr = 0;
int fg = -2;
int bg = -2;
if (!strncasecmp(value, "reset", len)) {
- strcpy(dst, "\033[m");
+ strcpy(dst, GIT_COLOR_RESET);
return;
}
- /* [fg [bg]] [attr] */
+ /* [fg [bg]] [attr]... */
while (len > 0) {
const char *word = ptr;
int val, wordlen = 0;
goto bad;
}
val = parse_attr(word, wordlen);
- if (val < 0 || attr != -1)
+ if (0 <= val)
+ attr |= (1 << val);
+ else
goto bad;
- attr = val;
}
- if (attr >= 0 || fg >= 0 || bg >= 0) {
+ if (attr || fg >= 0 || bg >= 0) {
int sep = 0;
+ int i;
*dst++ = '\033';
*dst++ = '[';
- if (attr >= 0) {
- *dst++ = '0' + attr;
- sep++;
+
+ for (i = 0; attr; i++) {
+ unsigned bit = (1 << i);
+ if (!(attr & bit))
+ continue;
+ attr &= ~bit;
+ if (sep++)
+ *dst++ = ';';
+ *dst++ = '0' + i;
}
if (fg >= 0) {
if (sep++)
r += fprintf(fp, "%s", color);
r += vfprintf(fp, fmt, args);
if (*color)
- r += fprintf(fp, "%s", COLOR_RESET);
+ r += fprintf(fp, "%s", GIT_COLOR_RESET);
if (trail)
r += fprintf(fp, "%s", trail);
return r;
char *p = memchr(buf, '\n', count);
if (p != buf && (fputs(color, fp) < 0 ||
fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
- fputs(COLOR_RESET, fp) < 0))
+ fputs(GIT_COLOR_RESET, fp) < 0))
return -1;
if (!p)
return 0;
diff --combined color.h
index 3cb4b7fc890880b0fcf19a11c6bc7de6b10d6e8d,e2988f4e93f95ece2a1b0721fa8a17aa3f030756..bcb28cf10f2cbef11d9dba0e5a7f3f0515cbbd70
+++ b/color.h
#ifndef COLOR_H
#define COLOR_H
- /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
- #define COLOR_MAXLEN 24
+ /* 2 + (2 * num_attrs) + 8 + 1 + 8 + 'm' + NUL */
+ /* "\033[1;2;4;5;7;38;5;2xx;48;5;2xxm\0" */
+ /*
+ * The maximum length of ANSI color sequence we would generate:
+ * - leading ESC '[' 2
+ * - attr + ';' 2 * 8 (e.g. "1;")
+ * - fg color + ';' 9 (e.g. "38;5;2xx;")
+ * - fg color + ';' 9 (e.g. "48;5;2xx;")
+ * - terminating 'm' NUL 2
+ *
+ * The above overcounts attr (we only use 5 not 8) and one semicolon
+ * but it is close enough.
+ */
+ #define COLOR_MAXLEN 40
+/*
+ * IMPORTANT: Due to the way these color codes are emulated on Windows,
+ * write them only using printf(), fprintf(), and fputs(). In particular,
+ * do not use puts() or write().
+ */
+#define GIT_COLOR_NORMAL ""
+#define GIT_COLOR_RESET "\033[m"
+#define GIT_COLOR_BOLD "\033[1m"
+#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_BG_RED "\033[41m"
+
/*
* This variable stores the value of color.ui
*/
int git_config_colorbool(const char *var, const char *value, int stdout_is_tty);
void color_parse(const char *value, const char *var, char *dst);
void color_parse_mem(const char *value, int len, const char *var, char *dst);
+__attribute__((format (printf, 3, 4)))
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
+__attribute__((format (printf, 3, 4)))
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
diff --combined t/t4026-color.sh
index 5ade44c043ca6577b2e331b152515359128dbd32,49eced20e7f9346ac6d52891c271ab3ef6d0982b..d5ccdd0cf8061e797e88185bfddb0864f73291dd
--- 1/t/t4026-color.sh
--- 2/t/t4026-color.sh
+++ b/t/t4026-color.sh
color()
{
- git config diff.color.new "$1" &&
- test "`git config --get-color diff.color.new`" = "\e$2"
+ actual=$(git config --get-color no.such.slot "$1") &&
+ test "$actual" = "\e$2"
}
invalid_color()
{
- git config diff.color.new "$1" &&
- test -z "`git config --get-color diff.color.new 2>/dev/null`"
+ test_must_fail git config --get-color no.such.slot "$1"
}
test_expect_success 'reset' '
color "blue red ul" "[4;34;41m"
'
+ test_expect_success 'fg bg attr...' '
+ color "blue bold dim ul blink reverse" "[1;2;4;5;7;34m"
+ '
+
+ test_expect_success 'long color specification' '
+ color "254 255 bold dim ul blink reverse" "[1;2;4;5;7;38;5;254;48;5;255m"
+ '
+
test_expect_success '256 colors' '
color "254 bold 255" "[1;38;5;254;48;5;255m"
'
invalid_color "dimX"
'
+test_expect_success 'unknown color slots are ignored (diff)' '
+ git config --unset diff.color.new
+ git config color.diff.nosuchslotwilleverbedefined white &&
+ git diff --color
+'
+
+test_expect_success 'unknown color slots are ignored (branch)' '
+ git config color.branch.nosuchslotwilleverbedefined white &&
+ git branch -a
+'
+
+test_expect_success 'unknown color slots are ignored (status)' '
+ git config color.status.nosuchslotwilleverbedefined white || exit
+ git status
+ case $? in 0|1) : ok ;; *) false ;; esac
+'
+
test_done