]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/colors: move colors canonicalization to lib/color-names.c
authorKarel Zak <kzak@redhat.com>
Mon, 27 Feb 2023 16:43:11 +0000 (17:43 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 27 Feb 2023 16:43:11 +0000 (17:43 +0100)
* let's make simplified sequences (e.g. "35;4")  used without
  lib/colors.c (without color schemes)

* add function to detect already usable esc sequence

* support this new feature in "test_colors --color <name|seq|...>"

  ./test_colors --color "red"
  ./test_colors --color "35;5"

Signed-off-by: Karel Zak <kzak@redhat.com>
include/color-names.h
lib/color-names.c
lib/colors.c

index 42f6f8f6e2fcb1f7240859b87eadf0201ac7a5bc..c6ab7ba4bb5fd89c16103a8d6ae92de98073181d 100644 (file)
@@ -41,4 +41,7 @@
 
 extern const char *color_sequence_from_colorname(const char *str);
 
+extern int color_is_sequence(const char *color);
+extern char *color_get_sequence(const char *color);
+
 #endif /* UTIL_LINUX_COLOR_NAMES_H */
index 9b1505e4b04b83bdb825f336effc0539fbace624..d6a3fc9ee617b1d37a35a53f44dbe05526923b93 100644 (file)
@@ -7,6 +7,8 @@
 #include "c.h"
 #include "color-names.h"
 
+#include <ctype.h>
+
 struct ul_color_name {
        const char *name;
        const char *seq;
@@ -62,3 +64,108 @@ const char *color_sequence_from_colorname(const char *str)
                                cmp_color_name);
        return res ? res->seq : NULL;
 }
+
+
+int color_is_sequence(const char *color)
+{
+       if (color && *color == 0x1B) {
+               size_t len = strlen(color);
+
+               if (len >= 4 &&
+                   *(color + 1) == '[' &&
+                   isdigit(*(color + 2)) &&
+                   *(color + len - 1) == 'm')
+               return 1;
+       }
+
+       return 0;
+}
+
+/* canonicalize sequence */
+static int __color_canonicalize(const char *str, char **seq)
+{
+       char *in, *out;
+       int len;
+
+       if (!str)
+               return -EINVAL;
+
+       *seq = NULL;
+
+       /* convert color names like "red" to the real sequence */
+       if (*str != '\\' && isalpha(*str)) {
+               const char *s = color_sequence_from_colorname(str);
+               *seq = strdup(s ? s : str);
+
+               return *seq ? 0 : -ENOMEM;
+       }
+
+       /* convert xx;yy sequences to "\033[xx;yy" */
+       if ((len = asprintf(seq, "\033[%sm", str)) < 1)
+               return -ENOMEM;
+
+       for (in = *seq, out = *seq; in && *in; in++) {
+               if (*in != '\\') {
+                       *out++ = *in;
+                       continue;
+               }
+               switch(*(in + 1)) {
+               case 'a':
+                       *out++ = '\a';  /* Bell */
+                       break;
+               case 'b':
+                       *out++ = '\b';  /* Backspace */
+                       break;
+               case 'e':
+                       *out++ = '\033';        /* Escape */
+                       break;
+               case 'f':
+                       *out++ = '\f';  /* Form Feed */
+                       break;
+               case 'n':
+                       *out++ = '\n';  /* Newline */
+                       break;
+               case 'r':
+                       *out++ = '\r';  /* Carriage Return */
+                       break;
+               case 't':
+                       *out++ = '\t';  /* Tab */
+                       break;
+               case 'v':
+                       *out++ = '\v';  /* Vertical Tab */
+                       break;
+               case '\\':
+                       *out++ = '\\';  /* Backslash */
+                       break;
+               case '_':
+                       *out++ = ' ';   /* Space */
+                       break;
+               case '#':
+                       *out++ = '#';   /* Hash mark */
+                       break;
+               case '?':
+                       *out++ = '?';   /* Question mark */
+                       break;
+               default:
+                       *out++ = *in;
+                       *out++ = *(in + 1);
+                       break;
+               }
+               in++;
+       }
+
+       if (out) {
+               assert ((out - *seq) <= len);
+               *out = '\0';
+       }
+
+       return 0;
+}
+
+char *color_get_sequence(const char *color)
+{
+       char *seq = NULL;
+       int rc = __color_canonicalize(color, &seq);
+
+       return rc ? NULL : seq;
+}
index 886dd81d70048aba98da51d5cd34b4ba0d1cefe4..621dca336461df13496246908c80b941586de6d7 100644 (file)
@@ -353,88 +353,6 @@ static char *colors_get_homedir(char *buf, size_t bufsz)
        return NULL;
 }
 
