clap_fmt 0.1.1

Serialize a clap arg parser into the command-line arguments.
Documentation
use clap::Parser;
use clap_fmt::FmtArgs as _;
use serde::Serialize;

#[derive(Parser, Debug, Serialize)]
#[command(name = "compiler")]
#[command(about = "An advanced compiler CLI example", long_about = None)]
struct Cli {
    /// Verbosity level (can be repeated)
    #[arg(short = 'v', long, action = clap::ArgAction::Count)]
    verbose: u8,

    /// Suppress output
    #[arg(short, long)]
    quiet: bool,

    /// Number of parallel jobs
    #[arg(short = 'j', long)]
    jobs: Option<usize>,

    /// Optimization level
    #[arg(short = 'O', long)]
    optimization: Option<String>,

    /// Include paths (can be repeated)
    #[arg(short = 'I', long = "include", action = clap::ArgAction::Append)]
    include_paths: Vec<String>,

    /// Library paths (can be repeated)
    #[arg(short = 'L', long = "library", action = clap::ArgAction::Append)]
    library_paths: Vec<String>,

    /// Preprocessor defines (can be repeated)
    #[arg(short = 'D', long = "define", action = clap::ArgAction::Append)]
    defines: Vec<String>,

    /// Enable release mode
    #[arg(long)]
    release: bool,

    /// Target triple
    #[arg(long)]
    target: Option<String>,

    /// Source files to compile
    #[arg(value_name = "FILES")]
    files: Vec<String>,
}

fn main() {
    println!("=== Advanced Compiler CLI Example ===\n");
    println!("This demonstrates automatic conversion with complex argument types.\n");

    // Example 1: Debug build with verbose output
    let debug_build = Cli {
        verbose: 2,
        quiet: false,
        jobs: Some(4),
        optimization: Some("0".to_string()),
        include_paths: vec!["./include".to_string(), "/usr/local/include".to_string()],
        library_paths: vec![],
        defines: vec!["DEBUG".to_string()],
        release: false,
        target: None,
        files: vec!["main.c".to_string(), "utils.c".to_string()],
    };

    println!("Debug Build:");
    println!("  Args: {:?}", debug_build.to_args());

    // Example 2: Release build with optimizations
    let release_build = Cli {
        verbose: 0,
        quiet: true,
        jobs: Some(8),
        optimization: Some("3".to_string()),
        include_paths: vec!["/usr/include".to_string()],
        library_paths: vec!["/usr/lib".to_string(), "/usr/local/lib".to_string()],
        defines: vec!["NDEBUG".to_string(), "RELEASE".to_string()],
        release: true,
        target: Some("x86_64-unknown-linux-gnu".to_string()),
        files: vec!["src/main.c".to_string(), "src/lib.c".to_string()],
    };

    println!("Release Build:");
    println!("  Args: {:?}", release_build.to_args());

    // Example 3: Cross-compilation
    let cross_compile = Cli {
        verbose: 3,
        quiet: false,
        jobs: None,
        optimization: Some("2".to_string()),
        include_paths: vec!["./include".to_string()],
        library_paths: vec![],
        defines: vec!["EMBEDDED".to_string(), "NO_STD".to_string()],
        release: true,
        target: Some("thumbv7em-none-eabihf".to_string()),
        files: vec!["embedded.c".to_string()],
    };

    println!("Cross-compilation:");
    println!("  Args: {:?}", cross_compile.to_args());

    println!("Notice how the library:");
    println!("- Automatically handles count flags (-vv, -vvv)");
    println!("- Skips default values");
    println!("- Handles repeated options (--include, --define)");
    println!("- Works with positional arguments");
    println!("- All WITHOUT any manual implementation!");
}