diff options
-rw-r--r-- | printf.c | 59 | ||||
-rwxr-xr-x | tests.sh | 5 | ||||
-rw-r--r-- | tests/test_printf_color.out | 20 |
3 files changed, 76 insertions, 8 deletions
@@ -69,6 +69,11 @@ static int bfs_printf_flush(CFILE *cfile, const struct bfs_printf *directive, co return fflush(cfile->file); } +/** Check if we can safely colorize this directive. */ +static bool should_color(CFILE *cfile, const struct bfs_printf *directive) { + return cfile->colors && strcmp(directive->str, "%s") == 0; +} + /** * Print a value to a temporary buffer before formatting it. */ @@ -210,7 +215,11 @@ static int bfs_printf_D(CFILE *cfile, const struct bfs_printf *directive, const /** %f: file name */ static int bfs_printf_f(CFILE *cfile, const struct bfs_printf *directive, const struct BFTW *ftwbuf) { - return fprintf(cfile->file, directive->str, ftwbuf->path + ftwbuf->nameoff); + if (should_color(cfile, directive)) { + return cfprintf(cfile, "%pF", ftwbuf); + } else { + return fprintf(cfile->file, directive->str, ftwbuf->path + ftwbuf->nameoff); + } } /** %F: file system type */ @@ -273,14 +282,28 @@ static int bfs_printf_h(CFILE *cfile, const struct bfs_printf *directive, const return -1; } - int ret = fprintf(cfile->file, directive->str, buf); + int ret; + if (should_color(cfile, directive)) { + ret = cfprintf(cfile, "${di}%s${rs}", buf); + } else { + ret = fprintf(cfile->file, directive->str, buf); + } + free(copy); return ret; } /** %H: current root */ static int bfs_printf_H(CFILE *cfile, const struct bfs_printf *directive, const struct BFTW *ftwbuf) { - return fprintf(cfile->file, directive->str, ftwbuf->root); + if (should_color(cfile, directive)) { + if (ftwbuf->depth == 0) { + return cfprintf(cfile, "%pP", ftwbuf); + } else { + return cfprintf(cfile, "${di}%s${rs}", ftwbuf->root); + } + } else { + return fprintf(cfile->file, directive->str, ftwbuf->root); + } } /** %i: inode */ @@ -312,6 +335,10 @@ static int bfs_printf_l(CFILE *cfile, const struct bfs_printf *directive, const const char *target = ""; if (ftwbuf->type == BFS_LNK) { + if (should_color(cfile, directive)) { + return cfprintf(cfile, "%pL", ftwbuf); + } + const struct bfs_stat *statbuf = bftw_cached_stat(ftwbuf, BFS_STAT_NOFOLLOW); size_t len = statbuf ? statbuf->size : 0; @@ -361,16 +388,32 @@ static int bfs_printf_n(CFILE *cfile, const struct bfs_printf *directive, const /** %p: full path */ static int bfs_printf_p(CFILE *cfile, const struct bfs_printf *directive, const struct BFTW *ftwbuf) { - return fprintf(cfile->file, directive->str, ftwbuf->path); + if (should_color(cfile, directive)) { + return cfprintf(cfile, "%pP", ftwbuf); + } else { + return fprintf(cfile->file, directive->str, ftwbuf->path); + } } /** %P: path after root */ static int bfs_printf_P(CFILE *cfile, const struct bfs_printf *directive, const struct BFTW *ftwbuf) { - const char *path = ftwbuf->path + strlen(ftwbuf->root); - if (path[0] == '/') { - ++path; + size_t offset = strlen(ftwbuf->root); + if (ftwbuf->path[offset] == '/') { + ++offset; + } + + if (should_color(cfile, directive)) { + if (ftwbuf->depth == 0) { + return 0; + } + + struct BFTW copybuf = *ftwbuf; + copybuf.path += offset; + copybuf.nameoff -= offset; + return cfprintf(cfile, "%pP", ©buf); + } else { + return fprintf(cfile->file, directive->str, ftwbuf->path + offset); } - return fprintf(cfile->file, directive->str, path); } /** %s: size */ @@ -765,6 +765,7 @@ bfs_tests=( test_printf_invalid_format test_printf_duplicate_flag test_printf_must_be_numeric + test_printf_color test_type_multi @@ -2305,6 +2306,10 @@ function test_printf_must_be_numeric() { ! quiet invoke_bfs basic -printf '%+p' } +function test_printf_color() { + LS_COLORS= bfs_diff -color -path './rainbow*' -printf '%H %h %f %p %P %l\n' +} + function test_fprintf() { invoke_bfs basic -fprintf scratch/test_fprintf.out '%%p(%p) %%d(%d) %%f(%f) %%h(%h) %%H(%H) %%P(%P) %%m(%m) %%M(%M) %%y(%y)\n' sort -o scratch/test_fprintf.out scratch/test_fprintf.out diff --git a/tests/test_printf_color.out b/tests/test_printf_color.out new file mode 100644 index 0000000..dc04d14 --- /dev/null +++ b/tests/test_printf_color.out @@ -0,0 +1,20 @@ +[01;34m.[0m [01;34m.[0m [01;34mrainbow[0m [01;34m./[0m[01;34mrainbow[0m [01;34mrainbow[0m +[01;34m.[0m [01;34m./rainbow[0m [01;32mexec.sh[0m [01;34m./rainbow/[0m[01;32mexec.sh[0m [01;34mrainbow/[0m[01;32mexec.sh[0m +[01;34m.[0m [01;34m./rainbow[0m [01;35msocket[0m [01;34m./rainbow/[0m[01;35msocket[0m [01;34mrainbow/[0m[01;35msocket[0m +[01;34m.[0m [01;34m./rainbow[0m [01;36mbroken[0m [01;34m./rainbow/[0m[01;36mbroken[0m [01;34mrainbow/[0m[01;36mbroken[0m nowhere +[01;34m.[0m [01;34m./rainbow[0m [01;36mlink.txt[0m [01;34m./rainbow/[0m[01;36mlink.txt[0m [01;34mrainbow/[0m[01;36mlink.txt[0m file.txt +[01;34m.[0m [01;34m./rainbow[0m [30;42msticky_ow[0m [01;34m./rainbow/[0m[30;42msticky_ow[0m [01;34mrainbow/[0m[30;42msticky_ow[0m +[01;34m.[0m [01;34m./rainbow[0m [30;43msgid[0m [01;34m./rainbow/[0m[30;43msgid[0m [01;34mrainbow/[0m[30;43msgid[0m +[01;34m.[0m [01;34m./rainbow[0m [33mpipe[0m [01;34m./rainbow/[0m[33mpipe[0m [01;34mrainbow/[0m[33mpipe[0m +[01;34m.[0m [01;34m./rainbow[0m [34;42mow[0m [01;34m./rainbow/[0m[34;42mow[0m [01;34mrainbow/[0m[34;42mow[0m +[01;34m.[0m [01;34m./rainbow[0m [37;41msugid[0m [01;34m./rainbow/[0m[37;41msugid[0m [01;34mrainbow/[0m[37;41msugid[0m +[01;34m.[0m [01;34m./rainbow[0m [37;41msuid[0m [01;34m./rainbow/[0m[37;41msuid[0m [01;34mrainbow/[0m[37;41msuid[0m +[01;34m.[0m [01;34m./rainbow[0m [37;44msticky[0m [01;34m./rainbow/[0m[37;44msticky[0m [01;34mrainbow/[0m[37;44msticky[0m +[01;34m.[0m [01;34m./rainbow[0m file.dat [01;34m./rainbow/[0mfile.dat [01;34mrainbow/[0mfile.dat +[01;34m.[0m [01;34m./rainbow[0m file.txt [01;34m./rainbow/[0mfile.txt [01;34mrainbow/[0mfile.txt +[01;34m.[0m [01;34m./rainbow[0m mh1 [01;34m./rainbow/[0mmh1 [01;34mrainbow/[0mmh1 +[01;34m.[0m [01;34m./rainbow[0m mh2 [01;34m./rainbow/[0mmh2 [01;34mrainbow/[0mmh2 +[01;34m.[0m [01;34m./rainbow[0m star.gz [01;34m./rainbow/[0mstar.gz [01;34mrainbow/[0mstar.gz +[01;34m.[0m [01;34m./rainbow[0m star.tar [01;34m./rainbow/[0mstar.tar [01;34mrainbow/[0mstar.tar +[01;34m.[0m [01;34m./rainbow[0m star.tar.gz [01;34m./rainbow/[0mstar.tar.gz [01;34mrainbow/[0mstar.tar.gz +[01;34m.[0m [01;34m./rainbow[0m [01;36mchardev_link[0m [01;34m./rainbow/[0m[01;36mchardev_link[0m [01;34mrainbow/[0m[01;36mchardev_link[0m [01;34m/dev/[0m[01;33mnull[0m |