@@ -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+
610671struct 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 }
0 commit comments