chiark / gitweb /
journalctl: add highlighting for matched substring
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 27 Jan 2018 12:00:09 +0000 (13:00 +0100)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:50:22 +0000 (07:50 +0200)
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.

src/basic/string-util.c
src/basic/string-util.h
src/test/test-strip-tab-ansi.c

index 3e19e43acf91edf74cd7476bcb5e6c5ae8a95ba9..b4d3517364ba18dbcccf02e0cbfbd37490988c5e 100644 (file)
@@ -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;
 }
 
index 7cbfef725f4e3a29ba02ba8d6d387480027aa8e2..dbdfe1383953326166713fabf73df582b98fdafb 100644 (file)
@@ -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_;
 
index aabb7c40e70762e8f99e950b222c49ba08fdd66d..838a6e4db66c326556c53ed73af46d12953731af 100644 (file)
@@ -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);