-/* canonicalize sequence */
-static int cn_sequence(const char *str, char **seq)
-{
-       char *in, *out;
-       int len;
-
-       if (!str)
-               return -EINVAL;
-
-       *seq = NULL;
-
-       /* convert logical names like "red" to the real sequence */
-       if (*str != '\\' && isalpha(*str)) {
-               const char *s = color_sequence_from_colorname(str);
-               *seq = strdup(s ? s : str);
-
-               return *seq ? 0 : -ENOMEM;
-       }
-
-       /* convert xx;yy sequences to "\033[xx;yy" */
-       if ((len = asprintf(seq, "\033[%sm", str)) < 1)
-               return -ENOMEM;
-
-       for (in = *seq, out = *seq; in && *in; in++) {
-               if (*in != '\\') {
-                       *out++ = *in;
-                       continue;
-               }
-               switch(*(in + 1)) {
-               case 'a':
-                       *out++ = '\a';  /* Bell */
-                       break;
-               case 'b':
-                       *out++ = '\b';  /* Backspace */
-                       break;
-               case 'e':
-                       *out++ = '\033';        /* Escape */
-                       break;
-               case 'f':
-                       *out++ = '\f';  /* Form Feed */
-                       break;
-               case 'n':
-                       *out++ = '\n';  /* Newline */
-                       break;
-               case 'r':
-                       *out++ = '\r';  /* Carriage Return */
-                       break;
-               case 't':
-                       *out++ = '\t';  /* Tab */
-                       break;
-               case 'v':
-                       *out++ = '\v';  /* Vertical Tab */
-                       break;
-               case '\\':
-                       *out++ = '\\';  /* Backslash */
-                       break;
-               case '_':
-                       *out++ = ' ';   /* Space */
-                       break;
-               case '#':
-                       *out++ = '#';   /* Hash mark */
-                       break;
-               case '?':
-                       *out++ = '?';   /* Question mark */
-                       break;
-               default:
-                       *out++ = *in;
-                       *out++ = *(in + 1);
-                       break;
-               }
-               in++;
-       }
-
-       if (out) {
-               assert ((out - *seq) <= len);
-               *out = '\0';
-       }
-
-       return 0;
-}
-
-
 /*
  * Adds one color sequence to array with color scheme.
  * When returning success (0) this function takes ownership of
@@ -453,30 +371,11 @@ static int colors_add_scheme(struct ul_color_ctl *cc,
 
        DBG(SCHEME, ul_debug("add '%s'", name));
 
-       rc = cn_sequence(seq0, &seq);
-       if (rc)
-               return rc;
-
+       seq = color_get_sequence(seq0);
+       if (!seq)
+               return -EINVAL;
        rc = -ENOMEM;
 
-       /* convert logical name (e.g. "red") to real ESC code */
-       if (isalpha(*seq)) {
-               const char *s = color_sequence_from_colorname(seq);
-               char *p;
-
-               if (!s) {
-                       DBG(SCHEME, ul_debug("unknown logical name: %s", seq));
-                       rc = -EINVAL;
-                       goto err;
-               }
-
-               p = strdup(s);
-               if (!p)
-                       goto err;
-               free(seq);
-               seq = p;
-       }
-
        /* enlarge the array */
        if (cc->nschemes == cc->schemes_sz) {
                void *tmp = realloc(cc->schemes, (cc->nschemes + 10)
@@ -875,7 +774,7 @@ int main(int argc, char *argv[])
        };
        int c, mode = UL_COLORMODE_UNDEF;       /* default */
        const char *color = "red", *name = NULL, *color_scheme = NULL;
-       const char *seq = NULL;
+       char *seq = NULL;
 
        while ((c = getopt_long(argc, argv, "C:c:m:n:", longopts, NULL)) != -1) {
                switch (c) {
@@ -904,7 +803,10 @@ int main(int argc, char *argv[])
 
        colors_init(mode, name ? name : program_invocation_short_name);
 
-       seq = color_sequence_from_colorname(color);
+       if (color_is_sequence(color))
+               seq = strdup(color);
+       else
+               seq = color_get_sequence(color);
 
        if (color_scheme)
                color_scheme_enable(color_scheme, seq);
@@ -914,6 +816,8 @@ int main(int argc, char *argv[])
        color_disable();
        fputc('\n', stdout);
 
+       free(seq);
+
        return EXIT_SUCCESS;
 }
 #endif /* TEST_PROGRAM_COLORS */