cmdkit-macros 0.2.1

Procedural macros for cmdkit command strategy generation.
Documentation
# cmdkit-macros

Procedural macros for generating `cmdkit` command strategies from plain Rust functions.

## What It Does

This crate provides one attribute macro:

- `#[strategy]`

It transforms a free function into a concrete type that implements `cmdkit::CommandStrategy`.

Given a function like `create_directory`, the macro generates:

- A strategy type named `CreateDirectory`
- A constructor `CreateDirectory::new()`
- A helper factory function `create_directory_strategy()`
- An `impl cmdkit::CommandStrategy` with `execute(...)`

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
cmdkit = "0.1"
cmdkit-macros = "0.1"
```

## Quick Example

```rust
use cmdkit::{Argument, CliCore, Command, StrategyError, Switch};
use cmdkit_macros::strategy;

#[strategy]
fn create_directory(
    _options: Vec<Switch>,
    arguments: Vec<Argument>,
    _subcommands: Vec<String>,
) -> Result<(), StrategyError> {
    let path = arguments
        .iter()
        .find(|argument| argument.name == "path")
        .and_then(|argument| argument.value.as_deref())
        .ok_or_else(|| StrategyError::invalid_arguments("missing path"))?;

    std::fs::create_dir(std::path::Path::new(path))
        .map_err(|e| StrategyError::execution(format!("Failed to create directory: {e}")))
}

fn main() {
    let core = CliCore::new();
    core.register(Command::new(
        "create",
        "Create a directory",
        CreateDirectory::new(),
    ));

    // You can also use create_directory_strategy()
    // generated by the macro.
}
```

## Required Function Signature

A function annotated with `#[strategy]` must:

1. Be a free function (not a method).
2. Not be `async`.
3. Accept exactly these three parameters in this order:
    - `options: Vec<Switch>`
    - `arguments: Vec<Argument>`
   - `subcommands: Vec<String>`
4. Return `Result<(), cmdkit::StrategyError>`.

Example accepted shape:

```rust
#[strategy]
fn my_command(
    options: Vec<cmdkit::Switch>,
    arguments: Vec<cmdkit::Argument>,
    subcommands: Vec<String>,
) -> Result<(), cmdkit::StrategyError> {
    let _ = (options, arguments, subcommands);
    Ok(())
}
```

## Naming Rules

The generated type name is UpperCamelCase from the function name.

- `simple_cli_strategy` -> `SimpleCliStrategy`
- `create_directory` -> `CreateDirectory`

## Macro Expansion Summary

For:

```rust
#[strategy]
fn sample_name(
    options: Vec<cmdkit::Switch>,
    arguments: Vec<cmdkit::Argument>,
    subcommands: Vec<String>,
) -> Result<(), cmdkit::StrategyError> {
    Ok(())
}
```

The macro generates equivalents of:

```rust
pub struct SampleName;

impl SampleName {
    pub fn new() -> Self {
        Self
    }
}

impl cmdkit::CommandStrategy for SampleName {
    fn execute(
        &self,
        options: Vec<cmdkit::Switch>,
        arguments: Vec<cmdkit::Argument>,
        subcommands: Vec<String>,
    ) -> Result<(), cmdkit::StrategyError> {
        let _ = (options, arguments, subcommands);
        Ok(())
    }
}

pub fn sample_name_strategy() -> SampleName {
    SampleName::new()
}
```

## Development

Run tests:

```bash
cargo test
```

## License

GPL-3.0-or-later