1111//! instead of parsing error strings, providing a more robust solution.
1212//!
1313
14- use crate :: error:: UResult ;
14+ use crate :: error:: { UResult , USimpleError } ;
1515use crate :: locale:: translate;
1616
1717use clap:: error:: { ContextKind , ErrorKind } ;
@@ -108,43 +108,37 @@ impl<'a> ErrorFormatter<'a> {
108108 where
109109 F : FnOnce ( ) ,
110110 {
111+ let code = self . print_error ( err, exit_code) ;
112+ callback ( ) ;
113+ std:: process:: exit ( code) ;
114+ }
115+
116+ /// Print error and return exit code (no exit call)
117+ pub fn print_error ( & self , err : & Error , exit_code : i32 ) -> i32 {
111118 match err. kind ( ) {
112119 ErrorKind :: DisplayHelp | ErrorKind :: DisplayVersion => self . handle_display_errors ( err) ,
113- ErrorKind :: UnknownArgument => {
114- self . handle_unknown_argument_with_callback ( err, exit_code, callback)
115- }
120+ ErrorKind :: UnknownArgument => self . handle_unknown_argument ( err, exit_code) ,
116121 ErrorKind :: InvalidValue | ErrorKind :: ValueValidation => {
117- self . handle_invalid_value_with_callback ( err, exit_code, callback)
118- }
119- ErrorKind :: MissingRequiredArgument => {
120- self . handle_missing_required_with_callback ( err, exit_code, callback)
122+ self . handle_invalid_value ( err, exit_code)
121123 }
124+ ErrorKind :: MissingRequiredArgument => self . handle_missing_required ( err, exit_code) ,
122125 ErrorKind :: TooFewValues | ErrorKind :: TooManyValues | ErrorKind :: WrongNumberOfValues => {
123126 // These need full clap formatting
124127 eprint ! ( "{}" , err. render( ) ) ;
125- callback ( ) ;
126- std:: process:: exit ( exit_code) ;
128+ exit_code
127129 }
128- _ => self . handle_generic_error_with_callback ( err, exit_code, callback ) ,
130+ _ => self . handle_generic_error ( err, exit_code) ,
129131 }
130132 }
131133
132134 /// Handle help and version display
133- fn handle_display_errors ( & self , err : & Error ) -> ! {
135+ fn handle_display_errors ( & self , err : & Error ) -> i32 {
134136 print ! ( "{}" , err. render( ) ) ;
135- std :: process :: exit ( 0 ) ;
137+ 0
136138 }
137139
138- /// Handle unknown argument errors with callback
139- fn handle_unknown_argument_with_callback < F > (
140- & self ,
141- err : & Error ,
142- exit_code : i32 ,
143- callback : F ,
144- ) -> !
145- where
146- F : FnOnce ( ) ,
147- {
140+ /// Handle unknown argument errors
141+ fn handle_unknown_argument ( & self , err : & Error , exit_code : i32 ) -> i32 {
148142 if let Some ( invalid_arg) = err. get ( ContextKind :: InvalidArg ) {
149143 let arg_str = invalid_arg. to_string ( ) ;
150144 let error_word = translate ! ( "common-error" ) ;
@@ -179,21 +173,13 @@ impl<'a> ErrorFormatter<'a> {
179173
180174 self . print_usage_and_help ( ) ;
181175 } else {
182- self . print_simple_error_with_callback (
183- & translate ! ( "clap-error-unexpected-argument-simple" ) ,
184- exit_code,
185- || { } ,
186- ) ;
176+ self . print_simple_error_msg ( & translate ! ( "clap-error-unexpected-argument-simple" ) ) ;
187177 }
188- callback ( ) ;
189- std:: process:: exit ( exit_code) ;
178+ exit_code
190179 }
191180
192- /// Handle invalid value errors with callback
193- fn handle_invalid_value_with_callback < F > ( & self , err : & Error , exit_code : i32 , callback : F ) -> !
194- where
195- F : FnOnce ( ) ,
196- {
181+ /// Handle invalid value errors
182+ fn handle_invalid_value ( & self , err : & Error , exit_code : i32 ) -> i32 {
197183 let invalid_arg = err. get ( ContextKind :: InvalidArg ) ;
198184 let invalid_value = err. get ( ContextKind :: InvalidValue ) ;
199185
@@ -245,32 +231,22 @@ impl<'a> ErrorFormatter<'a> {
245231 eprintln ! ( ) ;
246232 eprintln ! ( "{}" , translate!( "common-help-suggestion" ) ) ;
247233 } else {
248- self . print_simple_error ( & err. render ( ) . to_string ( ) , exit_code ) ;
234+ self . print_simple_error_msg ( & err. render ( ) . to_string ( ) ) ;
249235 }
250236
251237 // InvalidValue errors traditionally use exit code 1 for backward compatibility
252238 // But if a utility explicitly requests a high exit code (>= 125), respect it
253239 // This allows utilities like runcon (125) to override the default while preserving
254240 // the standard behavior for utilities using normal error codes (1, 2, etc.)
255- let actual_exit_code = if matches ! ( err. kind( ) , ErrorKind :: InvalidValue ) && exit_code < 125 {
241+ if matches ! ( err. kind( ) , ErrorKind :: InvalidValue ) && exit_code < 125 {
256242 1 // Force exit code 1 for InvalidValue unless using special exit codes
257243 } else {
258244 exit_code // Respect the requested exit code for special cases
259- } ;
260- callback ( ) ;
261- std:: process:: exit ( actual_exit_code) ;
245+ }
262246 }
263247
264- /// Handle missing required argument errors with callback
265- fn handle_missing_required_with_callback < F > (
266- & self ,
267- err : & Error ,
268- exit_code : i32 ,
269- callback : F ,
270- ) -> !
271- where
272- F : FnOnce ( ) ,
273- {
248+ /// Handle missing required argument errors
249+ fn handle_missing_required ( & self , err : & Error , exit_code : i32 ) -> i32 {
274250 let rendered_str = err. render ( ) . to_string ( ) ;
275251 let lines: Vec < & str > = rendered_str. lines ( ) . collect ( ) ;
276252
@@ -313,15 +289,11 @@ impl<'a> ErrorFormatter<'a> {
313289 }
314290 _ => eprint ! ( "{}" , err. render( ) ) ,
315291 }
316- callback ( ) ;
317- std:: process:: exit ( exit_code) ;
292+ exit_code
318293 }
319294
320- /// Handle generic errors with callback
321- fn handle_generic_error_with_callback < F > ( & self , err : & Error , exit_code : i32 , callback : F ) -> !
322- where
323- F : FnOnce ( ) ,
324- {
295+ /// Handle generic errors
296+ fn handle_generic_error ( & self , err : & Error , exit_code : i32 ) -> i32 {
325297 let rendered_str = err. render ( ) . to_string ( ) ;
326298 if let Some ( main_error_line) = rendered_str. lines ( ) . next ( ) {
327299 self . print_localized_error_line ( main_error_line) ;
@@ -330,27 +302,16 @@ impl<'a> ErrorFormatter<'a> {
330302 } else {
331303 eprint ! ( "{}" , err. render( ) ) ;
332304 }
333- callback ( ) ;
334- std:: process:: exit ( exit_code) ;
335- }
336-
337- /// Print a simple error message
338- fn print_simple_error ( & self , message : & str , exit_code : i32 ) -> ! {
339- self . print_simple_error_with_callback ( message, exit_code, || { } )
305+ exit_code
340306 }
341307
342- /// Print a simple error message with callback
343- fn print_simple_error_with_callback < F > ( & self , message : & str , exit_code : i32 , callback : F ) -> !
344- where
345- F : FnOnce ( ) ,
346- {
308+ /// Print a simple error message (no exit)
309+ fn print_simple_error_msg ( & self , message : & str ) {
347310 let error_word = translate ! ( "common-error" ) ;
348311 eprintln ! (
349312 "{}: {message}" ,
350313 self . color_mgr. colorize( & error_word, Color :: Red )
351314 ) ;
352- callback ( ) ;
353- std:: process:: exit ( exit_code) ;
354315 }
355316
356317 /// Print error line with localized "error:" prefix
@@ -478,7 +439,9 @@ where
478439 if e. exit_code ( ) == 0 {
479440 e. into ( ) // Preserve help/version
480441 } else {
481- handle_clap_error_with_exit_code ( e, exit_code)
442+ let formatter = ErrorFormatter :: new ( crate :: util_name ( ) ) ;
443+ let code = formatter. print_error ( & e, exit_code) ;
444+ USimpleError :: new ( code, "" )
482445 }
483446 } )
484447}
0 commit comments