use crate::capability;
use clap::Command;
pub fn path_to_id(path: &[&str]) -> Option<String> {
let id = path.join(".");
capability::find(&id).map(|_| id)
}
pub fn examples_block(examples: &[String]) -> String {
let mut s = String::from("Examples:\n");
for ex in examples {
s.push_str(" ");
s.push_str(ex);
s.push('\n');
}
s
}
pub fn inject(cmd: Command) -> Command {
inject_at(cmd, &mut Vec::new())
}
fn inject_at(mut cmd: Command, path: &mut Vec<String>) -> Command {
if !path.is_empty() {
let parts: Vec<&str> = path.iter().map(String::as_str).collect();
if let Some(id) = path_to_id(&parts) {
let d = capability::find(&id).expect("id resolved");
cmd = cmd
.long_about(d.long.clone())
.after_help(examples_block(&d.examples));
}
}
let child_names: Vec<String> = cmd
.get_subcommands()
.map(|c| c.get_name().to_string())
.collect();
for name in child_names {
path.push(name.clone());
cmd = cmd.mut_subcommand(&name, |child| inject_at(child, path));
path.pop();
}
cmd
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn path_resolves_known_capability() {
assert_eq!(
path_to_id(&["services", "start"]).as_deref(),
Some("services.start")
);
assert_eq!(path_to_id(&["capabilities"]), None);
assert_eq!(path_to_id(&["services"]), None);
assert_eq!(path_to_id(&["services", "bogus"]), None);
}
#[test]
fn examples_block_lists_each_example() {
let block = examples_block(&["fez a".into(), "fez b".into()]);
assert!(block.contains("fez a"));
assert!(block.contains("fez b"));
assert!(block.starts_with("Examples:"));
}
#[test]
fn inject_attaches_long_about_to_services_start() {
let cmd = inject(crate::cli::raw_command());
let services = cmd
.get_subcommands()
.find(|c| c.get_name() == "services")
.unwrap();
let start = services
.get_subcommands()
.find(|c| c.get_name() == "start")
.unwrap();
assert!(start.get_long_about().is_some());
assert!(start.get_after_help().is_some());
}
}