1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
// This example shows how to implement a command with a "catch all."
//
// This requires writing your own impl for `Decodable` because docopt's
// decoder uses `Option<T>` to mean "T may not be present" rather than
// "T may be present but incorrect."
use std::fmt;
use docopt::Docopt;
use serde::{Deserialize, de::{Deserializer, Error, Visitor}};
// Write the Docopt usage string.
const USAGE: &'static str = "
Rust's package manager
Usage:
mycli [<command>]
Options:
-h, --help Display this message
";
#[derive(Debug, Deserialize)]
struct Args {
arg_command: Command,
}
struct CommandVisitor;
impl<'de> Visitor<'de> for CommandVisitor {
type Value = Command;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string A, B or C")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where E: Error
{
Ok(match s {
"" => Command::None,
"A" => Command::A,
"B" => Command::B,
"C" => Command::C,
s => Command::Unknown(s.to_string()),
})
}
}
impl<'de> Deserialize<'de> for Command {
fn deserialize<D>(d: D) -> Result<Command, D::Error>
where D: Deserializer<'de>
{
d.deserialize_str(CommandVisitor)
}
}
#[derive(Debug)]
enum Command {
A,
B,
C,
Unknown(String),
None,
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.deserialize())
.unwrap_or_else(|e| e.exit());
println!("{:?}", args);
}
|