summaryrefslogtreecommitdiffstats
path: root/src/shared/pretty-print.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shared/pretty-print.c198
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);
+}