color.con commit diff --numstat: show binary with '-' to match "apply --numstat" (bfddbc5)
   1#include "color.h"
   2#include "cache.h"
   3#include "git-compat-util.h"
   4
   5#include <stdarg.h>
   6
   7#define COLOR_RESET "\033[m"
   8
   9static int parse_color(const char *name, int len)
  10{
  11        static const char * const color_names[] = {
  12                "normal", "black", "red", "green", "yellow",
  13                "blue", "magenta", "cyan", "white"
  14        };
  15        char *end;
  16        int i;
  17        for (i = 0; i < ARRAY_SIZE(color_names); i++) {
  18                const char *str = color_names[i];
  19                if (!strncasecmp(name, str, len) && !str[len])
  20                        return i - 1;
  21        }
  22        i = strtol(name, &end, 10);
  23        if (*name && !*end && i >= -1 && i <= 255)
  24                return i;
  25        return -2;
  26}
  27
  28static int parse_attr(const char *name, int len)
  29{
  30        static const int attr_values[] = { 1, 2, 4, 5, 7 };
  31        static const char * const attr_names[] = {
  32                "bold", "dim", "ul", "blink", "reverse"
  33        };
  34        int i;
  35        for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
  36                const char *str = attr_names[i];
  37                if (!strncasecmp(name, str, len) && !str[len])
  38                        return attr_values[i];
  39        }
  40        return -1;
  41}
  42
  43void color_parse(const char *value, const char *var, char *dst)
  44{
  45        const char *ptr = value;
  46        int attr = -1;
  47        int fg = -2;
  48        int bg = -2;
  49
  50        if (!strcasecmp(value, "reset")) {
  51                strcpy(dst, "\033[m");
  52                return;
  53        }
  54
  55        /* [fg [bg]] [attr] */
  56        while (*ptr) {
  57                const char *word = ptr;
  58                int val, len = 0;
  59
  60                while (word[len] && !isspace(word[len]))
  61                        len++;
  62
  63                ptr = word + len;
  64                while (*ptr && isspace(*ptr))
  65                        ptr++;
  66
  67                val = parse_color(word, len);
  68                if (val >= -1) {
  69                        if (fg == -2) {
  70                                fg = val;
  71                                continue;
  72                        }
  73                        if (bg == -2) {
  74                                bg = val;
  75                                continue;
  76                        }
  77                        goto bad;
  78                }
  79                val = parse_attr(word, len);
  80                if (val < 0 || attr != -1)
  81                        goto bad;
  82                attr = val;
  83        }
  84
  85        if (attr >= 0 || fg >= 0 || bg >= 0) {
  86                int sep = 0;
  87
  88                *dst++ = '\033';
  89                *dst++ = '[';
  90                if (attr >= 0) {
  91                        *dst++ = '0' + attr;
  92                        sep++;
  93                }
  94                if (fg >= 0) {
  95                        if (sep++)
  96                                *dst++ = ';';
  97                        if (fg < 8) {
  98                                *dst++ = '3';
  99                                *dst++ = '0' + fg;
 100                        } else {
 101                                dst += sprintf(dst, "38;5;%d", fg);
 102                        }
 103                }
 104                if (bg >= 0) {
 105                        if (sep++)
 106                                *dst++ = ';';
 107                        if (bg < 8) {
 108                                *dst++ = '4';
 109                                *dst++ = '0' + bg;
 110                        } else {
 111                                dst += sprintf(dst, "48;5;%d", bg);
 112                        }
 113                }
 114                *dst++ = 'm';
 115        }
 116        *dst = 0;
 117        return;
 118bad:
 119        die("bad config value '%s' for variable '%s'", value, var);
 120}
 121
 122int git_config_colorbool(const char *var, const char *value)
 123{
 124        if (!value)
 125                return 1;
 126        if (!strcasecmp(value, "auto")) {
 127                if (isatty(1) || (pager_in_use && pager_use_color)) {
 128                        char *term = getenv("TERM");
 129                        if (term && strcmp(term, "dumb"))
 130                                return 1;
 131                }
 132                return 0;
 133        }
 134        if (!strcasecmp(value, "never"))
 135                return 0;
 136        if (!strcasecmp(value, "always"))
 137                return 1;
 138        return git_config_bool(var, value);
 139}
 140
 141static int color_vprintf(const char *color, const char *fmt,
 142                va_list args, const char *trail)
 143{
 144        int r = 0;
 145
 146        if (*color)
 147                r += printf("%s", color);
 148        r += vprintf(fmt, args);
 149        if (*color)
 150                r += printf("%s", COLOR_RESET);
 151        if (trail)
 152                r += printf("%s", trail);
 153        return r;
 154}
 155
 156
 157
 158int color_printf(const char *color, const char *fmt, ...)
 159{
 160        va_list args;
 161        int r;
 162        va_start(args, fmt);
 163        r = color_vprintf(color, fmt, args, NULL);
 164        va_end(args);
 165        return r;
 166}
 167
 168int color_printf_ln(const char *color, const char *fmt, ...)
 169{
 170        va_list args;
 171        int r;
 172        va_start(args, fmt);
 173        r = color_vprintf(color, fmt, args, "\n");
 174        va_end(args);
 175        return r;
 176}