@@ -12,6 +12,8 @@ import (
15+ "github.com/charmbracelet/x/ansi"
15 "charm.land/fantasy"
17 "charm.land/fantasy"
16 "github.com/charmbracelet/crush/internal/config"
18 "github.com/charmbracelet/crush/internal/config"
17 "github.com/charmbracelet/crush/internal/fsext"
19 "github.com/charmbracelet/crush/internal/fsext"
@@ -423,15 +425,15 @@ func formatOutput(stdout, stderr string, execErr error) string {
425func TruncateOutput(content string) string {
427func TruncateOutput(content string) string {
426− if len(content) <= MaxOutputLength {
428+ if ansi.StringWidth(content) <= MaxOutputLength {
427 return content
429 return content
430 halfLength := MaxOutputLength / 2
432 halfLength := MaxOutputLength / 2
431− start := content[:halfLength]
433+ start := ansi.Truncate(content, halfLength, "")
432− end := content[len(content)-halfLength:]
434+ end := ansi.TruncateLeft(content, ansi.StringWidth(content)-halfLength, "")
434− truncatedLinesCount := countLines(content[halfLength : len(content)-halfLength])
436+ truncatedLinesCount := max(strings.Count(content, "\n")-strings.Count(start, "\n")-strings.Count(end, "\n"), 0)
435 return fmt.Sprintf("%s\n\n... [%d lines truncated] ...\n\n%s", start, truncatedLinesCount, end)
437 return fmt.Sprintf("%s\n\n... [%d lines truncated] ...\n\n%s", start, truncatedLinesCount, end)
@@ -439,13 +441,6 @@ func truncateOutput(content string) string {
439 return TruncateOutput(content)
441 return TruncateOutput(content)
442−func countLines(s string) int {
446− return len(strings.Split(s, "\n"))
449func normalizeWorkingDir(path string) string {
444func normalizeWorkingDir(path string) string {
450 if runtime.GOOS == "windows" {
445 if runtime.GOOS == "windows" {
451 path = strings.ReplaceAll(path, fsext.WindowsWorkingDirDrive(), "")
446 path = strings.ReplaceAll(path, fsext.WindowsWorkingDirDrive(), "")