Skip to content

JackLanger/cmdkit-macros

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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:

[dependencies]
cmdkit = "0.3"
cmdkit-macros = "0.3"

Quick Example

use cmdkit::{CMDKit, Command, InvocationArgs, StrategyError};
use cmdkit_macros::strategy;

#[strategy]
fn create_directory(
    _ctx: cmdkit::ExecutionContext,
    invocation_args: cmdkit::InvocationArgs,
) -> Result<(), cmdkit::StrategyError> {
    let path = invocation_args.args
        .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 = CMDKit::builder()
        .register(Command::new(
            "create",
            "Create a directory",
            CreateDirectory::new(),
        ))
        .build();

    // You can also use create_directory_strategy()
    // generated by the macro.
    let _ = core;
}

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 two parameters in this order:
    • ctx: cmdkit::ExecutionContext (or &cmdkit::ExecutionContext)
    • args: cmdkit::InvocationArgs
  4. Return Result<(), cmdkit::StrategyError>.

Example accepted shape:

#[strategy]
fn my_command(
    _ctx: cmdkit::ExecutionContext,
    _args: cmdkit::InvocationArgs,
) -> Result<(), cmdkit::StrategyError> {
    Ok(())
}

Naming Rules

The generated type name is UpperCamelCase from the function name.

  • simple_cli_strategy -> SimpleCliStrategy
  • create_directory -> CreateDirectory

Macro Expansion Summary

For:

#[strategy]
fn sample_name(
    ctx: cmdkit::ExecutionContext,
    args: cmdkit::InvocationArgs,
) -> Result<(), cmdkit::StrategyError> {
    Ok(())
}

The macro generates equivalents of:

pub struct SampleName;

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

impl cmdkit::CommandStrategy for SampleName {
    fn execute(
        &self,
        ctx: &cmdkit::ExecutionContext,
        args: cmdkit::InvocationArgs,
    ) -> Result<(), cmdkit::StrategyError> {
        Ok(())
    }
}

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

Development

Run tests:

cargo test

License

This project is licensed under Apache-2.0. See LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages