mirror of
https://github.com/clap-rs/clap
synced 2025-03-04 15:27:16 +00:00
parent
ff53b087e0
commit
ec4735a44e
4 changed files with 105 additions and 2 deletions
|
@ -143,6 +143,7 @@ rustversion = "1"
|
||||||
trycmd = { version = "0.13", default-features = false, features = ["color-auto", "diff", "examples"] }
|
trycmd = { version = "0.13", default-features = false, features = ["color-auto", "diff", "examples"] }
|
||||||
humantime = "2"
|
humantime = "2"
|
||||||
snapbox = "0.2.9"
|
snapbox = "0.2.9"
|
||||||
|
shlex = "1.1.0"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "demo"
|
name = "demo"
|
||||||
|
@ -182,6 +183,11 @@ name = "hostname"
|
||||||
path = "examples/multicall-hostname.rs"
|
path = "examples/multicall-hostname.rs"
|
||||||
required-features = ["unstable-multicall"]
|
required-features = ["unstable-multicall"]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "repl"
|
||||||
|
path = "examples/repl.rs"
|
||||||
|
required-features = ["unstable-multicall"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "01_quick"
|
name = "01_quick"
|
||||||
path = "examples/tutorial_builder/01_quick.rs"
|
path = "examples/tutorial_builder/01_quick.rs"
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
- hostname: [builder](multicall-hostname.md)
|
- hostname: [builder](multicall-hostname.md)
|
||||||
- Topics:
|
- Topics:
|
||||||
- Subcommands
|
- Subcommands
|
||||||
|
- repl: [builder](repl.rs)
|
||||||
|
- Topics:
|
||||||
|
- Read-Eval-Print Loops / Custom command lines
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,13 @@ use clap::Command;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
|
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
|
||||||
|
.multicall(true)
|
||||||
.arg_required_else_help(true)
|
.arg_required_else_help(true)
|
||||||
.subcommand_value_name("APPLET")
|
.subcommand_value_name("APPLET")
|
||||||
.subcommand_help_heading("APPLETS")
|
.subcommand_help_heading("APPLETS")
|
||||||
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
|
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
|
||||||
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
|
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
|
||||||
|
|
||||||
let cmd = cmd.multicall(true);
|
|
||||||
|
|
||||||
match cmd.get_matches().subcommand_name() {
|
match cmd.get_matches().subcommand_name() {
|
||||||
Some("hostname") => println!("www"),
|
Some("hostname") => println!("www"),
|
||||||
Some("dnsdomainname") => println!("example.com"),
|
Some("dnsdomainname") => println!("example.com"),
|
||||||
|
|
95
examples/repl.rs
Normal file
95
examples/repl.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// Note: this requires the `unstable-multicall` feature
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use clap::Command;
|
||||||
|
|
||||||
|
fn main() -> Result<(), String> {
|
||||||
|
loop {
|
||||||
|
let line = readline()?;
|
||||||
|
let line = line.trim();
|
||||||
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match respond(line) {
|
||||||
|
Ok(quit) => {
|
||||||
|
if quit {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
write!(std::io::stdout(), "{}", err).map_err(|e| e.to_string())?;
|
||||||
|
std::io::stdout().flush().map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn respond(line: &str) -> Result<bool, String> {
|
||||||
|
let args = shlex::split(line).ok_or("error: Invalid quoting")?;
|
||||||
|
let matches = cli()
|
||||||
|
.try_get_matches_from(&args)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
match matches.subcommand() {
|
||||||
|
Some(("ping", _matches)) => {
|
||||||
|
write!(std::io::stdout(), "Pong").map_err(|e| e.to_string())?;
|
||||||
|
std::io::stdout().flush().map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
Some(("quit", _matches)) => {
|
||||||
|
write!(std::io::stdout(), "Exiting ...").map_err(|e| e.to_string())?;
|
||||||
|
std::io::stdout().flush().map_err(|e| e.to_string())?;
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
Some((name, _matches)) => unimplemented!("{}", name),
|
||||||
|
None => unreachable!("subcommand required"),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cli() -> Command<'static> {
|
||||||
|
// strip out usage
|
||||||
|
const PARSER_TEMPLATE: &str = "\
|
||||||
|
{all-args}
|
||||||
|
";
|
||||||
|
// strip out name/version
|
||||||
|
const APPLET_TEMPLATE: &str = "\
|
||||||
|
{about-with-newline}\n\
|
||||||
|
{usage-heading}\n {usage}\n\
|
||||||
|
\n\
|
||||||
|
{all-args}{after-help}\
|
||||||
|
";
|
||||||
|
|
||||||
|
Command::new("repl")
|
||||||
|
.multicall(true)
|
||||||
|
.arg_required_else_help(true)
|
||||||
|
.disable_help_flag(true)
|
||||||
|
.subcommand_required(true)
|
||||||
|
.subcommand_value_name("APPLET")
|
||||||
|
.subcommand_help_heading("APPLETS")
|
||||||
|
.help_template(PARSER_TEMPLATE)
|
||||||
|
.subcommand(
|
||||||
|
Command::new("ping")
|
||||||
|
.about("Get a response")
|
||||||
|
.help_template(APPLET_TEMPLATE),
|
||||||
|
)
|
||||||
|
.subcommand(
|
||||||
|
Command::new("quit")
|
||||||
|
.alias("exit")
|
||||||
|
.about("Quit the REPL")
|
||||||
|
.help_template(APPLET_TEMPLATE),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readline() -> Result<String, String> {
|
||||||
|
write!(std::io::stdout(), "$ ").map_err(|e| e.to_string())?;
|
||||||
|
std::io::stdout().flush().map_err(|e| e.to_string())?;
|
||||||
|
let mut buffer = String::new();
|
||||||
|
std::io::stdin()
|
||||||
|
.read_line(&mut buffer)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
Ok(buffer)
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue