@@ -16,9 +16,13 @@ use crate::logger::{GroupEvent, JsonEvent, get_group_event, get_json_event};
1616
1717pub const CODSPEED_U8_COLOR_CODE : u8 = 208 ; // #FF8700
1818
19+ /// Spinner tick characters - smooth animation for a polished feel
20+ const SPINNER_TICKS : & [ & str ] = & [ " " , ". " , ".." , " ." ] ;
21+
1922lazy_static ! {
2023 pub static ref SPINNER : Arc <Mutex <Option <ProgressBar >>> = Arc :: new( Mutex :: new( None ) ) ;
2124 pub static ref IS_TTY : bool = std:: io:: IsTerminal :: is_terminal( & std:: io:: stdout( ) ) ;
25+ static ref CURRENT_GROUP_NAME : Arc <Mutex <Option <String >>> = Arc :: new( Mutex :: new( None ) ) ;
2226}
2327
2428/// Hide the progress bar temporarily, execute `f`, then redraw the progress bar.
@@ -67,26 +71,34 @@ impl Log for LocalLogger {
6771 if let Some ( group_event) = get_group_event ( record) {
6872 match group_event {
6973 GroupEvent :: Start ( name) | GroupEvent :: StartOpened ( name) => {
70- eprintln ! (
71- "\n {}" ,
72- style( format!( "►►► {name} " ) )
73- . bold( )
74- . color256( CODSPEED_U8_COLOR_CODE )
75- ) ;
74+ let header = format_group_header ( & name) ;
75+ eprintln ! ( "\n {header}" ) ;
76+
77+ // Store current group name for completion message
78+ if let Ok ( mut current) = CURRENT_GROUP_NAME . lock ( ) {
79+ * current = Some ( name. clone ( ) ) ;
80+ }
7681
7782 if * IS_TTY {
7883 let spinner = ProgressBar :: new_spinner ( ) ;
84+ let tick_strings: Vec < String > = SPINNER_TICKS
85+ . iter ( )
86+ . map ( |s| format ! ( "{}" , style( s) . color256( CODSPEED_U8_COLOR_CODE ) . dim( ) ) )
87+ . collect ( ) ;
88+ let tick_strs: Vec < & str > =
89+ tick_strings. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
90+
7991 spinner. set_style (
8092 ProgressStyle :: with_template (
81- format ! (
82- " {{spinner:>.{CODSPEED_U8_COLOR_CODE}}} {{wide_msg:.{CODSPEED_U8_COLOR_CODE}.bold}}"
83- )
84- . as_str ( ) ,
93+ & format ! (
94+ " {{spinner}} {{wide_msg:.{CODSPEED_U8_COLOR_CODE}}} {{elapsed:.dim}}"
95+ ) ,
8596 )
86- . unwrap ( ) ,
97+ . unwrap ( )
98+ . tick_strings ( & tick_strs) ,
8799 ) ;
88100 spinner. set_message ( format ! ( "{name}..." ) ) ;
89- spinner. enable_steady_tick ( Duration :: from_millis ( 100 ) ) ;
101+ spinner. enable_steady_tick ( Duration :: from_millis ( 300 ) ) ;
90102 SPINNER . lock ( ) . unwrap ( ) . replace ( spinner) ;
91103 } else {
92104 eprintln ! ( "{name}..." ) ;
@@ -95,8 +107,22 @@ impl Log for LocalLogger {
95107 GroupEvent :: End => {
96108 if * IS_TTY {
97109 let mut spinner = SPINNER . lock ( ) . unwrap ( ) ;
98- if let Some ( spinner) = spinner. as_mut ( ) {
99- spinner. finish_and_clear ( ) ;
110+ if let Some ( pb) = spinner. as_mut ( ) {
111+ let elapsed = pb. elapsed ( ) ;
112+ pb. finish_and_clear ( ) ;
113+
114+ // Show completion message with checkmark
115+ if let Ok ( mut current) = CURRENT_GROUP_NAME . lock ( ) {
116+ if let Some ( name) = current. take ( ) {
117+ let elapsed_str = format_elapsed ( elapsed) ;
118+ eprintln ! (
119+ " {} {} {}" ,
120+ style( "\u{2714} " ) . green( ) . bold( ) ,
121+ style( name) . dim( ) ,
122+ style( elapsed_str) . dim( ) ,
123+ ) ;
124+ }
125+ }
100126 }
101127 }
102128 }
@@ -118,26 +144,62 @@ impl Log for LocalLogger {
118144 }
119145}
120146
147+ /// Format a group header with styled prefix
148+ fn format_group_header ( name : & str ) -> String {
149+ let prefix = style ( "\u{25B6} " ) . color256 ( CODSPEED_U8_COLOR_CODE ) . bold ( ) ;
150+ let title = style ( name) . bold ( ) ;
151+ format ! ( "{prefix} {title}" )
152+ }
153+
154+ /// Format elapsed duration in a compact human-readable way
155+ fn format_elapsed ( duration : Duration ) -> String {
156+ let secs = duration. as_secs ( ) ;
157+ let millis = duration. as_millis ( ) ;
158+
159+ if secs >= 60 {
160+ let mins = secs / 60 ;
161+ let remaining_secs = secs % 60 ;
162+ format ! ( "{mins}m {remaining_secs}s" )
163+ } else if secs > 0 {
164+ format ! ( "{secs}.{:01}s" , ( millis % 1000 ) / 100 )
165+ } else {
166+ format ! ( "{millis}ms" )
167+ }
168+ }
169+
121170/// Print a log record to the console with the appropriate style
122171fn print_record ( record : & log:: Record ) {
123- let error_style = Style :: new ( ) . red ( ) ;
124- let info_style = Style :: new ( ) . white ( ) ;
125- let warn_style = Style :: new ( ) . yellow ( ) ;
126- let debug_style = Style :: new ( ) . blue ( ) . dim ( ) ;
127- let trace_style = Style :: new ( ) . black ( ) . dim ( ) ;
128-
129172 match record. level ( ) {
130- log:: Level :: Error => eprintln ! ( "{}" , error_style. apply_to( record. args( ) ) ) ,
131- log:: Level :: Warn => eprintln ! ( "{}" , warn_style. apply_to( record. args( ) ) ) ,
132- log:: Level :: Info => eprintln ! ( "{}" , info_style. apply_to( record. args( ) ) ) ,
133- log:: Level :: Debug => eprintln ! (
134- "{}" ,
135- debug_style. apply_to( format!( "[DEBUG::{}] {}" , record. target( ) , record. args( ) ) ) ,
136- ) ,
137- log:: Level :: Trace => eprintln ! (
138- "{}" ,
139- trace_style. apply_to( format!( "[TRACE::{}] {}" , record. target( ) , record. args( ) ) )
140- ) ,
173+ log:: Level :: Error => {
174+ let prefix = style ( "\u{2717} " ) . red ( ) . bold ( ) ;
175+ let msg = Style :: new ( ) . red ( ) . apply_to ( record. args ( ) ) ;
176+ eprintln ! ( " {prefix} {msg}" ) ;
177+ }
178+ log:: Level :: Warn => {
179+ let prefix = style ( "\u{25B2} " ) . yellow ( ) ;
180+ let msg = Style :: new ( ) . yellow ( ) . apply_to ( record. args ( ) ) ;
181+ eprintln ! ( " {prefix} {msg}" ) ;
182+ }
183+ log:: Level :: Info => {
184+ let msg = Style :: new ( ) . white ( ) . apply_to ( record. args ( ) ) ;
185+ eprintln ! ( " {msg}" ) ;
186+ }
187+ log:: Level :: Debug => {
188+ let prefix = style ( "\u{00B7} " ) . dim ( ) ;
189+ let msg = Style :: new ( )
190+ . blue ( )
191+ . dim ( )
192+ . apply_to ( format ! ( "{}" , record. args( ) ) ) ;
193+ eprintln ! ( " {prefix} {msg}" ) ;
194+ }
195+ log:: Level :: Trace => {
196+ let msg = Style :: new ( ) . black ( ) . dim ( ) . apply_to ( format ! (
197+ "[TRACE::{}] {}" ,
198+ record. target( ) ,
199+ record. args( )
200+ ) ) ;
201+ eprintln ! ( " {msg}" ) ;
202+ }
141203 }
142204}
143205
0 commit comments