clapcmd 0.1.1

A readline wrapper that allows for creating custom interactive shells, similar to python's cmd module
Documentation

ClapCmd

A library to quickly build full-featured REPLs supported by CLAP and readline (provided via rustyline)

Features

  • Full readline support that exposes all customization for rustyline
    • emacs-style keyboard shortcuts
    • command history
  • Full integration with clap builders allowing for full-featured commands
  • Tab completion for:
    • commands and (TODO) command aliases
    • arguments
    • subcommands
    • values supplied via value_parsers (i.e. a list of valid values)
    • value hints (e.g. ValueHint::FilePath)
    • TODO: callback and/or demo for how to query value_parsers at runtime
  • Callback style approach with provided state
  • Customizable prompts that can be updated at anytime during execution
  • Support for writing to stdout outside of the command loop without mangling the input line via get_async_writer()
  • TODO: command groups

Basic Example

A minimal example showing a basic REPL is as follows:

use clapcmd::{ArgMatches, ClapCmd, ClapCmdResult, Command};

fn do_ping(_: &mut ClapCmd, _: ArgMatches) -> ClapCmdResult {
    println!("pong");
    Ok(())
}

fn main() {
    let mut cmd = ClapCmd::default();
    cmd.command(
        do_ping,
        Command::new("ping").about("do a ping")
    );
    cmd.run_loop();
}

With State

To pass state or persistent information to callbacks, provide a State class like so. The State class must implement Clone and Default traits, and can be accessed via the get_state() and set_state() methods on the ClapCmd reference passed into the callback.

use clapcmd::{ArgMatches, ClapCmd, ClapCmdResult, Command};

#[derive(Clone, Default)]
struct State {
   counter: u32,
}

fn do_count(cmd: &mut ClapCmd<State>, _: ArgMatches) -> ClapCmdResult
where
    State: Clone + Default,
{
    let state = cmd.get_state();
    let new_count = state.counter + 1;
    println!("{}", new_count);
    cmd.set_state(State { counter: new_count });
    Ok(())
}

fn main() {
    let mut cmd = ClapCmd::<State>::default();
    cmd.command(
        do_count,
        Command::new("count").about("increment a counter")
    );
    cmd.run_loop();
}

Related Projects