@@ -7,6 +7,67 @@ export function escapeImportPath(path: string) {
77 return isWindows ? path . replaceAll ( "\\" , "\\\\" ) : path ;
88}
99
10+ // Removes ANSI escape sequences to get actual visible length
11+ function getVisibleLength ( str : string ) : number {
12+ return (
13+ str
14+ // Remove terminal hyperlinks: \u001b]8;;URL\u0007TEXT\u001b]8;;\u0007
15+ . replace ( / \u001b ] 8 ; ; [ ^ \u0007 ] * \u0007 / g, "" )
16+ // Remove standard ANSI escape sequences (colors, cursor movement, etc.)
17+ . replace ( / \x1b \[ [ 0 - 9 ; ] * [ a - z A - Z ] / g, "" ) . length
18+ ) ;
19+ }
20+
21+ function truncateMessage ( msg : string , maxLength ?: number ) : string {
22+ const terminalWidth = maxLength ?? process . stdout . columns ?? 80 ;
23+ const availableWidth = terminalWidth - 5 ; // Reserve some space for the spinner and padding
24+ const visibleLength = getVisibleLength ( msg ) ;
25+
26+ if ( visibleLength <= availableWidth ) {
27+ return msg ;
28+ }
29+
30+ // 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 ) ;
35+ }
36+
37+ return truncated + "..." ;
38+ }
39+
40+ const wrappedClackSpinner = ( ) => {
41+ let currentMessage = "" ;
42+ let isActive = false ;
43+
44+ const handleResize = ( ) => {
45+ if ( isActive && currentMessage ) {
46+ spinner . message ( truncateMessage ( currentMessage ) ) ;
47+ }
48+ } ;
49+
50+ const spinner = clackSpinner ( ) ;
51+
52+ return {
53+ start : ( msg ?: string ) : void => {
54+ currentMessage = msg ?? "" ;
55+ isActive = true ;
56+ process . stdout . on ( "resize" , handleResize ) ;
57+ spinner . start ( truncateMessage ( currentMessage ) ) ;
58+ } ,
59+ stop : ( msg ?: string , code ?: number ) : void => {
60+ isActive = false ;
61+ process . stdout . off ( "resize" , handleResize ) ;
62+ spinner . stop ( truncateMessage ( msg ?? "" ) , code ) ;
63+ } ,
64+ message : ( msg ?: string ) : void => {
65+ currentMessage = msg ?? "" ;
66+ spinner . message ( truncateMessage ( currentMessage ) ) ;
67+ } ,
68+ } ;
69+ } ;
70+
1071const ballmerSpinner = ( ) => ( {
1172 start : ( msg ?: string ) : void => {
1273 log . step ( msg ?? "" ) ;
@@ -21,4 +82,4 @@ const ballmerSpinner = () => ({
2182
2283// This will become unecessary with the next clack release, the bug was fixed here:
2384// https://github.com/natemoo-re/clack/pull/182
24- export const spinner = ( ) => ( isWindows ? ballmerSpinner ( ) : clackSpinner ( ) ) ;
85+ export const spinner = ( ) => ( isWindows ? ballmerSpinner ( ) : wrappedClackSpinner ( ) ) ;
0 commit comments