diff mbox

[ovs-dev,v3,2/7] ovs-ofctl: declare / set up colors for command output

Message ID 1456930582-8157-3-git-send-email-quentin.monnet@6wind.com
State Accepted
Headers show

Commit Message

Quentin Monnet March 2, 2016, 2:56 p.m. UTC
OVS_COLORS environment variable is parsed to extract user-defined
preferences regarding colors (this is used to set up a color theme, not
to replace the `--color` option for activating color output).

The string should be of a format similar to LS_COLORS or GREP_COLORS,
with available colors being as follows:

* ac: action field
* dr: drop keyword
* le: learn keyword
* pm: parameters receiving attributes
* pr: keyword having parenthesis
* sp: some special keywords
* vl: lone values with no parameter name

For color whose idendifier does not appear in the string, the default
hardcoded value is used instead.

As an example, setting OVS_COLORS to the following string is equivalent
to using the default values:

    OVS_COLORS="ac:01;31:dr=34:le=31:pm=36:pr=35:sp=33:vl=32"

Signed-off-by: Quentin Monnet <quentin.monnet@6wind.com>
---
 lib/automake.mk       |   2 +
 lib/colors.c          | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/colors.h          |  42 +++++++++++++++
 utilities/ovs-ofctl.c |   3 ++
 4 files changed, 193 insertions(+)
 create mode 100644 lib/colors.c
 create mode 100644 lib/colors.h
diff mbox

Patch

diff --git a/lib/automake.mk b/lib/automake.mk
index 27a16691ebda..1eeb5e48b19a 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -40,6 +40,8 @@  lib_libopenvswitch_la_SOURCES = \
 	lib/classifier-private.h \
 	lib/cmap.c \
 	lib/cmap.h \
+	lib/colors.c \
+	lib/colors.h \
 	lib/command-line.c \
 	lib/command-line.h \
 	lib/compiler.h \
