diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2023-06-24 02:40:14 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2023-06-28 00:55:02 +0200 |
commit | cb558ab222f0dbda3afd985c2190f35693963ffa (patch) | |
tree | 1b3a0ffa54ac3603bab08c80f0481b21e9ae0b66 /src/test/test-ellipsize.c | |
parent | test-gunicode: add new test to show that unichar_iswide() is borked (diff) | |
download | systemd-cb558ab222f0dbda3afd985c2190f35693963ffa.tar.xz systemd-cb558ab222f0dbda3afd985c2190f35693963ffa.zip |
string-util: pass ANSI sequences through unchanged
Cutting off in the middle may leave the terminal in a bad state, breaking
further output. But we don't know what a given ANSI sequence does, e.g.
ANSI_NORMAL should not be skipped. But it is also nice to keep various
sequences intact, so that if we had part of the string in blue, and we cut out
the beginning of the blue part, we still want to keep the remainder in color.
So let's just pass them through, stripping out the characters that take up
actual space.
Also, use memcpy_safe as we may end up copying zero bytes when ellipsizing at
the start/end of a string.
Fixes: #24502
This also fixes an ugliness where we would ellipsize string with ANSI
sequences too much, leading to output that was narrower on screen than the
requested length:
Starting AAAAAAAAAAAAAAAAAAAAA.service
Starting BBBBBBBBBBBBBBBBBBBBB.service
Starting LONG…ER.service
Co-authored-by: Jan Janssen <medhefgo@web.de>
Diffstat (limited to 'src/test/test-ellipsize.c')
-rw-r--r-- | src/test/test-ellipsize.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c index a96644f617..40edc289e9 100644 --- a/src/test/test-ellipsize.c +++ b/src/test/test-ellipsize.c @@ -4,6 +4,7 @@ #include "alloc-util.h" #include "constants.h" +#include "escape.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" @@ -115,4 +116,44 @@ TEST(ellipsize) { test_ellipsize_one("shórt"); } +TEST(ellipsize_ansi) { + const char *s = ANSI_HIGHLIGHT_YELLOW_UNDERLINE "yęllow" + ANSI_HIGHLIGHT_GREY_UNDERLINE "grěy" + ANSI_HIGHLIGHT_BLUE_UNDERLINE "blue" + ANSI_NORMAL "nórmął"; + size_t len = strlen(s); + + for (unsigned percent = 0; percent <= 100; percent += 15) + for (ssize_t x = 21; x >= 0; x--) { + _cleanup_free_ char *t = ellipsize_mem(s, len, x, percent); + printf("%02zd: \"%s\"\n", x, t); + assert_se(utf8_is_valid(t)); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *e = cescape(t); + printf(" : \"%s\"\n", e); + } + } +} + +TEST(ellipsize_ansi_cats) { + _cleanup_free_ char *e, *f, *g, *h; + + /* Make sure we don't cut off in the middle of an ANSI escape sequence. */ + + e = ellipsize("01" ANSI_NORMAL "23", 4, 0); + puts(e); + assert_se(streq(e, "01" ANSI_NORMAL "23")); + f = ellipsize("ab" ANSI_NORMAL "cd", 4, 90); + puts(f); + assert_se(streq(f, "ab" ANSI_NORMAL "cd")); + + g = ellipsize("🐱🐱" ANSI_NORMAL "🐱🐱" ANSI_NORMAL, 5, 0); + puts(g); + assert_se(streq(g, "…" ANSI_NORMAL "🐱🐱" ANSI_NORMAL)); + h = ellipsize("🐱🐱" ANSI_NORMAL "🐱🐱" ANSI_NORMAL, 5, 90); + puts(h); + assert_se(streq(h, "🐱…" ANSI_NORMAL "🐱" ANSI_NORMAL)); +} + DEFINE_TEST_MAIN(LOG_INFO); |