]> git.ipfire.org Git - thirdparty/git.git/commitdiff
color: add support for 12-bit RGB colors
authorBeat Bolli <bb@drbeat.li>
Thu, 2 May 2024 11:03:31 +0000 (13:03 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 May 2024 16:30:38 +0000 (09:30 -0700)
RGB color parsing currently supports 24-bit values in the form #RRGGBB.

As in Cascading Style Sheets (CSS [1]), also allow to specify an RGB color
using only three digits with #RGB.

In this shortened form, each of the digits is – again, as in CSS –
duplicated to convert the color to 24 bits, e.g. #f1b specifies the same
color as #ff11bb.

In color.h, remove the '0x' prefix in the example to match the actual
syntax.

[1] https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color

Signed-off-by: Beat Bolli <dev+git@drbeat.li>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config.txt
color.c
color.h
t/t4026-color.sh

index 70b448b132628c71ee8807bfef59c1e4e60fc823..6f649c997c0f36bfa3ee01867a7995b2555e4148 100644 (file)
@@ -316,7 +316,8 @@ 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
 your terminal supports it, you may also specify 24-bit RGB values as
-hex, like `#ff0ab3`.
+hex, like `#ff0ab3`, or 12-bit RGB values like `#f1b`, which is
+equivalent to the 24-bit color `#ff11bb`.
 +
 The accepted attributes are `bold`, `dim`, `ul`, `blink`, `reverse`,
 `italic`, and `strike` (for crossed-out or "strikethrough" letters).
diff --git a/color.c b/color.c
index f663c06ac4eddc7b8085739318ddfc99a3ee7583..227a5ab2f42ef99e578c837f59b2b40986a3c9e3 100644 (file)
--- a/color.c
+++ b/color.c
@@ -64,12 +64,16 @@ static int match_word(const char *word, int len, const char *match)
        return !strncasecmp(word, match, len) && !match[len];
 }
 
-static int get_hex_color(const char *in, unsigned char *out)
+static int get_hex_color(const char **inp, int width, unsigned char *out)
 {
+       const char *in = *inp;
        unsigned int val;
-       val = (hexval(in[0]) << 4) | hexval(in[1]);
+
+       assert(width == 1 || width == 2);
+       val = (hexval(in[0]) << 4) | hexval(in[width - 1]);
        if (val & ~0xff)
                return -1;
+       *inp += width;
        *out = val;
        return 0;
 }
@@ -135,11 +139,14 @@ static int parse_color(struct color *out, const char *name, int len)
                return 0;
        }
 
-       /* Try a 24-bit RGB value */
-       if (len == 7 && name[0] == '#') {
-               if (!get_hex_color(name + 1, &out->red) &&
-                   !get_hex_color(name + 3, &out->green) &&
-                   !get_hex_color(name + 5, &out->blue)) {
+       /* Try a 24- or 12-bit RGB value prefixed with '#' */
+       if ((len == 7 || len == 4) && name[0] == '#') {
+               int width_per_color = (len == 7) ? 2 : 1;
+               const char *color = name + 1;
+
+               if (!get_hex_color(&color, width_per_color, &out->red) &&
+                   !get_hex_color(&color, width_per_color, &out->green) &&
+                   !get_hex_color(&color, width_per_color, &out->blue)) {
                        out->type = COLOR_RGB;
                        return 0;
                }
diff --git a/color.h b/color.h
index bb28343be210643b57201c6a68ac4f718fa8ebc8..7ed259a35bb450ea5a0b479d2a0c9929f2f1b47a 100644 (file)
--- a/color.h
+++ b/color.h
@@ -112,7 +112,8 @@ int want_color_fd(int fd, int var);
  * Translate a Git color from 'value' into a string that the terminal can
  * interpret and store it into 'dst'. The Git color values are of the form
  * "foreground [background] [attr]" where fore- and background can be a color
- * name ("red"), a RGB code (#0xFF0000) or a 256-color-mode from the terminal.
+ * name ("red"), a RGB code (#FF0000 or #F00) or a 256-color-mode from the
+ * terminal.
  */
 int color_parse(const char *value, char *dst);
 int color_parse_mem(const char *value, int len, char *dst);
index c4113803198980dce731f7b27d0f28b6f5d21c55..b05f2a9b6075d0de8235919a30c0e9066f562542 100755 (executable)
@@ -96,8 +96,8 @@ test_expect_success '256 colors' '
        color "254 bold 255" "[1;38;5;254;48;5;255m"
 '
 
-test_expect_success '24-bit colors' '
-       color "#ff00ff black" "[38;2;255;0;255;40m"
+test_expect_success 'RGB colors' '
+       color "#ff00ff #0f0" "[38;2;255;0;255;48;2;0;255;0m"
 '
 
 test_expect_success '"default" foreground' '
@@ -146,13 +146,15 @@ test_expect_success 'non-hex character in RGB color' '
        invalid_color "#12x456" &&
        invalid_color "#123x56" &&
        invalid_color "#1234x6" &&
-       invalid_color "#12345x"
+       invalid_color "#12345x" &&
+       invalid_color "#x23" &&
+       invalid_color "#1x3" &&
+       invalid_color "#12x"
 '
 
 test_expect_success 'wrong number of letters in RGB color' '
        invalid_color "#1" &&
        invalid_color "#23" &&
-       invalid_color "#456" &&
        invalid_color "#789a" &&
        invalid_color "#bcdef" &&
        invalid_color "#1234567"