Skip to main content

handler

Attribute Macro handler 

Source
#[handler]
Expand description

Transforms a pure function into a Standout-compatible handler.

This macro generates a wrapper function that extracts CLI arguments from ArgMatches and calls your pure function. The original function is preserved for direct testing.

§Parameter Annotations

AnnotationTypeDescription
#[flag]boolBoolean CLI flag
#[flag(name = "x")]boolFlag with custom CLI name
#[arg]TRequired CLI argument
#[arg]Option<T>Optional CLI argument
#[arg]Vec<T>Multiple CLI arguments
#[arg(name = "x")]TArgument with custom CLI name
#[ctx]&CommandContextAccess to command context
#[matches]&ArgMatchesRaw matches (escape hatch)

§Return Type Handling

Return TypeBehavior
Result<T, E>Passed through (dispatch auto-wraps in Output::Render)
Result<(), E>Wrapped in HandlerResult<()> with Output::Silent

§Generated Code

For a function fn foo(...), the macro generates fn foo__handler(...).

§Example

use standout_macros::handler;

// Pure function - easy to test
#[handler]
pub fn list(#[flag] all: bool, #[arg] limit: Option<usize>) -> Result<Vec<Item>, Error> {
    storage::list(all, limit)
}

// Generates:
// pub fn list__handler(m: &ArgMatches) -> Result<Vec<Item>, Error> {
//     let all = m.get_flag("all");
//     let limit = m.get_one::<usize>("limit").cloned();
//     list(all, limit)
// }

// Use with Dispatch derive:
#[derive(Subcommand, Dispatch)]
#[dispatch(handlers = handlers)]
enum Commands {
    #[dispatch(handler = list)]  // Uses list__handler
    List { ... },
}

§Testing

The original function is preserved, so you can test it directly:

#[test]
fn test_list() {
    let result = list(true, Some(10));
    assert!(result.is_ok());
}