diff --git a/lib/colors.c b/lib/colors.c
new file mode 100644
index 000000000000..2ed4bad69f71
--- /dev/null
+++ b/lib/colors.c
@@ -0,0 +1,146 @@ 
+/*
+ * Copyright (c) 2016 6WIND S.A.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Handle color setup for output. */
+
+#include <config.h>
+
+#include "colors.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+struct color_key {
+    const char *name;
+    char **var_ptr;
+};
+
+/* Returns a pointer to the variable containing a given color. */
+static char **get_color(const struct color_key color_dic[], const char * name);
+
+/* Extract user-defined colors from OVS_COLORS environment variable. */
+static void colors_parse_from_env(const struct color_key color_dic[]);
+
+/* Global holder for colors. Declared in header file. */
+struct colors colors = { "", "", "", "", "", "", "", "" };
+
+static char **
+get_color(const struct color_key color_dic[], const char *name)
+{
+    const struct color_key *color;
+    for (color = color_dic; color->name; color++) {
+        if (!strcmp(color->name, name)) {
+            return color->var_ptr;
+        }
+    }
+    return NULL;
+}
+
+void
+colors_init(bool enable_color)
+{
+    /* If colored output is not enabled, just keep empty strings for color
+     * markers, including end marker.
+     */
+    if (!enable_color) {
+        return;
+    }
+
+    /* Color IDs to use in OVS_COLORS environment variable to overwrite
+     * defaults with custom colors.
+     */
+    const struct color_key color_dic[] =
+    {
+        { "ac", &(colors.actions) },
+        { "dr", &(colors.drop) },
+        { "le", &(colors.learn) },
+        { "pm", &(colors.param) },
+        { "pr", &(colors.paren) },
+        { "sp", &(colors.special) },
+        { "vl", &(colors.value) },
+        { NULL, NULL }
+    };
+
+    /* Actual color to use. First we define default values. */
+    colors.actions = "\33[1;31m\33[K";  /* bold red */
+    colors.drop    = "\33[34m\33[K";    /* blue */
+    colors.learn   = "\33[31m\33[K";    /* red */
+    colors.param   = "\33[36m\33[K";    /* cyan */
+    colors.paren   = "\33[35m\33[K";    /* magenta */
+    colors.special = "\33[33m\33[K";    /* yellow */
+    colors.value   = "\33[32m\33[K";    /* green */
+    colors.end     = "\33[m\33[K";      /* end marker */
+
+    /* Now, overwrite with user-defined color markers. */
+    colors_parse_from_env(color_dic);
+}
+
+/* Colorized output: get user-defined colors from OVS_COLORS environment
+ * variable. This must be a string of the form:
+ *     ac=01;31:r=34:le=:pm=02;32:pr=01;30
+ * (see color_dic[] in colors_init() function for all color names)
+ * If a color is missing from this string, default value is used instead.
+ * If a color name is assigned an empty or incorrect value (i.e. something
+ * containing characters other than decimals and ';'), fields using this color
+ * will not be highlighted.
+ * If a color is assigned more than once, the last (rightmost) value appearing
+ * in the string is kept.
+ * Unknown color names are ignored so as to ensure forward compatibility.
+ * (Feeling adventurous? Try combining markers: "ac=1;3;5;7;38;2;30;150;100".)
+ */
+static void
+colors_parse_from_env(const struct color_key color_dic[])
+{
+    const char *color_str;
+    char *s;
+    char *token;
+
+    color_str = getenv("OVS_COLORS");
+    if (color_str == NULL || *color_str == '\0')
+    {
+        return;
+    }
+    s = xstrdup(color_str);
+
+    /* Loop on tokens: they are separated by columns ':' */
+    for (token = strsep(&s, ":");
+            token != NULL;
+            token = strsep(&s, ":")) {
+        char *ptr;
+        char *name = strsep(&token, "=");
+        for (ptr = token; ptr != NULL && *ptr != '\0'; ptr++) {
+            /* We accept only decimals and ';' for color marker */
+            if (*ptr == ';' || (*ptr >= '0' && *ptr <= '9')) {
+                continue;
+            }
+            name = NULL;
+            break;
+        }
+        if (name != NULL) {
+            /* We found a name and marker contains only decimals and ';'
+             * Try to get a pointer to associated color variable
+             */
+            char **color_var_ptr = get_color(color_dic, name);
+            /* If we know that color, update its value */
+            if (color_var_ptr != NULL) {
+                *color_var_ptr = malloc(sizeof(char)*(11 + strlen(token)));
+                sprintf(*color_var_ptr, "\33[%sm\33[K", token);
+            }
+        }
+    }
+}
diff --git a/lib/colors.h b/lib/colors.h
new file mode 100644
index 000000000000..4bfbf9671264
--- /dev/null
+++ b/lib/colors.h
@@ -0,0 +1,42 @@ 
+/*
+ * Copyright (c) 2016 6WIND S.A.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COLORS_H
+#define COLORS_H 1
+
+#include <stdbool.h>
+
+struct colors {
+    /* Color codes for various situation. Each of these is a fully formed
+     * Select Graphic Rendition (SGR, "\33[...m") start string for the
+     * appropriate color.
+     */
+    char *actions;
+    char *drop;
+    char *learn;
+    char *param;
+    char *paren;
+    char *special;
+    char *value;
+
+    /* SGR end string. */
+    char *end;
+};
+extern struct colors colors;
+
+void colors_init(bool enable_color);
+
+#endif /* colors.h */
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index c535005797af..bde9fa0654de 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -33,6 +33,7 @@ 
 #include "classifier.h"
 #include "command-line.h"
 #include "daemon.h"
+#include "colors.h"
 #include "compiler.h"
 #include "dirs.h"
 #include "dynamic-string.h"
@@ -367,6 +368,8 @@  parse_options(int argc, char *argv[])
     allowed_protocols &= version_protocols;
     mask_allowed_ofp_versions(ofputil_protocols_to_version_bitmap(
                                   allowed_protocols));
+
+    colors_init(enable_color);
 }
 
 static void