Skip to content

feat(macros): allow default values for #ok arguments in sarge macros#14

Merged
Kyllingene merged 4 commits intoKyllingene:masterfrom
YuniqueUnic:master
Dec 14, 2025
Merged

feat(macros): allow default values for #ok arguments in sarge macros#14
Kyllingene merged 4 commits intoKyllingene:masterfrom
YuniqueUnic:master

Conversation

@YuniqueUnic
Copy link
Contributor

@YuniqueUnic YuniqueUnic commented Dec 13, 2025

Previously, default values were disallowed for #ok arguments with a compile error. This change enables support for optional defaults on #ok arguments by accepting an Option<T> as the default value. The default is used when the argument is missing or fails to parse, since #ok treats parsing failures as if the argument was not provided.

Additionally, this commit fixes a potential name pollution issue where importing anyhow::Ok could interfere with the macro expansion. A test case has been added to verify that the macro works correctly even when Ok is shadowed.

The documentation in __var_tag! has been updated to reflect the new behavior and provide guidance on how to use defaults with #ok and #err arguments.


I think the default value for Option is necessary that I reopen it by this pr.


sarge! {
    #[derive(Debug, PartialEq, Eq)]
    DefaultArgs,

    // Default value (String).
    socket_addr: String = "127.0.0.1:9912",

    // `#ok` default is a plain value; macro wraps it in `Some(...)`.
    #ok 't' target_addr: String = "127.0.0.1:9911",

    // `#ok` default should be used when parsing fails.
    #ok 'n' num: u32 = 42,

    // `#err` default is a plain value (not `Some(Ok(...))`).
    #err 'h' help: bool = false,
}

Previously, default values were disallowed for `#ok` arguments with a compile error.
This change enables support for optional defaults on `#ok` arguments by accepting
an `Option<T>` as the default value. The default is used when the argument is
missing or fails to parse, since `#ok` treats parsing failures as if the argument
was not provided.

Additionally, this commit fixes a potential name pollution issue where importing
`anyhow::Ok` could interfere with the macro expansion. A test case has been added
to verify that the macro works correctly even when `Ok` is shadowed.

The documentation in `__var_tag!` has been updated to reflect the new behavior
and provide guidance on how to use defaults with `#ok` and `#err` arguments.
@YuniqueUnic
Copy link
Contributor Author

YuniqueUnic commented Dec 13, 2025

I will post a new help() function later, So this pr should be kept before the new commit pushed please.

Currently, the print_help() could not meet some situation that dev like to modify the help content, So the help() function will return help content back only to avoid print directly.

Thanks.

- Change `print_help` to `help` which returns a String
- Add new `print_help` method that prints the result of `help`
- Update documentation comments to reflect new behavior
- Add test case for `help` method returning correct content

This change allows users to capture the help output as a string for further processing,
while maintaining the previous printing behavior through the new `print_help` wrapper.
@YuniqueUnic
Copy link
Contributor Author

feat(help): return help message as string instead of printing directly

  • Change print_help to help which returns a String
  • Add new print_help method that prints the result of help
  • Update documentation comments to reflect new behavior
  • Add test case for help method returning correct content

This change allows users to capture the help output as a string for further processing,
while maintaining the previous printing behavior through the new print_help wrapper.

a5af6a1 help() commit

- Add internal `__SargeDefault` trait and helper function to support
  automatic conversion of literal defaults to their target types
- Update `__parse_arg!` macro to accept type information and handle
  default values more consistently across `err`, `ok`, and unwrapped cases
- Simplify user-facing syntax: `#ok` defaults now accept plain values
  instead of requiring explicit `Some(...)` wrapping
- Adjust generated code to use new default conversion mechanism,
  reducing boilerplate needed from callers
- Update documentation and tests to reflect simplified default usage
@YuniqueUnic
Copy link
Contributor Author

refactor(macros): improve default value handling in argument parsing

  • Add internal __SargeDefault trait and helper function to support
    automatic conversion of literal defaults to their target types
  • Update __parse_arg! macro to accept type information and handle
    default values more consistently across err, ok, and unwrapped cases
  • Simplify user-facing syntax: #ok defaults now accept plain values
    instead of requiring explicit Some(...) wrapping
  • Adjust generated code to use new default conversion mechanism,
    reducing boilerplate needed from callers
  • Update documentation and tests to reflect simplified default usage

@Kyllingene
Copy link
Owner

I'll have to review this tonight, but the changes all look good.

I can't complain too much since I'm not very tidy myself, but usually it's good etiquette to split separate changes into different PRs. I'll still probably accept this though.

@YuniqueUnic
Copy link
Contributor Author

You're right, it's a good practice to separate different changes into different PRs. However, the reason I didn't do that this time is that I felt the changes were all quite minor, so I combined them into a single PR.

@Kyllingene
Copy link
Owner

If you use a default value for #ok, can that argument ever be None? If not, then it may as well not be an Option anymore. At that point, the only difference between placing a default on an #ok argument and a plain argument, is that the former silently ignores parsing errors. Is that something we want to support? If so, we need to figure out how to better document that, since it's not immediately obvious that #ok + default leads to ignoring errors.

- Update macro logic to distinguish between missing arguments and parse failures for `#ok`
- Apply defaults only when the argument is missing, not on parse errors
- Parse errors now consistently result in `None` for `#ok` arguments
- Add clarifying documentation and tests for `#ok` behavior with defaults

The previous implementation incorrectly applied defaults on parse errors, which was inconsistent with the intended behavior. This change ensures that defaults are only used when an argument is absent, while maintaining `None` for parse failures.
@YuniqueUnic
Copy link
Contributor Author

If you use a default value for #ok, can that argument ever be None? If not, then it may as well not be an Option anymore. At that point, the only difference between placing a default on an #ok argument and a plain argument, is that the former silently ignores parsing errors. Is that something we want to support? If so, we need to figure out how to better document that, since it's not immediately obvious that #ok + default leads to ignoring errors.


Updated

fix(macros): improve #ok argument handling with defaults

Update macro logic to distinguish between missing arguments and parse failures for #ok
Apply defaults only when the argument is missing, not on parse errors
Parse errors now consistently result in None for #ok arguments
Add clarifying documentation and tests for #ok behavior with defaults

The previous implementation incorrectly applied defaults on parse errors, which was inconsistent with the intended behavior. This change ensures that defaults are only used when an argument is absent, while maintaining None for parse failures.

@Kyllingene Kyllingene merged commit a20fafe into Kyllingene:master Dec 14, 2025
1 check passed
@Kyllingene
Copy link
Owner

The question now is, could these changes cause SemVer hazards? I don't believe the added defaults could, but it's perhaps possible that __SargeDefault could break inference in some edge cases. I'll have to investigate further before publishing on crates.io.

However, thanks again for the contributions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants