summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2022-04-15 13:31:22 -0400
committerTavian Barnes <tavianator@tavianator.com>2022-04-15 14:45:08 -0400
commit7241d6cc35134fcb5ec6dfa81bbd01e430b2415f (patch)
tree3b3dbde25dff9430ca644f680249a6add224f213
parenta571aa9ef6f3dc2099ee33c5040f8c54776ddece (diff)
downloadbfs-7241d6cc35134fcb5ec6dfa81bbd01e430b2415f.tar.xz
color: Support a separate $BFS_COLORS environment variable
-rw-r--r--bfs.114
-rw-r--r--color.c123
-rw-r--r--color.h6
-rw-r--r--parse.c2
-rwxr-xr-xtests.sh9
5 files changed, 84 insertions, 70 deletions
diff --git a/bfs.1 b/bfs.1
index b9288e8..53a9831 100644
--- a/bfs.1
+++ b/bfs.1
@@ -715,16 +715,26 @@ Yes/no prompts (e.g. from
.BR \-ok )
will also be interpreted according to the current locale.
.RE
-.TP
+.PP
.B LS_COLORS
+.br
+.B BFS_COLORS
+.RS
Controls the colors used when displaying file paths if
.B \-color
is enabled.
.B bfs
-interprets this environment variable is interpreted the same way GNU
+interprets
+.B LS_COLORS
+the same way GNU
.BR ls (1)
does (see
.BR dir_colors (5)).
+.B BFS_COLORS
+can be used to customize
+.B bfs
+without affecting other commands.
+.RE
.TP
.B NO_COLOR
Causes
diff --git a/color.c b/color.c
index d59875c..9e267da 100644
--- a/color.c
+++ b/color.c
@@ -34,9 +34,6 @@
#include <time.h>
#include <unistd.h>
-/**
- * The parsed form of LS_COLORS.
- */
struct colors {
char *reset;
char *leftcode;
@@ -198,7 +195,7 @@ static const char *get_ext_color(const struct colors *colors, const char *filena
}
/**
- * Parse a chunk of LS_COLORS that may have escape sequences. The supported
+ * Parse a chunk of $LS_COLORS that may have escape sequences. The supported
* escapes are:
*
* \a, \b, \f, \n, \r, \t, \v:
@@ -358,7 +355,66 @@ fail:
return NULL;
}
-struct colors *parse_colors(const char *ls_colors) {
+/** Parse the GNU $LS_COLORS format. */
+static void parse_gnu_ls_colors(struct colors *colors, const char *ls_colors) {
+ for (const char *chunk = ls_colors, *next; chunk; chunk = next) {
+ if (chunk[0] == '*') {
+ char *key = unescape(chunk + 1, '=', &next);
+ if (!key) {
+ continue;
+ }
+
+ char *value = unescape(next, ':', &next);
+ if (value) {
+ if (set_ext_color(colors, key, value) != 0) {
+ dstrfree(value);
+ }
+ }
+
+ dstrfree(key);
+ } else {
+ const char *equals = strchr(chunk, '=');
+ if (!equals) {
+ break;
+ }
+
+ char *value = unescape(equals + 1, ':', &next);
+ if (!value) {
+ continue;
+ }
+
+ char *key = strndup(chunk, equals - chunk);
+ if (!key) {
+ dstrfree(value);
+ continue;
+ }
+
+ // All-zero values should be treated like NULL, to fall
+ // back on any other relevant coloring for that file
+ if (strspn(value, "0") == strlen(value)
+ && strcmp(key, "rs") != 0
+ && strcmp(key, "lc") != 0
+ && strcmp(key, "rc") != 0
+ && strcmp(key, "ec") != 0) {
+ dstrfree(value);
+ value = NULL;
+ }
+
+ if (set_color(colors, key, value) != 0) {
+ dstrfree(value);
+ }
+ free(key);
+ }
+ }
+
+ if (colors->link && strcmp(colors->link, "target") == 0) {
+ colors->link_as_target = true;
+ dstrfree(colors->link);
+ colors->link = NULL;
+ }
+}
+
+struct colors *parse_colors() {
struct colors *colors = malloc(sizeof(struct colors));
if (!colors) {
return NULL;
@@ -422,61 +478,8 @@ struct colors *parse_colors(const char *ls_colors) {
return NULL;
}
- for (const char *chunk = ls_colors, *next; chunk; chunk = next) {
- if (chunk[0] == '*') {
- char *key = unescape(chunk + 1, '=', &next);
- if (!key) {
- continue;
- }
-
- char *value = unescape(next, ':', &next);
- if (value) {
- if (set_ext_color(colors, key, value) != 0) {
- dstrfree(value);
- }
- }
-
- dstrfree(key);
- } else {
- const char *equals = strchr(chunk, '=');
- if (!equals) {
- break;
- }
-
- char *value = unescape(equals + 1, ':', &next);
- if (!value) {
- continue;
- }
-
- char *key = strndup(chunk, equals - chunk);
- if (!key) {
- dstrfree(value);
- continue;
- }
-
- // All-zero values should be treated like NULL, to fall
- // back on any other relevant coloring for that file
- if (strspn(value, "0") == strlen(value)
- && strcmp(key, "rs") != 0
- && strcmp(key, "lc") != 0
- && strcmp(key, "rc") != 0
- && strcmp(key, "ec") != 0) {
- dstrfree(value);
- value = NULL;
- }
-
- if (set_color(colors, key, value) != 0) {
- dstrfree(value);
- }
- free(key);
- }
- }
-
- if (colors->link && strcmp(colors->link, "target") == 0) {
- colors->link_as_target = true;
- dstrfree(colors->link);
- colors->link = NULL;
- }
+ parse_gnu_ls_colors(colors, getenv("LS_COLORS"));
+ parse_gnu_ls_colors(colors, getenv("BFS_COLORS"));
return colors;
}
diff --git a/color.h b/color.h
index 36450bf..edf1ef7 100644
--- a/color.h
+++ b/color.h
@@ -27,18 +27,16 @@
#include <stdio.h>
/**
- * A lookup table for colors.
+ * A color scheme.
*/
struct colors;
/**
* Parse a color table.
*
- * @param ls_colors
- * A color table in the LS_COLORS environment variable format.
* @return The parsed color table.
*/
-struct colors *parse_colors(const char *ls_colors);
+struct colors *parse_colors(void);
/**
* Free a color table.
diff --git a/parse.c b/parse.c
index 17aeafe..65087a0 100644
--- a/parse.c
+++ b/parse.c
@@ -3856,7 +3856,7 @@ struct bfs_ctx *bfs_parse_cmdline(int argc, char *argv[]) {
use_color = COLOR_NEVER;
}
- ctx->colors = parse_colors(getenv("LS_COLORS"));
+ ctx->colors = parse_colors();
if (!ctx->colors) {
ctx->colors_error = errno;
}
diff --git a/tests.sh b/tests.sh
index c31d2c9..6d2c703 100755
--- a/tests.sh
+++ b/tests.sh
@@ -28,6 +28,9 @@ export MSAN_OPTIONS="abort_on_error=1"
export TSAN_OPTIONS="abort_on_error=1"
export UBSAN_OPTIONS="abort_on_error=1"
+export LS_COLORS=""
+unset BFS_COLORS
+
if [ -t 1 ]; then
BLD=$(printf '\033[01m')
RED=$(printf '\033[01;31m')
@@ -2452,7 +2455,7 @@ function test_printf_must_be_numeric() {
}
function test_printf_color() {
- LS_COLORS="" bfs_diff -color -path './rainbow*' -printf '%H %h %f %p %P %l\n'
+ bfs_diff -color -path './rainbow*' -printf '%H %h %f %p %P %l\n'
}
function test_fprintf() {
@@ -2552,11 +2555,11 @@ function test_extra_paren() {
}
function test_color() {
- LS_COLORS="" bfs_diff rainbow -color
+ bfs_diff rainbow -color
}
function test_color_L() {
- LS_COLORS="" bfs_diff -L rainbow -color
+ bfs_diff -L rainbow -color
}
function test_color_rs_lc_rc_ec() {