diff options
Diffstat (limited to 'internal/color/color.go')
| -rw-r--r-- | internal/color/color.go | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/internal/color/color.go b/internal/color/color.go index e971382..5a1aa54 100644 --- a/internal/color/color.go +++ b/internal/color/color.go @@ -180,6 +180,37 @@ func VisibleLen(s string) int { return utf8.RuneCountInString(ansiRe.ReplaceAllString(s, "")) } +// TruncateVisible truncates s to at most maxVisible visible characters, +// preserving ANSI SGR codes. Assumes cells follow the common pattern +// "\x1b[...mTEXT\x1b[0m" or are plain text. Appends "..." when truncated. +func TruncateVisible(s string, maxVisible int) string { + if maxVisible < 3 { + maxVisible = 3 + } + if VisibleLen(s) <= maxVisible { + return s + } + var pre, suf string + rest := s + if idx := strings.IndexByte(rest, 'm'); idx >= 0 && strings.HasPrefix(rest, "\x1b[") { + pre = rest[:idx+1] + rest = rest[idx+1:] + } + if strings.HasSuffix(rest, Reset) { + suf = Reset + rest = rest[:len(rest)-len(Reset)] + } + runes := []rune(rest) + budget := maxVisible - 3 + if budget < 0 { + budget = 0 + } + if len(runes) > budget { + rest = string(runes[:budget]) + "..." + } + return pre + rest + suf +} + // WrapANSI wraps text to the given visible width, ignoring ANSI color codes // when measuring. Each input line (split on "\n") is handled on its own: a line // that already fits is returned untouched, so indentation and aligned UI are |
