fix: truncate in runes rather than bytes

truncate measures and slices by byte, so a string cut inside a
multi-byte rune both mis-measures the fixed-width column it is being
laid out against and emits a broken character. Everything it is handed
is server-supplied — alert names, label values, annotations — and none
of that is guaranteed to be ASCII.

Identical behaviour for the ASCII case.
This commit is contained in:
Niklas Ye
2026-08-07 13:31:51 +02:00
parent 4740687b96
commit f75ae60e74
+9 -2
View File
@@ -808,12 +808,19 @@ func renderBarWidth(count, maxCount, maxWidth int) int {
return w return w
} }
// truncate shortens s to max terminal cells, marking the cut with an ellipsis.
//
// Counted in runes rather than bytes: these strings are laid out against
// fixed-width columns, and a byte cut through a multi-byte rune would both
// mis-measure the column and emit a broken character. Server-supplied text —
// labels, annotations, delivery errors — is not guaranteed to be ASCII.
func truncate(s string, max int) string { func truncate(s string, max int) string {
if max < 1 { if max < 1 {
return "" return ""
} }
if len(s) <= max { r := []rune(s)
if len(r) <= max {
return s return s
} }
return s[:max-1] + "…" return string(r[:max-1]) + "…"
} }