Skip to content

Commit f1fa639

Browse files
authored
Merge pull request #157 from vinxcls/freebsd-coloring
Support for FreeBSD-style ls Coloring
2 parents 4223543 + b4a8afc commit f1fa639

File tree

5 files changed

+107
-5
lines changed

5 files changed

+107
-5
lines changed

src/color.c

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,67 @@ static int parse_gnu_ls_colors(struct colors *colors, const char *ls_colors) {
607607
return ret;
608608
}
609609

610+
/** Parse the FreeBSD $LSCOLORS format. */
611+
static int parse_bsd_ls_colors(struct colors *colors, const char *lscolors) {
612+
static const char *keys[] = {
613+
"di", "ln", "so", "pi", "ex", "bd", "cd", "su", "sg", "tw", "ow"
614+
};
615+
616+
static const char *fg_codes[256] = {
617+
['a'] = "30", ['b'] = "31", ['c'] = "32", ['d'] = "33",
618+
['e'] = "34", ['f'] = "35", ['g'] = "36", ['h'] = "37", ['x'] = "39",
619+
['A'] = "1;30", ['B'] = "1;31", ['C'] = "1;32", ['D'] = "1;33",
620+
['E'] = "1;34", ['F'] = "1;35", ['G'] = "1;36", ['H'] = "1;37", ['X'] = "1"
621+
};
622+
623+
static const char *bg_codes[256] = {
624+
['a'] = "40", ['b'] = "41", ['c'] = "42", ['d'] = "43",
625+
['e'] = "44", ['f'] = "45", ['g'] = "46", ['h'] = "47", ['x'] = "49",
626+
['A'] = "4;100", ['B'] = "4;101", ['C'] = "4;102", ['D'] = "4;103",
627+
['E'] = "4;104", ['F'] = "4;105", ['G'] = "4;106", ['H'] = "4;107", ['X'] = "4;49"
628+
};
629+
630+
// Please refer to https://man.freebsd.org/cgi/man.cgi?ls(1)#ENVIRONMENT
631+
char complete_colors[] = "exfxcxdxbxegedabagacad";
632+
633+
size_t max = strlen(complete_colors);
634+
size_t len = strnlen(lscolors, max + 1);
635+
if (len == 0 || len % 2 != 0 || len > max) {
636+
errno = EINVAL;
637+
return -1;
638+
}
639+
memcpy(complete_colors, lscolors, len);
640+
641+
for (size_t i = 0; i < countof(keys); ++i) {
642+
uint8_t fg = complete_colors[i * 2];
643+
uint8_t bg = complete_colors[(i * 2) + 1];
644+
645+
const char *fg_code = fg_codes[fg];
646+
const char *bg_code = bg_codes[bg];
647+
648+
if (!fg_code || !bg_code) {
649+
continue;
650+
}
651+
652+
dchar *esc = dstrprintf("%s;%s", fg_code, bg_code);
653+
if (!esc) {
654+
return -1;
655+
}
656+
657+
int ret = set_esc(colors, keys[i], esc);
658+
dstrfree(esc);
659+
if (ret != 0) {
660+
return -1;
661+
}
662+
}
663+
664+
return 0;
665+
}
666+
667+
static bool str_isset(const char *str) {
668+
return str && *str;
669+
}
670+
610671
struct colors *parse_colors(void) {
611672
struct colors *colors = ALLOC(struct colors);
612673
if (!colors) {
@@ -676,12 +737,22 @@ struct colors *parse_colors(void) {
676737
goto fail;
677738
}
678739

679-
if (parse_gnu_ls_colors(colors, getenv("LS_COLORS")) != 0) {
680-
goto fail;
681-
}
682-
if (parse_gnu_ls_colors(colors, getenv("BFS_COLORS")) != 0) {
683-
goto fail;
740+
const char *gnu_colors = getenv("LS_COLORS");
741+
const char *bfs_colors = getenv("BFS_COLORS");
742+
const char *bsd_colors = getenv("LSCOLORS");
743+
if (str_isset(gnu_colors) || str_isset(bfs_colors)) {
744+
if (parse_gnu_ls_colors(colors, gnu_colors) != 0) {
745+
goto fail;
746+
}
747+
if (parse_gnu_ls_colors(colors, bfs_colors) != 0) {
748+
goto fail;
749+
}
750+
} else if (str_isset(bsd_colors)) {
751+
if (parse_bsd_ls_colors(colors, bsd_colors) != 0) {
752+
goto fail;
753+
}
684754
}
755+
685756
if (build_iext_trie(colors) != 0) {
686757
goto fail;
687758
}

tests/bfs/color_bsd.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
$'rainbow/\e[1m'
2+
$'rainbow/\e[1m/'$'\e[0m'
3+
rainbow
4+
rainbow/sugid
5+
rainbow/suid
6+
rainbow/sticky_ow
7+
rainbow/ow
8+
rainbow/sgid
9+
rainbow/exec.sh
10+
rainbow/socket
11+
rainbow/pipe
12+
rainbow/broken
13+
rainbow/chardev_link
14+
rainbow/link.txt
15+
rainbow/sticky
16+
rainbow/file.dat
17+
rainbow/file.txt
18+
rainbow/lower.gz
19+
rainbow/lower.tar
20+
rainbow/lower.tar.gz
21+
rainbow/lu.tar.GZ
22+
rainbow/mh1
23+
rainbow/mh2
24+
rainbow/ul.TAR.gz
25+
rainbow/upper.GZ
26+
rainbow/upper.TAR
27+
rainbow/upper.TAR.GZ

tests/bfs/color_bsd.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
LSCOLORS="eB" bfs_diff rainbow -color

tests/bfs/color_bsd_fail.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# LSCOLORS can be at most 22 characters long (11 color pairs); this one has 24.
2+
! LSCOLORS="exfxcxdxbxegedabagacadeB" invoke_bfs rainbow -color

tests/util.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ stdenv() {
3434

3535
export LS_COLORS=""
3636
unset BFS_COLORS
37+
unset LSCOLORS
3738

3839
if [ "$UNAME" = Darwin ]; then
3940
# ASan on macOS likes to report

0 commit comments

Comments
 (0)