diff options
Diffstat (limited to 'src/shared/pretty-print.c')
-rw-r--r-- | src/shared/pretty-print.c | 198 |
1 files changed, 153 insertions, 45 deletions
diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index 2833063..c75f74a 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -5,6 +5,7 @@ #include <stdio.h> #include "alloc-util.h" +#include "color-util.h" #include "conf-files.h" #include "constants.h" #include "env-util.h" @@ -140,16 +141,8 @@ int terminal_urlify_path(const char *path, const char *text, char **ret) { if (isempty(text)) text = path; - if (!urlify_enabled()) { - char *n; - - n = strdup(text); - if (!n) - return -ENOMEM; - - *ret = n; - return 0; - } + if (!urlify_enabled()) + return strdup_to(ret, text); r = file_url_from_path(path, &url); if (r < 0) @@ -213,7 +206,7 @@ static int cat_file(const char *filename, bool newline, CatFlags flags) { break; LineType line_type = classify_line_type(line, flags); - if (flags & CAT_TLDR) { + if (FLAGS_SET(flags, CAT_TLDR)) { if (line_type == LINE_SECTION) { /* The start of a section, let's not print it yet. */ free_and_replace(section, line); @@ -236,6 +229,28 @@ static int cat_file(const char *filename, bool newline, CatFlags flags) { } } + /* Highlight the left side (directive) of a Foo=bar assignment */ + if (FLAGS_SET(flags, CAT_FORMAT_HAS_SECTIONS) && line_type == LINE_NORMAL) { + const char *p = strchr(line, '='); + if (p) { + _cleanup_free_ char *highlighted = NULL, *directive = NULL; + + directive = strndup(line, p - line); + if (!directive) + return log_oom(); + + highlighted = strjoin(ansi_highlight_green(), + directive, + "=", + ansi_normal(), + p + 1); + if (!highlighted) + return log_oom(); + + free_and_replace(line, highlighted); + } + } + printf("%s%s%s\n", line_type == LINE_SECTION ? ansi_highlight_cyan() : line_type == LINE_COMMENT ? ansi_highlight_grey() : @@ -271,14 +286,12 @@ void print_separator(void) { * one line filled with spaces with ANSI underline set, followed by a second (empty) line. */ if (underline_enabled()) { - size_t i, c; - - c = columns(); + size_t c = columns(); flockfile(stdout); fputs_unlocked(ANSI_UNDERLINE, stdout); - for (i = 0; i < c; i++) + for (size_t i = 0; i < c; i++) fputc_unlocked(' ', stdout); fputs_unlocked(ANSI_NORMAL "\n\n", stdout); @@ -287,7 +300,7 @@ void print_separator(void) { fputs("\n\n", stdout); } -static int guess_type(const char **name, char ***prefixes, bool *is_collection, const char **extension) { +static int guess_type(const char **name, char ***ret_prefixes, bool *ret_is_collection, const char **ret_extension) { /* Try to figure out if name is like tmpfiles.d/ or systemd/system-presets/, * i.e. a collection of directories without a main config file. * Incidentally, all those formats don't use sections. So we return a single @@ -295,11 +308,10 @@ static int guess_type(const char **name, char ***prefixes, bool *is_collection, */ _cleanup_free_ char *n = NULL; - bool usr = false, run = false, coll = false; + bool run = false, coll = false; const char *ext = ".conf"; /* This is static so that the array doesn't get deallocated when we exit the function */ static const char* const std_prefixes[] = { CONF_PATHS(""), NULL }; - static const char* const usr_prefixes[] = { CONF_PATHS_USR(""), NULL }; static const char* const run_prefixes[] = { "/run/", NULL }; if (path_equal(*name, "environment.d")) @@ -311,50 +323,33 @@ static int guess_type(const char **name, char ***prefixes, bool *is_collection, if (!n) return log_oom(); - /* All systemd-style config files should support the /usr-/etc-/run split and - * dropins. Let's add a blanket rule that allows us to support them without keeping - * an explicit list. */ - if (path_startswith(n, "systemd") && endswith(n, ".conf")) - usr = true; - delete_trailing_chars(n, "/"); + /* We assume systemd-style config files support the /usr-/run-/etc split and dropins. */ + if (endswith(n, ".d")) coll = true; - if (path_equal(n, "environment")) - usr = true; - if (path_equal(n, "udev/hwdb.d")) ext = ".hwdb"; - - if (path_equal(n, "udev/rules.d")) + else if (path_equal(n, "udev/rules.d")) ext = ".rules"; - - if (path_equal(n, "kernel/install.d")) + else if (path_equal(n, "kernel/install.d")) ext = ".install"; - - if (path_equal(n, "systemd/ntp-units.d")) { + else if (path_equal(n, "systemd/ntp-units.d")) { coll = true; ext = ".list"; - } - - if (path_equal(n, "systemd/relabel-extra.d")) { + } else if (path_equal(n, "systemd/relabel-extra.d")) { coll = run = true; ext = ".relabel"; - } - - if (PATH_IN_SET(n, "systemd/system-preset", "systemd/user-preset")) { + } else if (PATH_IN_SET(n, "systemd/system-preset", "systemd/user-preset")) { coll = true; ext = ".preset"; } - if (path_equal(n, "systemd/user-preset")) - usr = true; - - *prefixes = (char**) (usr ? usr_prefixes : run ? run_prefixes : std_prefixes); - *is_collection = coll; - *extension = ext; + *ret_prefixes = (char**) (run ? run_prefixes : std_prefixes); + *ret_is_collection = coll; + *ret_extension = ext; return 0; } @@ -419,3 +414,116 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) { return cat_files(path, files, flags); } + +int terminal_tint_color(double hue, char **ret) { + double red, green, blue; + int r; + + assert(ret); + + r = get_default_background_color(&red, &green, &blue); + if (r < 0) + return log_debug_errno(r, "Unable to get terminal background color: %m"); + + double s, v; + rgb_to_hsv(red, green, blue, /* h= */ NULL, &s, &v); + + if (v > 50) /* If the background is bright, then pull down saturation */ + s = 25; + else /* otherwise pump it up */ + s = 75; + + v = MAX(20, v); /* Make sure we don't hide the color in black */ + + uint8_t r8, g8, b8; + hsv_to_rgb(hue, s, v, &r8, &g8, &b8); + + if (asprintf(ret, "48;2;%u;%u;%u", r8, g8, b8) < 0) + return -ENOMEM; + + return 0; +} + +bool shall_tint_background(void) { + static int cache = -1; + + if (cache >= 0) + return cache; + + cache = getenv_bool("SYSTEMD_TINT_BACKGROUND"); + if (cache == -ENXIO) + return (cache = true); + if (cache < 0) + log_debug_errno(cache, "Failed to parse $SYSTEMD_TINT_BACKGROUND, leaving background tinting enabled: %m"); + + return cache != 0; +} + +void draw_progress_bar(const char *prefix, double percentage) { + + fputc('\r', stderr); + if (prefix) + fputs(prefix, stderr); + + if (!terminal_is_dumb()) { + size_t cols = columns(); + size_t prefix_length = strlen_ptr(prefix); + size_t length = cols > prefix_length + 6 ? cols - prefix_length - 6 : 0; + + if (length > 5 && percentage >= 0.0 && percentage <= 100.0) { + size_t p = (size_t) (length * percentage / 100.0); + bool separator_done = false; + + fputs(ansi_highlight_green(), stderr); + + for (size_t i = 0; i < length; i++) { + + if (i <= p) { + if (get_color_mode() == COLOR_24BIT) { + uint8_t r8, g8, b8; + double z = i == 0 ? 0 : (((double) i / p) * 100); + hsv_to_rgb(145 /* green */, z, 33 + z*2/3, &r8, &g8, &b8); + fprintf(stderr, "\x1B[38;2;%u;%u;%um", r8, g8, b8); + } + + fputs(special_glyph(SPECIAL_GLYPH_HORIZONTAL_FAT), stderr); + } else if (i+1 < length && !separator_done) { + fputs(ansi_normal(), stderr); + fputc(' ', stderr); + separator_done = true; + fputs(ansi_grey(), stderr); + } else + fputs(special_glyph(SPECIAL_GLYPH_HORIZONTAL_DOTTED), stderr); + } + + fputs(ansi_normal(), stderr); + fputc(' ', stderr); + } + } + + fprintf(stderr, + "%s%3.0f%%%s", + ansi_highlight(), + percentage, + ansi_normal()); + + if (!terminal_is_dumb()) + fputs(ANSI_ERASE_TO_END_OF_LINE, stderr); + + fputc('\r', stderr); + fflush(stderr); +} + +void clear_progress_bar(const char *prefix) { + + fputc('\r', stderr); + + if (terminal_is_dumb()) + fputs(strrepa(" ", strlen_ptr(prefix) + 4), /* 4: %3.0f%% */ + stderr); + else + fputs(ANSI_ERASE_TO_END_OF_LINE, stderr); + + fputc('\r', stderr); + fflush(stderr); +} |