@@ -99,16 +99,19 @@ impl Spinner {
9999 out : & mut impl Write ,
100100 ) -> io:: Result < ( ) > {
101101 self . frame_index = 0 ;
102- self . cursor_hidden = false ;
103- execute ! (
102+ let show_result = execute ! (
104103 out,
105104 MoveToColumn ( 0 ) ,
106105 Clear ( ClearType :: CurrentLine ) ,
107106 SetForegroundColor ( theme. spinner_done) ,
108107 Print ( format!( "✔ {label}\n " ) ) ,
109108 ResetColor ,
110109 Show
111- ) ?;
110+ ) ;
111+ if show_result. is_ok ( ) {
112+ self . cursor_hidden = false ;
113+ }
114+ show_result?;
112115 out. flush ( )
113116 }
114117
@@ -119,16 +122,19 @@ impl Spinner {
119122 out : & mut impl Write ,
120123 ) -> io:: Result < ( ) > {
121124 self . frame_index = 0 ;
122- self . cursor_hidden = false ;
123- execute ! (
125+ let show_result = execute ! (
124126 out,
125127 MoveToColumn ( 0 ) ,
126128 Clear ( ClearType :: CurrentLine ) ,
127129 SetForegroundColor ( theme. spinner_failed) ,
128130 Print ( format!( "✘ {label}\n " ) ) ,
129131 ResetColor ,
130132 Show
131- ) ?;
133+ ) ;
134+ if show_result. is_ok ( ) {
135+ self . cursor_hidden = false ;
136+ }
137+ show_result?;
132138 out. flush ( )
133139 }
134140}
@@ -927,6 +933,7 @@ fn strip_ansi(input: &str) -> String {
927933#[ cfg( test) ]
928934mod tests {
929935 use super :: { strip_ansi, MarkdownStreamState , Spinner , TerminalRenderer } ;
936+ use std:: io:: { self , Write } ;
930937
931938 #[ test]
932939 fn renders_markdown_with_styling_and_lists ( ) {
@@ -1081,4 +1088,48 @@ mod tests {
10811088 let output = String :: from_utf8_lossy ( & out) ;
10821089 assert ! ( output. contains( "Working" ) ) ;
10831090 }
1091+
1092+ struct AlwaysFailWriter ;
1093+
1094+ impl Write for AlwaysFailWriter {
1095+ fn write ( & mut self , _buf : & [ u8 ] ) -> io:: Result < usize > {
1096+ Err ( io:: Error :: other ( "write failed" ) )
1097+ }
1098+
1099+ fn flush ( & mut self ) -> io:: Result < ( ) > {
1100+ Ok ( ( ) )
1101+ }
1102+ }
1103+
1104+ #[ test]
1105+ fn spinner_finish_error_keeps_cursor_hidden_for_drop_recovery ( ) {
1106+ let terminal_renderer = TerminalRenderer :: new ( ) ;
1107+ let mut spinner = Spinner :: new ( ) ;
1108+ let mut out = Vec :: new ( ) ;
1109+ spinner
1110+ . tick ( "Working" , terminal_renderer. color_theme ( ) , & mut out)
1111+ . expect ( "tick succeeds" ) ;
1112+
1113+ let mut failing_out = AlwaysFailWriter ;
1114+ let result = spinner. finish ( "Done" , terminal_renderer. color_theme ( ) , & mut failing_out) ;
1115+
1116+ assert ! ( result. is_err( ) ) ;
1117+ assert ! ( spinner. cursor_hidden) ;
1118+ }
1119+
1120+ #[ test]
1121+ fn spinner_fail_error_keeps_cursor_hidden_for_drop_recovery ( ) {
1122+ let terminal_renderer = TerminalRenderer :: new ( ) ;
1123+ let mut spinner = Spinner :: new ( ) ;
1124+ let mut out = Vec :: new ( ) ;
1125+ spinner
1126+ . tick ( "Working" , terminal_renderer. color_theme ( ) , & mut out)
1127+ . expect ( "tick succeeds" ) ;
1128+
1129+ let mut failing_out = AlwaysFailWriter ;
1130+ let result = spinner. fail ( "Done" , terminal_renderer. color_theme ( ) , & mut failing_out) ;
1131+
1132+ assert ! ( result. is_err( ) ) ;
1133+ assert ! ( spinner. cursor_hidden) ;
1134+ }
10841135}
0 commit comments