### Run example applications Source: https://github.com/ksk001100/seahorse/blob/master/README.md Commands to clone the repository and execute the provided example applications. ```bash $ git clone https://github.com/ksk001100/seahorse $ cd seahorse $ cargo run --example single_app -- --help $ cargo run --example multiple_app -- --help ``` -------------------------------- ### Create a multiple command application Source: https://github.com/ksk001100/seahorse/blob/master/README.md An example demonstrating how to define multiple commands and actions within a single application. ```rust use seahorse::{App, Context, Command}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new(env!("CARGO_PKG_NAME")) .description(env!("CARGO_PKG_DESCRIPTION")) .author(env!("CARGO_PKG_AUTHORS")) .version(env!("CARGO_PKG_VERSION")) .usage("cli [name]") .action(default_action) .command(add_command()) .command(sub_command()); app.run(args); } fn default_action(c: &Context) { println!("Hello, {:?}", c.args); } fn add_action(c: &Context) { let sum: i32 = c.args.iter().map(|n| n.parse::().unwrap()).sum(); println!("{}", sum); } fn add_command() -> Command { Command::new("add") .description("add command") .alias("a") .usage("cli add(a) [nums...]") .action(add_action) } fn sub_action(c: &Context) { let sum: i32 = c.args.iter().map(|n| n.parse::().unwrap() * -1).sum(); println!("{}", sum); } fn sub_command() -> Command { Command::new("sub") .description("sub command") .alias("s") .usage("cli sub(s) [nums...]") .action(sub_action) } ``` -------------------------------- ### Execute multiple command application Source: https://github.com/ksk001100/seahorse/blob/master/README.md Example output from running the multiple command application. ```bash $ cli John Hello, ["John"] $ cli add 32 10 43 85 $ cli sub 12 23 89 -124 ``` -------------------------------- ### Execute CLI commands with flags Source: https://github.com/ksk001100/seahorse/blob/master/README.md Example command-line invocations for the branch processing application. ```bash $ cli John Hello, ["John"] $ cli John --bye Bye, ["John"] $ cli John --age 10 Hello, ["John"] ["John"] is 10 years old $ cli John -b -a=40 Bye, ["John"] ["John"] is 40 years old $ cli calc --operator add 1 2 3 4 5 15 $ cli calc -op sub 10 6 3 2 -21 ``` -------------------------------- ### Execute CLI commands with error handling Source: https://github.com/ksk001100/seahorse/blob/master/README.md Example command-line invocations demonstrating successful and error states. ```bash $ cli OK $ cli --error ERROR... $ cli -e ERROR... ``` -------------------------------- ### Initialize a CLI Application with App::new Source: https://context7.com/ksk001100/seahorse/llms.txt Configures a basic CLI application with metadata, a default action, and a boolean flag. ```rust use seahorse::{App, Context, Flag, FlagType}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new("myapp") .author("Author Name ") .description("A sample CLI application") .usage("myapp [options] [args]") .version("1.0.0") .action(|c: &Context| { println!("Arguments: {:?}", c.args); }) .flag( Flag::new("verbose", FlagType::Bool) .description("Enable verbose output") .alias("v"), ); app.run(args); } ``` -------------------------------- ### Build and run the basic CLI Source: https://github.com/ksk001100/seahorse/blob/master/README.md Commands to compile and execute the basic CLI application. ```bash $ cargo build --release $ ./target/release/cli --help $ ./target/release/cli John ``` -------------------------------- ### Initialize a new project Source: https://github.com/ksk001100/seahorse/blob/master/README.md Commands to create a new cargo project and add the seahorse dependency. ```bash $ cargo new cli $ cd cli $ echo 'seahorse = "*"' >> Cargo.toml ``` -------------------------------- ### Create a basic CLI application Source: https://github.com/ksk001100/seahorse/blob/master/README.md A simple implementation of a CLI application using the App struct. ```rust use seahorse::{App}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new(env!("CARGO_PKG_NAME")) .description(env!("CARGO_PKG_DESCRIPTION")) .author(env!("CARGO_PKG_AUTHORS")) .version(env!("CARGO_PKG_VERSION")) .usage("cli [args]") .action(|c| println!("Hello, {:?}", c.args)); app.run(args); } ``` -------------------------------- ### Define Subcommands with Command::new Source: https://context7.com/ksk001100/seahorse/llms.txt Creates complex applications by attaching multiple commands, each with unique flags and action handlers. ```rust use seahorse::{App, Command, Context, Flag, FlagType}; use std::env; fn main() { let args: Vec = env::args().collect(); let greet_command = Command::new("greet") .description("Greet a person") .usage("myapp greet [name] --formal") .alias("g") .action(greet_action) .flag( Flag::new("formal", FlagType::Bool) .description("Use formal greeting") .alias("f"), ); let add_command = Command::new("add") .description("Add numbers together") .usage("myapp add [numbers...]") .alias("a") .action(|c: &Context| { let sum: i32 = c.args.iter() .map(|n| n.parse::().unwrap_or(0)) .sum(); println!("Sum: {}", sum); }); let app = App::new("myapp") .description("Multi-command application") .usage("myapp [command] [args]") .command(greet_command) .command(add_command); app.run(args); } fn greet_action(c: &Context) { let name = c.args.first().map(|s| s.as_str()).unwrap_or("World"); if c.bool_flag("formal") { println!("Good day, {}.", name); } else { println!("Hello, {}!", name); } } ``` -------------------------------- ### Implement top-level error handling in Rust Source: https://github.com/ksk001100/seahorse/blob/master/README.md Demonstrates using action_with_result to return custom errors from a CLI command. ```rust use seahorse::{App, Context, Flag, FlagType}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new(env!("CARGO_PKG_NAME")) .author(env!("CARGO_PKG_AUTHORS")) .description(env!("CARGO_PKG_DESCRIPTION")) .usage("multiple_app [command] [arg]") .version(env!("CARGO_PKG_VERSION")) .action_with_result(|c: &Context| { if c.bool_flag("error") { Err(Box::new(Error)) } else { Ok(()) } }) .flag( Flag::new("error", FlagType::Bool) .description("error flag") .alias("e"), ); match app.run_with_result(args) { Ok(_) => println!("OK"), Err(e) => println!("{}", e), }; } #[derive(Debug, Clone)] struct Error; impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ERROR...") } } impl std::error::Error for Error {} ``` -------------------------------- ### Build Hierarchical Subcommands Source: https://context7.com/ksk001100/seahorse/llms.txt Define nested command structures by passing Command instances into the command() method of an App or another Command. ```rust use seahorse::{App, Command, Context, Flag, FlagType}; use std::env; fn main() { let args: Vec = env::args().collect(); // Define nested subcommands for 'db' command let db_migrate = Command::new("migrate") .description("Run database migrations") .usage("myapp db migrate [--version N]") .alias("m") .action(|c: &Context| { match c.int_flag("version") { Ok(v) => println!("Migrating to version {}", v), Err(_) => println!("Migrating to latest version"), } }) .flag( Flag::new("version", FlagType::Int) .description("Target migration version") .alias("v"), ); let db_seed = Command::new("seed") .description("Seed the database") .usage("myapp db seed") .alias("s") .action(|_| println!("Seeding database...")); let db_command = Command::new("db") .description("Database operations") .usage("myapp db [command]") .alias("database") .action(|c: &Context| { println!("DB command args: {:?}", c.args); c.help(); }) .command(db_migrate) .command(db_seed); let app = App::new("myapp") .description("Application with nested commands") .usage("myapp [command] [subcommand] [args]") .version("1.0.0") .command(db_command); app.run(args); } ``` -------------------------------- ### Implement branch processing with flags and subcommands in Rust Source: https://github.com/ksk001100/seahorse/blob/master/README.md Defines an application with boolean and integer flags, and a subcommand that performs arithmetic operations based on a string flag. ```rust use seahorse::{App, Command, Context, Flag, FlagType, error::FlagError}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new(env!("CARGO_PKG_NAME")) .description(env!("CARGO_PKG_DESCRIPTION")) .author(env!("CARGO_PKG_AUTHORS")) .version(env!("CARGO_PKG_VERSION")) .usage("cli [name]") .action(default_action) .flag( Flag::new("bye", FlagType::Bool) .description("Bye flag") .alias("b"), ) .flag( Flag::new("age", FlagType::Int) .description("Age flag") .alias("a"), ) .command(calc_command()); app.run(args); } fn default_action(c: &Context) { if c.bool_flag("bye") { println!("Bye, {:?}", c.args); } else { println!("Hello, {:?}", c.args); } if let Ok(age) = c.int_flag("age") { println!("{:?} is {} years old", c.args, age); } } fn calc_action(c: &Context) { match c.string_flag("operator") { Ok(op) => { let sum: i32 = match &*op { "add" => c.args.iter().map(|n| n.parse::().unwrap()).sum(), "sub" => c.args.iter().map(|n| n.parse::().unwrap() * -1).sum(), _ => panic!("undefined operator..."), }; println!("{}", sum); } Err(e) => match e { FlagError::Undefined => panic!("undefined operator..."), FlagError::ArgumentError => panic!("argument error..."), FlagError::NotFound => panic!("not found flag..."), FlagError::ValueTypeError => panic!("value type mismatch..."), FlagError::TypeError => panic!("flag type mismatch..."), }, } } fn calc_command() -> Command { Command::new("calc") .description("calc command") .alias("cl, c") .usage("cli calc(cl, c) [nums...]") .action(calc_action) .flag( Flag::new("operator", FlagType::String) .description("Operator flag(ex. cli calc --operator add 1 2 3)") .alias("op"), ) } ``` -------------------------------- ### Add dependency to Cargo.toml Source: https://github.com/ksk001100/seahorse/blob/master/README.md Include the seahorse crate in your project's dependencies. ```toml [dependencies] seahorse = "2.2" ``` -------------------------------- ### Top-level Error Handling with action_with_result Source: https://context7.com/ksk001100/seahorse/llms.txt Use `action_with_result` to return a `Result` and manage errors at the application's top level using `run_with_result`. This approach centralizes error reporting and exit code management. ```rust use seahorse::{App, Context, Flag, FlagType}; use std::env; use std::fmt; use std::error::Error; fn main() { let args: Vec = env::args().collect(); let app = App::new("safe_app") .description("Application with error handling") .usage("safe_app [options]") .action_with_result(safe_action) .flag( Flag::new("fail", FlagType::Bool) .description("Simulate a failure") .alias("f"), ) .flag( Flag::new("code", FlagType::Int) .description("Error code to return") .alias("c"), ); // Handle the result at the top level match app.run_with_result(args) { Ok(_) => { println!("Operation completed successfully"); std::process::exit(0); } Err(e) => { eprintln!("Error: {}", e); std::process::exit(1); } } } fn safe_action(c: &Context) -> Result<(), Box> { if c.bool_flag("fail") { let code = c.int_flag("code").unwrap_or(1); return Err(Box::new(AppError::new(code, "Operation failed"))); } println!("Processing: {:?}", c.args); Ok(()) } #[derive(Debug)] struct AppError { code: isize, message: String, } impl AppError { fn new(code: isize, message: &str) -> Self { Self { code, message: message.to_string() } } } impl fmt::Display for AppError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[Error {}] {}", self.code, self.message) } } impl Error for AppError {} ``` -------------------------------- ### Define Typed Command-Line Flags with Seahorse Source: https://context7.com/ksk001100/seahorse/llms.txt Use `Flag::new` to define flags with specific types (Bool, String, Int, Uint, Float). Flags support descriptions and aliases for shorter input. The `action` closure receives a `Context` to access parsed values. ```rust use seahorse::{App, Context, Flag, FlagType}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new("config") .description("Application with various flag types") .usage("config [options]") .action(action) .flag( Flag::new("debug", FlagType::Bool) .description("Enable debug mode") .alias("d"), ) .flag( Flag::new("output", FlagType::String) .description("Output file path") .alias("o"), ) .flag( Flag::new("count", FlagType::Int) .description("Number of iterations") .alias("c"), ) .flag( Flag::new("threshold", FlagType::Float) .description("Threshold value") .alias("t"), ) .flag( Flag::new("port", FlagType::Uint) .description("Port number") .alias("p"), ); app.run(args); } fn action(c: &Context) { println!("Debug: {}", c.bool_flag("debug")); match c.string_flag("output") { Ok(path) => println!("Output: {}", path), Err(_) => println!("Output: (not specified)"), } match c.int_flag("count") { Ok(n) => println!("Count: {}", n), Err(_) => println!("Count: (not specified)"), } match c.float_flag("threshold") { Ok(t) => println!("Threshold: {}", t), Err(_) => println!("Threshold: (not specified)"), } match c.uint_flag("port") { Ok(p) => println!("Port: {}", p), Err(_) => println!("Port: (not specified)"), } } // Usage: // $ config --debug -o output.txt --count 5 -t 0.75 --port 8080 // Debug: true // Output: output.txt // Count: 5 // Threshold: 0.75 // Port: 8080 // // $ config -d --count=-10 // Debug: true // Output: (not specified) // Count: -10 // Threshold: (not specified) // Port: (not specified) ``` -------------------------------- ### Access Parsed Arguments and Flags via Context Source: https://context7.com/ksk001100/seahorse/llms.txt The `Context` struct provides access to positional arguments (after flags are removed) and methods like `bool_flag`, `string_flag`, `int_flag`, `uint_flag`, and `float_flag` to retrieve flag values. Bool flags return `false` if not provided, while others return a `Result`. ```rust use seahorse::{App, Context, Flag, FlagType, error::FlagError}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new("processor") .usage("processor [files...] [options]") .action(process_action) .flag( Flag::new("recursive", FlagType::Bool) .description("Process recursively") .alias("r"), ) .flag( Flag::new("depth", FlagType::Int) .description("Maximum depth") .alias("d"), ) .flag( Flag::new("pattern", FlagType::String) .description("File pattern to match") .alias("p"), ); app.run(args); } fn process_action(c: &Context) { // Access positional arguments (flags are automatically removed) println!("Files to process: {:?}", c.args); // Bool flags return false if not provided let recursive = c.bool_flag("recursive"); println!("Recursive: {}", recursive); // Other flag types return Result with FlagError match c.int_flag("depth") { Ok(depth) => println!("Max depth: {}", depth), Err(FlagError::NotFound) => println!("Using default depth"), Err(FlagError::ValueTypeError) => println!("Invalid depth value"), Err(e) => println!("Error: {:?}", e), } match c.string_flag("pattern") { Ok(pattern) => println!("Pattern: {}", pattern), Err(FlagError::NotFound) => println!("No pattern specified"), Err(e) => println!("Error: {:?}", e), } // Display help programmatically if c.args.is_empty() && !recursive { c.help(); } } // Usage: // $ processor file1.txt file2.txt -r --depth 3 -p "*.rs" // Files to process: ["file1.txt", "file2.txt"] // Recursive: true // Max depth: 3 // Pattern: *.rs ``` -------------------------------- ### Handle Multiple Flag Occurrences Source: https://context7.com/ksk001100/seahorse/llms.txt Use the multiple() method on a Flag to allow repeated inputs, then retrieve values using *_flag_vec methods. ```rust use seahorse::{App, Context, Flag, FlagType}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new("request") .description("HTTP request builder") .usage("request [url] [options]") .action(action) .flag( Flag::new("header", FlagType::String) .description("Add HTTP header (can be repeated)") .alias("H") .multiple(), ) .flag( Flag::new("verbose", FlagType::Bool) .description("Increase verbosity (repeat for more)") .alias("v") .multiple(), ) .flag( Flag::new("retry", FlagType::Uint) .description("Retry counts for different endpoints") .alias("r") .multiple(), ); app.run(args); } fn action(c: &Context) { let url = c.args.first().map(|s| s.as_str()).unwrap_or("http://localhost"); println!("URL: {}", url); // Count verbosity level by number of -v flags let verbosity = c.bool_flag_vec("verbose").iter().flatten().count(); println!("Verbosity level: {}", verbosity); // Get all header values println!("Headers:"); for header in c.string_flag_vec("header") { match header { Ok(h) => println!(" {}", h), Err(e) => println!(" Error: {:?}", e), } } // Get all retry values println!("Retry counts:"); for retry in c.uint_flag_vec("retry") { match retry { Ok(r) => println!(" {}", r), Err(e) => println!(" Error: {:?}", e), } } } ``` -------------------------------- ### Handling Flag Parsing Errors with FlagError Source: https://context7.com/ksk001100/seahorse/llms.txt The `FlagError` enum provides detailed error information for flag parsing issues. Handle specific errors like NotFound, TypeError, and ArgumentError to provide user-friendly feedback. ```rust use seahorse::{App, Context, Flag, FlagType, error::FlagError}; use std::env; fn main() { let args: Vec = env::args().collect(); let app = App::new("validator") .description("Demonstrates flag error handling") .usage("validator [options]") .action(validate_action) .flag(Flag::new("count", FlagType::Int).alias("c")) .flag(Flag::new("ratio", FlagType::Float).alias("r")) .flag(Flag::new("name", FlagType::String).alias("n")); app.run(args); } fn validate_action(c: &Context) { // Handle each type of error appropriately match c.int_flag("count") { Ok(count) => println!("Count: {}", count), Err(FlagError::NotFound) => { println!("Count flag was not provided, using default: 1"); } Err(FlagError::ValueTypeError) => { eprintln!("Error: --count requires a valid integer"); } Err(FlagError::ArgumentError) => { eprintln!("Error: --count requires a value"); } Err(e) => eprintln!("Unexpected error: {:?}", e), } match c.float_flag("ratio") { Ok(ratio) if ratio >= 0.0 && ratio <= 1.0 => { println!("Ratio: {:.2}", ratio); } Ok(ratio) => { eprintln!("Warning: ratio {} is outside expected range [0, 1]", ratio); } Err(FlagError::NotFound) => { println!("Ratio not specified, using default: 0.5"); } Err(FlagError::ValueTypeError) => { eprintln!("Error: --ratio requires a valid decimal number"); } Err(e) => eprintln!("Error with ratio: {:?}", e), } // Check for undefined flags (not registered) match c.string_flag("undefined_flag") { Err(FlagError::Undefined) => { println!("Note: 'undefined_flag' is not a registered flag"); } _ => {} } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.