@@ -19,6 +19,11 @@ function getVisibleLength(str: string): number {
1919}
2020
2121function truncateMessage ( msg : string , maxLength ?: number ) : string {
22+ // If not a TTY and no explicit length provided, don't truncate
23+ if ( ! process . stdout . isTTY && maxLength === undefined ) {
24+ return msg ;
25+ }
26+
2227 const terminalWidth = maxLength ?? process . stdout . columns ?? 80 ;
2328 const availableWidth = terminalWidth - 5 ; // Reserve some space for the spinner and padding
2429 const visibleLength = getVisibleLength ( msg ) ;
@@ -28,13 +33,45 @@ function truncateMessage(msg: string, maxLength?: number): string {
2833 }
2934
3035 // We need to truncate based on visible characters, but preserve ANSI sequences
31- // Simple approach: truncate character by character until we fit
32- let truncated = msg ;
33- while ( getVisibleLength ( truncated ) > availableWidth - 3 ) {
34- truncated = truncated . slice ( 0 , - 1 ) ;
36+ const targetLength = availableWidth - 3 ;
37+ let visibleCount = 0 ;
38+ let result = "" ;
39+
40+ const ansiRegex = / \x1b \] 8 ; ; [ ^ \x07 ] * \x07 | \x1b \[ [ 0 - 9 ; ] * [ a - z A - Z ] / g;
41+ let lastIndex = 0 ;
42+ let match ;
43+
44+ while ( ( match = ansiRegex . exec ( msg ) ) !== null ) {
45+ const textPart = msg . slice ( lastIndex , match . index ) ;
46+ const textPartVisibleLength = textPart . length ;
47+
48+ if ( visibleCount + textPartVisibleLength > targetLength ) {
49+ if ( visibleCount <= targetLength ) {
50+ result += textPart . slice ( 0 , targetLength - visibleCount ) + "..." ;
51+ visibleCount = targetLength + 1 ; // Mark as done
52+ }
53+ result += match [ 0 ] ;
54+ } else {
55+ if ( visibleCount <= targetLength ) {
56+ result += textPart + match [ 0 ] ;
57+ visibleCount += textPartVisibleLength ;
58+ } else {
59+ result += match [ 0 ] ;
60+ }
61+ }
62+ lastIndex = ansiRegex . lastIndex ;
63+ }
64+
65+ if ( visibleCount <= targetLength ) {
66+ const remainingText = msg . slice ( lastIndex ) ;
67+ if ( visibleCount + remainingText . length > targetLength ) {
68+ result += remainingText . slice ( 0 , targetLength - visibleCount ) + "..." ;
69+ } else {
70+ result += remainingText ;
71+ }
3572 }
3673
37- return truncated + "..." ;
74+ return result ;
3875}
3976
4077const wrappedClackSpinner = ( ) => {
0 commit comments