@@ -28,6 +28,8 @@ pub const ParseOptions = struct {
2828 argument_prompt : ? []const u8 = null ,
2929 version_string : ? []const u8 = null ,
3030 print_help_and_exit : bool = true ,
31+ /// When true, print the help text to stderr before returning any parse error.
32+ print_help_on_error : bool = true ,
3133};
3234
3335/// Parses arguments according to the given structure.
@@ -784,14 +786,22 @@ fn OptionParser(
784786 options .version_string ,
785787 options .argument_prompt ,
786788 );
787- const parsed_options = try Self .parseCommand (
789+ const parsed_options = Self .parseCommand (
788790 Options ,
789791 arguments_to_parse ,
790792 & argument_index ,
791793 message_helper ,
792794 null ,
793795 options ,
794- );
796+ ) catch | err | {
797+ if (! is_test and options .print_help_on_error ) {
798+ var stderr_buffer : [4096 ]u8 = undefined ;
799+ var stderr_writer = std .fs .File .stderr ().writer (& stderr_buffer );
800+ message_helper .printHelp (Options , null , & stderr_writer .interface ) catch {};
801+ stderr_writer .interface .flush () catch {};
802+ }
803+ return err ;
804+ };
795805 var result = ParseResult (Options , options .version_string , options .argument_prompt ){
796806 .program_name = input_arguments [0 ],
797807 .allocator = self .allocator ,
@@ -1182,6 +1192,36 @@ test "parse/print_help_and_exit false" {
11821192 try std .testing .expectEqual (result .positional_arguments .len , 0 );
11831193}
11841194
1195+ test "parse/print_help_on_error" {
1196+ // Verify that parse errors are propagated correctly regardless of print_help_on_error.
1197+ // The actual stderr printing is guarded by !is_test, so only the error return is tested here.
1198+ const gpa = std .testing .allocator ;
1199+ var input_arguments = [_ ][:0 ]u8 {
1200+ try gpa .dupeZ (u8 , "awesome-cli" ),
1201+ try gpa .dupeZ (u8 , "--help" ),
1202+ };
1203+ defer for (input_arguments ) | argument | {
1204+ gpa .free (argument );
1205+ };
1206+
1207+ // With print_help_on_error: true (default), errors are still propagated.
1208+ {
1209+ var parser = OptionParser (TestArguments ).init (gpa );
1210+ try std .testing .expectError (
1211+ error .MissingRequiredOption ,
1212+ parser .parse (& input_arguments , .{ .print_help_on_error = true }),
1213+ );
1214+ }
1215+ // With print_help_on_error: false, errors are also propagated (no other change in test mode).
1216+ {
1217+ var parser = OptionParser (TestArguments ).init (gpa );
1218+ try std .testing .expectError (
1219+ error .MissingRequiredOption ,
1220+ parser .parse (& input_arguments , .{ .print_help_on_error = false }),
1221+ );
1222+ }
1223+ }
1224+
11851225test "parse/sub commands" {
11861226 const gpa = std .testing .allocator ;
11871227 var input_arguments = [_ ][:0 ]u8 {
0 commit comments