ansiTruncate returns the first maxWidth visual columns of an ANSI-styled string, properly passing through escape sequences without counting them as visible width.
(s string, maxWidth int)
| 472 | // ansiTruncate returns the first maxWidth visual columns of an ANSI-styled string, |
| 473 | // properly passing through escape sequences without counting them as visible width. |
| 474 | func ansiTruncate(s string, maxWidth int) string { |
| 475 | var result strings.Builder |
| 476 | width := 0 |
| 477 | inEscape := false |
| 478 | for _, r := range s { |
| 479 | if r == '\033' { |
| 480 | inEscape = true |
| 481 | result.WriteRune(r) |
| 482 | continue |
| 483 | } |
| 484 | if inEscape { |
| 485 | result.WriteRune(r) |
| 486 | if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') { |
| 487 | inEscape = false |
| 488 | } |
| 489 | continue |
| 490 | } |
| 491 | if width >= maxWidth { |
| 492 | break |
| 493 | } |
| 494 | result.WriteRune(r) |
| 495 | width++ |
| 496 | } |
| 497 | // Reset any open ANSI styling |
| 498 | result.WriteString("\033[0m") |
| 499 | return result.String() |
| 500 | } |
| 501 | |
| 502 | // ansiSkip skips the first skipWidth visual columns of an ANSI-styled string |
| 503 | // and returns the remainder. |