Skip to content

Instantly share code, notes, and snippets.

@tadzik
Last active January 4, 2020 20:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tadzik/249986bddfce57773567db272323742c to your computer and use it in GitHub Desktop.
Save tadzik/249986bddfce57773567db272323742c to your computer and use it in GitHub Desktop.
enum DispatchResult<'a, T> {
Matched(&'a T),
Ambiguous(Vec<&'a String>),
NotFound,
}
fn dispatch<'a, T>(command: &str, candidates: &'a Vec<(String, T)>) -> DispatchResult<'a, T> {
let matches = candidates.iter()
.filter(|c| c.0.starts_with(command))
.collect::<Vec<_>>();
if matches.len() == 1 {
DispatchResult::Matched(&matches[0].1)
} else if matches.len() == 0 {
DispatchResult::NotFound
} else {
DispatchResult::Ambiguous(matches.iter().map(|c| &c.0).collect::<Vec<_>>())
}
}
fn main() {
let commands: Vec<(String, Box<dyn Fn()>)> = vec![
(String::from("start"), Box::new(|| start_work())),
(String::from("status"), Box::new(|| show_status())),
];
match env::args().nth(1) {
Some(command) => match dispatch(&command, &commands) {
DispatchResult::Matched(target) => target(),
DispatchResult::Ambiguous(matches) => {
println!("More than one command matches prefix '{}':", command);
for m in matches {
println!("\t{}", m);
}
println!("Please be more specific");
},
DispatchResult::NotFound => usage(),
}
None => usage(),
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment