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