From: Zbigniew Jędrzejewski-Szmek Date: Sat, 27 Jan 2018 12:00:09 +0000 (+0100) Subject: journalctl: add highlighting for matched substring X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=33ab419a61bfb3667f0b99f9804e4315b0e79c15;p=elogind.git journalctl: add highlighting for matched substring Red is used for highligting, the same as grep does. Except when the line is highlighted red already, because it has high priority, in which case plain ansi highlight is used for the matched substring. Coloring is implemented for short and cat outputs, and not for other types. I guess we could also add it for verbose output in the future. --- diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 3e19e43ac..b4d351736 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -30,6 +30,7 @@ #include "gunicode.h" #include "macro.h" #include "string-util.h" +//#include "terminal-util.h" #include "utf8.h" #include "util.h" @@ -652,7 +653,17 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin return ret; } -char *strip_tab_ansi(char **ibuf, size_t *_isz) { +static void advance_offsets(ssize_t diff, size_t offsets[2], size_t shift[2], size_t size) { + if (!offsets) + return; + + if ((size_t) diff < offsets[0]) + shift[0] += size; + if ((size_t) diff < offsets[1]) + shift[1] += size; +} + +char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { const char *i, *begin = NULL; enum { STATE_OTHER, @@ -660,7 +671,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { STATE_BRACKET } state = STATE_OTHER; char *obuf = NULL; - size_t osz = 0, isz; + size_t osz = 0, isz, shift[2] = {}; FILE *f; assert(ibuf); @@ -688,15 +699,18 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { break; else if (*i == '\x1B') state = STATE_ESCAPE; - else if (*i == '\t') + else if (*i == '\t') { fputs(" ", f); - else + advance_offsets(i - *ibuf, highlight, shift, 7); + } else fputc(*i, f); + break; case STATE_ESCAPE: if (i >= *ibuf + isz) { /* EOT */ fputc('\x1B', f); + advance_offsets(i - *ibuf, highlight, shift, 1); break; } else if (*i == '[') { state = STATE_BRACKET; @@ -704,6 +718,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { } else { fputc('\x1B', f); fputc(*i, f); + advance_offsets(i - *ibuf, highlight, shift, 1); state = STATE_OTHER; } @@ -715,6 +730,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { (!(*i >= '0' && *i <= '9') && !IN_SET(*i, ';', 'm'))) { fputc('\x1B', f); fputc('[', f); + advance_offsets(i - *ibuf, highlight, shift, 2); state = STATE_OTHER; i = begin-1; } else if (*i == 'm') @@ -736,6 +752,11 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { if (_isz) *_isz = osz; + if (highlight) { + highlight[0] += shift[0]; + highlight[1] += shift[1]; + } + return obuf; } diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 7cbfef725..dbdfe1383 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -185,7 +185,7 @@ char* strshorten(char *s, size_t l); char *strreplace(const char *text, const char *old_string, const char *new_string); -char *strip_tab_ansi(char **p, size_t *l); +char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]); char *strextend_with_separator(char **x, const char *separator, ...) _sentinel_; diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c index aabb7c40e..838a6e4db 100644 --- a/src/test/test-strip-tab-ansi.c +++ b/src/test/test-strip-tab-ansi.c @@ -28,24 +28,24 @@ int main(int argc, char *argv[]) { char *p; assert_se(p = strdup("\tFoobar\tbar\twaldo\t")); - assert_se(strip_tab_ansi(&p, NULL)); + assert_se(strip_tab_ansi(&p, NULL, NULL)); fprintf(stdout, "<%s>\n", p); assert_se(streq(p, " Foobar bar waldo ")); free(p); assert_se(p = strdup(ANSI_HIGHLIGHT "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL)); - assert_se(strip_tab_ansi(&p, NULL)); + assert_se(strip_tab_ansi(&p, NULL, NULL)); fprintf(stdout, "<%s>\n", p); assert_se(streq(p, "Hello world!")); free(p); assert_se(p = strdup("\x1B[\x1B[\t\x1B[" ANSI_HIGHLIGHT "\x1B[" "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL)); - assert_se(strip_tab_ansi(&p, NULL)); + assert_se(strip_tab_ansi(&p, NULL, NULL)); assert_se(streq(p, "\x1B[\x1B[ \x1B[\x1B[Hello world!")); free(p); assert_se(p = strdup("\x1B[waldo")); - assert_se(strip_tab_ansi(&p, NULL)); + assert_se(strip_tab_ansi(&p, NULL, NULL)); assert_se(streq(p, "\x1B[waldo")); free(p);