use std::io;
use std::path::{Path, PathBuf};
use clap::Command as Cmd;
pub use clap_complete::Shell;
use super::family::Family;
fn named_commands(family: &'static Family) -> Vec<(String, u8, Cmd)> {
let mut all: Vec<(String, u8, Cmd)> = family
.tools
.iter()
.map(|tool| {
(
tool.name.to_string(),
tool.section,
super::tool_command(family, tool),
)
})
.collect();
all.push((family.repo.to_string(), 1, super::repo_command(family)));
all
}
pub fn man_pages(family: &'static Family, share: &Path) -> io::Result<Vec<PathBuf>> {
let mut written = Vec::new();
for (name, section, cmd) in named_commands(family) {
let dir = share.join("man").join(format!("man{section}"));
std::fs::create_dir_all(&dir)?;
let cmd = cmd.version(family.version);
let skip: Vec<&str> = if name == family.repo {
family.tools.iter().map(|t| t.verb).collect()
} else {
Vec::new()
};
write_pages(family, &dir, section, &name, cmd, &skip, &mut written)?;
}
Ok(written)
}
fn write_pages(
family: &Family,
dir: &Path,
section: u8,
name: &str,
cmd: Cmd,
skip: &[&str],
written: &mut Vec<PathBuf>,
) -> io::Result<()> {
let path = dir.join(format!("{name}.{section}"));
let mut page = Vec::new();
let leaked: &'static str = Box::leak(name.to_string().into_boxed_str());
clap_mangen::Man::new(cmd.clone().name(leaked))
.title(name.to_uppercase())
.section(section.to_string())
.source(format!("{} {}", family.crate_name, family.version))
.manual(family.repo)
.render(&mut page)?;
std::fs::write(&path, page)?;
written.push(path);
for sub in cmd.get_subcommands() {
if sub.is_hide_set() || sub.get_name() == "help" || skip.contains(&sub.get_name()) {
continue;
}
let sub_name = format!("{name}-{}", sub.get_name());
write_pages(family, dir, section, &sub_name, sub.clone(), &[], written)?;
}
Ok(())
}
pub fn completion_path(share: &Path, shell: Shell, name: &str) -> PathBuf {
match shell {
Shell::Zsh => share.join("zsh/site-functions").join(format!("_{name}")),
Shell::Bash => share.join("bash-completion/completions").join(name),
Shell::Fish => share
.join("fish/vendor_completions.d")
.join(format!("{name}.fish")),
other => share.join(other.to_string()).join(name),
}
}
pub const SHELLS: [Shell; 3] = [Shell::Zsh, Shell::Bash, Shell::Fish];
pub fn completions(family: &'static Family, share: &Path) -> io::Result<Vec<PathBuf>> {
let mut written = Vec::new();
for (name, _, mut cmd) in named_commands(family) {
for shell in SHELLS {
let path = completion_path(share, shell, &name);
std::fs::create_dir_all(path.parent().expect("a completion has a directory"))?;
let mut script = Vec::new();
clap_complete::generate(shell, &mut cmd, name.clone(), &mut script);
std::fs::write(&path, script)?;
written.push(path);
}
}
Ok(written)
}