⌨️ cli

Command-Line Argument Parser - Rust clap-Inspired

~300 lines ~25 function Auto-Help

📖 Overview

CLI modülü, Rust'ın clap kütüphanesinden esinlenerek geliştirilmiş modern komut satırı argument parser'ıdır. Otomatik help generation, subcommands, validation and type-safe parsing sağlar.

🔑 Key Features

🚀 Quick Start

import cli

function main(args: Vector[str]) do
    // CLI create
    let app = cli.new("myapp", "1.0.0", "My awesome application")
    
    // Arguments define
    app.add_flag("verbose", 'v', "Enable verbose output")
    app.add_option("output", 'o', "Output file", default: "out.txt")
    app.add_positional("input", "Input file", required: true)
    
    // Parse et (otomatik --help exitı)
    let parsed = app.parse(args)?
    
    // Değerleri use
    if parsed.get_flag("verbose")  do
        io.println("Verbose mode enabled")
    end
    
    let input = parsed.get_positional(0)
    let output = parsed.get_option("output")
    io.println("Processing {} -> {}", input, output)
end

💡 Example 1: File Converter

import cli, fs

function main(args: Vector[str]) do
    let app = cli.new("converter", "1.0.0", "File format converter")
    
    // Flags
    app.add_flag("overwrite", 'f', "Force overwrite existing files")
    app.add_flag("verbose", 'v', "Verbose output")
    app.add_flag("quiet", 'q', "Suppress output")
    
    // Options with validation
    app.add_option("format", 't', "Target format", do
        default: "json",
        allowed_values: ["json", "xml", "yaml", "toml"]
    end)
    
    app.add_option("output", 'o', "Output directory", do
        default: ".",
        env: "OUTPUT_DIR"  // Env variable fallback
    end)
    
    // Positional
    app.add_positional("files", "Input files", do
        required: true,
        multiple: true  // Accept multiple files
    end)
    
    let parsed = app.parse(args)?
    
    // Get values
    let format = parsed.get_option("format")
    let output_dir = parsed.get_option("output")
    let files = parsed.get_positional_all("files")
    let verbose = parsed.get_flag("verbose")
    let overwrite = parsed.get_flag("overwrite")
    
    // Process files
    each file in files for do
        if verbose  do
            io.println("Converting {} to {}...", file, format)
        end
        
        let output_path = "{}/{}.{}".formatla(output_dir, 
            fs.stem(file), format)
        
        if fs.exists(output_path) and overwrite else do
            io.eprintln("Error: {} exists (use -f to overwrite)", output_path)
            continue
        end
        
        // Convert file...
        convert_file(file, output_path, format)?
        
        if verbose else and parsed.get_flag("quiet") else do
            io.println("✓ {}", output_path)
        end
    end
end

// Output:
// $ converter --help
// converter 1.0.0
// File format converter
// 
// USAGE:
//     converter [OPTIONS] <files>...
// 
// OPTIONS:
//     -t, --format <value>     Target format [default: json] [possible: json, xml, yaml, toml]
//     -o, --output <value>     Output directory [default: .] [env: OUTPUT_DIR]
//     -f, --overwrite          Force overwrite existing files
//     -v, --verbose            Verbose output
//     -q, --quiet              Suppress output
//     -h, --help               Print help
//     -V, --version            Print version

💡 Example 2: Git-Style Subcommands

import cli

function main(args: Vector[str]) do
    let app = cli.new("git-like", "1.0.0", "Git-style CLI tool")
    
    // Global flags
    app.add_flag("verbose", 'v', "Verbose output")
    
    // Subcommands
    let commit = app.add_subcommand("commit", "Record changes")
    commit.add_option("message", 'm', "Commit message", required: true)
    commit.add_flag("amend", 'a', "Amend previous commit")
    commit.add_flag("all", 'A', "Stage all changes")
    
    let push = app.add_subcommand("push", "Push to remote")
    push.add_option("remote", 'r', "Remote name", default: "origin")
    push.add_option("branch", 'b', "Branch name")
    push.add_flag("force", 'f', "Force push")
    
    let log = app.add_subcommand("log", "Show commit history")
    log.add_option("limit", 'n', "Number of commits", default: "10")
    log.add_flag("oneline", None, "One commit per line")
    
    // Parse
    let parsed = app.parse(args)?
    
    // Handle subcommands
    match parsed.subcommand() do
        Some("commit") => do
            let msg = parsed.get_option("message")
            let amend = parsed.get_flag("amend")
            let all = parsed.get_flag("all")
            
            if all  do
                io.println("Staging all changes...")
            end
            
            if amend  do
                io.println("Amending commit: {}", msg)
            else do
                io.println("Creating commit: {}", msg)
            end
        end,
        
        Some("push") => do
            let remote = parsed.get_option("remote")
            let branch = parsed.get_option_or("branch", "main")
            let force = parsed.get_flag("force")
            
            if force  do
                io.println("Force pushing to {}/{}", remote, branch)
            else do
                io.println("Pushing to {}/{}", remote, branch)
            end
        end,
        
        Some("log") => do
            let limit = parsed.get_option("limit").parse_int()?
            let oneline = parsed.get_flag("oneline")
            
            io.println("Showing last {} commits:", limit)
            // Show log...
        end,
        
        None => do
            io.eprintln("No subcommand provided. Use --help for usage.")
            sys.exit(1)
        end
    end
end

⚙️ Argument Types

// Flag (boolean)
app.add_flag(name: str, short: char, help: str)

// Option (string value)
app.add_option(name: str, short: char, help: str, config: OptionConfig)

struct OptionConfig do
    default: Optional[str],
    required: bool,
    env: Optional[str],
    allowed_values: Optional[Vector[str]]
end

// Positional (required arguments)
app.add_positional(name: str, help: str, config: PositionalConfig)

struct PositionalConfig do
    required: bool,
    multiple: bool  // Accept multiple values
end

🔗 Related Modules

← All Modules