⌨️ 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
- Flags (boolean options): --verbose, -v
- Options (key-value): --output=file.txt
- Positional arguments: <input> <output>
- Subcommands: git commit, git push
- Automatic --help and --version
- Default values & environment variables
- Value validation & allowed values
- Error handling with clear messages
🚀 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
sys- Command-line argumentsterminal- Colored outputstring- String parsing