From: Simon Marchi Date: Fri, 22 Nov 2019 18:24:16 +0000 (-0500) Subject: common: introduce struct bt_common_color_codes and function bt_common_color_get_codes X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=3aa68ad9462c0d154a57b98d0f51880128731781 common: introduce struct bt_common_color_codes and function bt_common_color_get_codes The behavior of the color functions is currently initialized at startup. If we detect that colors should be enabled, we set the bt_common_color_code_* variables once and for all. The following patches will introduce string formatting functions that optionally use color, based on a parameter with three values: - always: always use colors, regardless of what we detected at startup - never: never use colors, regardless of what we detected at startup - auto: use colors based on what we detected at startup One option would be to add some color functions that take a parameter, so you could do: bt_common_color_bg_cyan_opt(BT_COMMON_COLOR_WHEN_ALWAYS) bt_common_color_bg_cyan_opt(BT_COMMON_COLOR_WHEN_NEVER) bt_common_color_bg_cyan_opt(BT_COMMON_COLOR_WHEN_AUTO) However, I find this very verbose, so not very practical. This patch introduces a new structure type bt_common_color_codes that holds the color codes for the current terminal, or empty strings. It also introduces a function bt_common_color_get_codes that accepts an always/never/auto parameter. It initializes a bt_common_color_codes structure with the color codes (or empty strings) to use. This will allow the string formatting function to conditionally use colors without being too verbose: struct bt_common_color_codes codes; bt_common_color_get_codes(&codes, use_colors); printf("%sHello%s\n", codes.fg_cyan, codes.reset); Change-Id: I887e736291e9e1fe54156a81ce4011b3906d6f3c Signed-off-by: Simon Marchi Reviewed-on: https://review.lttng.org/c/babeltrace/+/2431 Tested-by: jenkins Reviewed-by: Philippe Proulx --- diff --git a/src/common/common.c b/src/common/common.c index 86c70341..1a7d57cc 100644 --- a/src/common/common.c +++ b/src/common/common.c @@ -79,14 +79,107 @@ static const char *bt_common_color_code_bg_magenta = ""; static const char *bt_common_color_code_bg_cyan = ""; static const char *bt_common_color_code_bg_light_gray = ""; +/* + * A color codes structure always filled with the proper color codes for the + * terminal. + */ +static struct bt_common_color_codes color_codes; + +/* + * A color codes structure always filled with empty strings, for when we want no + * colors. + */ +static struct bt_common_color_codes no_color_codes = { + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", +}; + static void __attribute__((constructor)) bt_common_color_ctor(void) { - if (bt_common_colors_supported()) { - const char *term_env_var; - const char *bright_means_bold_env_var; - bool bright_means_bold = true; + const char *term_env_var; + const char *bright_means_bold_env_var; + bool bright_means_bold = true; + const char *code_fg_bright_red; + const char *code_fg_bright_green; + const char *code_fg_bright_yellow; + const char *code_fg_bright_blue; + const char *code_fg_bright_magenta; + const char *code_fg_bright_cyan; + const char *code_fg_bright_light_gray; + + /* + * Check whether or not the terminal supports having + * bold foreground colors which do _not_ become bright + * colors, that is, the lines + * + * $ echo -e "\033[31mTHIS\n\033[1mTHAT\033[0m" + * + * have the _same_ color, but `THAT` uses a bold font. + * + * This is the case of the kitty terminal emulator. + * + * It's also possible with GNOME Terminal since 3.27.2 + * and xfce4-terminal since 0.8.7 (and GNOME VTE since + * 0.51.2), but it's user-configurable. Since we don't + * have this configuration value here, assume it's not + * the case to support old versions of GNOME Terminal. + * + * Any user can set the + * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` environment + * variable to `0` to use the bright foreground color + * codes instead of making the normal foreground color + * codes bold. + * + * Summary: + * + * With kitty or when + * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` is `0`: + * Output bright colors using dedicated SGR codes + * 90 to 97. + * + * Otherwise: + * Output bright colors with bold + SGR codes 30 to + * 37. + */ + term_env_var = getenv("TERM"); + + if (term_env_var && strcmp(term_env_var, "xterm-kitty") == 0) { + /* + * The kitty terminal emulator supports + * non-bright bold foreground colors. + */ + bright_means_bold = false; + } + + bright_means_bold_env_var = + getenv("BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD"); + + if (bright_means_bold_env_var) { + bright_means_bold = + !(strcmp(bright_means_bold_env_var, "0") == 0); + } + if (bright_means_bold) { + code_fg_bright_red = BT_COMMON_COLOR_FG_BOLD_RED; + code_fg_bright_green = BT_COMMON_COLOR_FG_BOLD_GREEN; + code_fg_bright_yellow = BT_COMMON_COLOR_FG_BOLD_YELLOW; + code_fg_bright_blue = BT_COMMON_COLOR_FG_BOLD_BLUE; + code_fg_bright_magenta = BT_COMMON_COLOR_FG_BOLD_MAGENTA; + code_fg_bright_cyan = BT_COMMON_COLOR_FG_BOLD_CYAN; + code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BOLD_LIGHT_GRAY; + } else { + code_fg_bright_red = BT_COMMON_COLOR_FG_BRIGHT_RED; + code_fg_bright_green = BT_COMMON_COLOR_FG_BRIGHT_GREEN; + code_fg_bright_yellow = BT_COMMON_COLOR_FG_BRIGHT_YELLOW; + code_fg_bright_blue = BT_COMMON_COLOR_FG_BRIGHT_BLUE; + code_fg_bright_magenta = BT_COMMON_COLOR_FG_BRIGHT_MAGENTA; + code_fg_bright_cyan = BT_COMMON_COLOR_FG_BRIGHT_CYAN; + code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BRIGHT_LIGHT_GRAY; + } + + if (bt_common_colors_supported()) { bt_common_color_code_reset = BT_COMMON_COLOR_RESET; bt_common_color_code_bold = BT_COMMON_COLOR_BOLD; bt_common_color_code_fg_default = BT_COMMON_COLOR_FG_DEFAULT; @@ -98,76 +191,13 @@ void __attribute__((constructor)) bt_common_color_ctor(void) bt_common_color_code_fg_cyan = BT_COMMON_COLOR_FG_CYAN; bt_common_color_code_fg_light_gray = BT_COMMON_COLOR_FG_LIGHT_GRAY; - /* - * Check whether or not the terminal supports having - * bold foreground colors which do _not_ become bright - * colors, that is, the lines - * - * $ echo -e "\033[31mTHIS\n\033[1mTHAT\033[0m" - * - * have the _same_ color, but `THAT` uses a bold font. - * - * This is the case of the kitty terminal emulator. - * - * It's also possible with GNOME Terminal since 3.27.2 - * and xfce4-terminal since 0.8.7 (and GNOME VTE since - * 0.51.2), but it's user-configurable. Since we don't - * have this configuration value here, assume it's not - * the case to support old versions of GNOME Terminal. - * - * Any user can set the - * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` environment - * variable to `0` to use the bright foreground color - * codes instead of making the normal foreground color - * codes bold. - * - * Summary: - * - * With kitty or when - * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` is `0`: - * Output bright colors using dedicated SGR codes - * 90 to 97. - * - * Otherwise: - * Output bright colors with bold + SGR codes 30 to - * 37. - */ - term_env_var = getenv("TERM"); - BT_ASSERT(term_env_var); - - if (strcmp(term_env_var, "xterm-kitty") == 0) { - /* - * The kitty terminal emulator supports - * non-bright bold foreground colors. - */ - bright_means_bold = false; - } - - bright_means_bold_env_var = - getenv("BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD"); - - if (bright_means_bold_env_var) { - bright_means_bold = - !(strcmp(bright_means_bold_env_var, "0") == 0); - } - - if (bright_means_bold) { - bt_common_color_code_fg_bright_red = BT_COMMON_COLOR_FG_BOLD_RED; - bt_common_color_code_fg_bright_green = BT_COMMON_COLOR_FG_BOLD_GREEN; - bt_common_color_code_fg_bright_yellow = BT_COMMON_COLOR_FG_BOLD_YELLOW; - bt_common_color_code_fg_bright_blue = BT_COMMON_COLOR_FG_BOLD_BLUE; - bt_common_color_code_fg_bright_magenta = BT_COMMON_COLOR_FG_BOLD_MAGENTA; - bt_common_color_code_fg_bright_cyan = BT_COMMON_COLOR_FG_BOLD_CYAN; - bt_common_color_code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BOLD_LIGHT_GRAY; - } else { - bt_common_color_code_fg_bright_red = BT_COMMON_COLOR_FG_BRIGHT_RED; - bt_common_color_code_fg_bright_green = BT_COMMON_COLOR_FG_BRIGHT_GREEN; - bt_common_color_code_fg_bright_yellow = BT_COMMON_COLOR_FG_BRIGHT_YELLOW; - bt_common_color_code_fg_bright_blue = BT_COMMON_COLOR_FG_BRIGHT_BLUE; - bt_common_color_code_fg_bright_magenta = BT_COMMON_COLOR_FG_BRIGHT_MAGENTA; - bt_common_color_code_fg_bright_cyan = BT_COMMON_COLOR_FG_BRIGHT_CYAN; - bt_common_color_code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BRIGHT_LIGHT_GRAY; - } + bt_common_color_code_fg_bright_red = code_fg_bright_red; + bt_common_color_code_fg_bright_green = code_fg_bright_green; + bt_common_color_code_fg_bright_yellow = code_fg_bright_yellow; + bt_common_color_code_fg_bright_blue = code_fg_bright_blue; + bt_common_color_code_fg_bright_magenta = code_fg_bright_magenta; + bt_common_color_code_fg_bright_cyan = code_fg_bright_cyan; + bt_common_color_code_fg_bright_light_gray = code_fg_bright_light_gray; bt_common_color_code_bg_default = BT_COMMON_COLOR_BG_DEFAULT; bt_common_color_code_bg_red = BT_COMMON_COLOR_BG_RED; @@ -178,6 +208,32 @@ void __attribute__((constructor)) bt_common_color_ctor(void) bt_common_color_code_bg_cyan = BT_COMMON_COLOR_BG_CYAN; bt_common_color_code_bg_light_gray = BT_COMMON_COLOR_BG_LIGHT_GRAY; } + + color_codes.reset = BT_COMMON_COLOR_RESET; + color_codes.bold = BT_COMMON_COLOR_BOLD; + color_codes.fg_default = BT_COMMON_COLOR_FG_DEFAULT; + color_codes.fg_red = BT_COMMON_COLOR_FG_RED; + color_codes.fg_green = BT_COMMON_COLOR_FG_GREEN; + color_codes.fg_yellow = BT_COMMON_COLOR_FG_YELLOW; + color_codes.fg_blue = BT_COMMON_COLOR_FG_BLUE; + color_codes.fg_magenta = BT_COMMON_COLOR_FG_MAGENTA; + color_codes.fg_cyan = BT_COMMON_COLOR_FG_CYAN; + color_codes.fg_light_gray = BT_COMMON_COLOR_FG_LIGHT_GRAY; + color_codes.fg_bright_red = code_fg_bright_red; + color_codes.fg_bright_green = code_fg_bright_green; + color_codes.fg_bright_yellow = code_fg_bright_yellow; + color_codes.fg_bright_blue = code_fg_bright_blue; + color_codes.fg_bright_magenta = code_fg_bright_magenta; + color_codes.fg_bright_cyan = code_fg_bright_cyan; + color_codes.fg_bright_light_gray = code_fg_bright_light_gray; + color_codes.bg_default = BT_COMMON_COLOR_BG_DEFAULT; + color_codes.bg_red = BT_COMMON_COLOR_BG_RED; + color_codes.bg_green = BT_COMMON_COLOR_BG_GREEN; + color_codes.bg_yellow = BT_COMMON_COLOR_BG_YELLOW; + color_codes.bg_blue = BT_COMMON_COLOR_BG_BLUE; + color_codes.bg_magenta = BT_COMMON_COLOR_BG_MAGENTA; + color_codes.bg_cyan = BT_COMMON_COLOR_BG_CYAN; + color_codes.bg_light_gray = BT_COMMON_COLOR_BG_LIGHT_GRAY; } BT_HIDDEN @@ -561,6 +617,25 @@ const char *bt_common_color_bg_light_gray(void) return bt_common_color_code_bg_light_gray; } +BT_HIDDEN +void bt_common_color_get_codes(struct bt_common_color_codes *codes, + enum bt_common_color_when use_colors) +{ + if (use_colors == BT_COMMON_COLOR_WHEN_ALWAYS) { + *codes = color_codes; + } else if (use_colors == BT_COMMON_COLOR_WHEN_NEVER) { + *codes = no_color_codes; + } else { + BT_ASSERT(use_colors == BT_COMMON_COLOR_WHEN_AUTO); + + if (bt_common_colors_supported()) { + *codes = color_codes; + } else { + *codes = no_color_codes; + } + } +} + BT_HIDDEN GString *bt_common_string_until(const char *input, const char *escapable_chars, const char *end_chars, size_t *end_pos) diff --git a/src/common/common.h b/src/common/common.h index e931e2d1..b5990a88 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -77,6 +77,40 @@ #define BT_COMMON_COLOR_BG_CYAN "\033[46m" #define BT_COMMON_COLOR_BG_LIGHT_GRAY "\033[47m" +enum bt_common_color_when { + BT_COMMON_COLOR_WHEN_AUTO, + BT_COMMON_COLOR_WHEN_ALWAYS, + BT_COMMON_COLOR_WHEN_NEVER, +}; + +struct bt_common_color_codes { + const char *reset; + const char *bold; + const char *fg_default; + const char *fg_red; + const char *fg_green; + const char *fg_yellow; + const char *fg_blue; + const char *fg_magenta; + const char *fg_cyan; + const char *fg_light_gray; + const char *fg_bright_red; + const char *fg_bright_green; + const char *fg_bright_yellow; + const char *fg_bright_blue; + const char *fg_bright_magenta; + const char *fg_bright_cyan; + const char *fg_bright_light_gray; + const char *bg_default; + const char *bg_red; + const char *bg_green; + const char *bg_yellow; + const char *bg_blue; + const char *bg_magenta; + const char *bg_cyan; + const char *bg_light_gray; +}; + struct bt_common_lttng_live_url_parts { GString *proto; GString *hostname; @@ -199,6 +233,10 @@ const char *bt_common_color_bg_cyan(void); BT_HIDDEN const char *bt_common_color_bg_light_gray(void); +BT_HIDDEN +void bt_common_color_get_codes(struct bt_common_color_codes *codes, + enum bt_common_color_when use_colors); + /* * Returns the substring from `input` to the first character found * in the list of characters `end_chars`, unescaping any character