### Basic Shell with Custom Commands Source: https://gitlab.com/john_t/shellfish/-/blob/master/README.md This example demonstrates how to create a basic interactive shell using Shellfish. It includes custom commands like 'greet', 'echo', 'count', and an asynchronous 'cat' command. The shell can also run non-interactively if command-line arguments are provided. ```rust use std::error::Error; use std::fmt; use async_std::prelude::*; use rustyline::DefaultEditor; use shellfish::{app, handler::DefaultAsyncHandler, Command, Shell}; #[macro_use] extern crate shellfish; #[async_std::main] async fn main() -> Result<(), Box> { // Define a shell let mut shell = Shell::new_with_async_handler( 0_u64, "<[Shellfish Example]>-$ ", DefaultAsyncHandler::default(), DefaultEditor::new()?, ); // Add some commands shell .commands .insert("greet", Command::new("greets you.".to_string(), greet)); shell .commands .insert("echo", Command::new("prints the input.".to_string(), echo)); shell.commands.insert( "count", Command::new("increments a counter.".to_string(), count), ); shell.commands.insert( "cat", Command::new_async( "Displays a plaintext file.".to_string(), async_fn!(u64, cat), ), ); // Check if we have > 2 args, if so no need for interactive shell let mut args = std::env::args(); if args.nth(1).is_some() { // Create the app from the shell. let mut app = app::App::try_from_async(shell)?; // Set the binary name app.handler.proj_name = Some("shellfish-example".to_string()); app.load_cache()?; // Run it app.run_args_async().await?; } else { // Run the shell shell.run_async().await?; } Ok(()) } /// Greets the user fn greet(_state: &mut u64, args: Vec) -> Result<(), Box> { let arg = args.get(1).ok_or_else(|| Box::new(GreetingError))?; println!("Greetings {}, my good friend.", arg); Ok(()) } /// Echos the input fn echo(_state: &mut u64, args: Vec) -> Result<(), Box> { let mut args = args.iter(); args.next(); for arg in args { print!("{} ", arg); } println!(); Ok(()) } /// Acts as a counter fn count(state: &mut u64, _args: Vec) -> Result<(), Box> { *state += 1; println!("You have used this counter {} times", state); Ok(()) } /// Asynchronously reads a file async fn cat( _state: &mut u64, args: Vec, ) -> Result<(), Box> { use async_std::fs; if let Some(file) = args.get(1) { let mut contents = String::new(); let mut file = fs::File::open(file).await?; file.read_to_string(&mut contents).await?; println!("{}", contents); } Ok(()) } /// Greeting error #[derive(Debug)] pub struct GreetingError; impl fmt::Display for GreetingError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "No name specified") } } impl Error for GreetingError {} ``` -------------------------------- ### Clap Command Integration in Shellfish Source: https://gitlab.com/john_t/shellfish/-/blob/master/README.md This Rust code demonstrates how to integrate Clap for command-line argument parsing within a Shellfish interactive shell. It defines a 'greet' command with arguments parsed by Clap. ```rust use async_std::io::ReadExt; use clap::Parser; use shellfish::{ clap_command, handler::DefaultAsyncHandler, rustyline::DefaultEditor, Shell, }; use std::path::PathBuf; /// Simple command to greet a person /// /// This command will greet the person based of a multitide /// of option flags, see below. #[derive(Parser, Debug)] #[clap(author, version, about)] struct GreetArgs { /// Name of the person to greet name: String, /// Age of the person to greet #[clap(short, long)] age: Option, /// Whether to be formal or note #[clap(short, long)] formal: bool, } #[async_std::main] async fn main() -> Result<(), Box> { // Define a shell let mut shell = Shell::new_with_async_handler( (), "<[Shellfish Example]>-$ ", DefaultAsyncHandler::default(), DefaultEditor::new()?, ); shell .commands .insert("greet", clap_command!((), GreetArgs, greet)); shell.run_async().await?; Ok(()) } fn greet( _state: &mut (), args: GreetArgs, ) -> Result<(), Box> { if args.formal { match args.age { Some(age) => { println!("Good day {}, you are {} years old.", args.name, age) } None => println!("Good day {}.", args.name), } } else { match args.age { Some(age) => { println!("Hi {}, you're {} years old.", args.name, age) } None => println!("Hi {}!", args.name), } } Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.