56 lines
1.6 KiB
Rust
56 lines
1.6 KiB
Rust
use std::io::{self, Write};
|
|
|
|
use anyhow::{Context, Result};
|
|
use clap::CommandFactory;
|
|
use clap_complete::{Shell, generate};
|
|
|
|
use crate::cli::Ahab;
|
|
|
|
pub fn completions(shell: Shell) -> Result<()> {
|
|
let script = script(shell);
|
|
|
|
let mut stdout = io::stdout().lock();
|
|
match stdout.write_all(&script).and_then(|()| stdout.flush()) {
|
|
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => Ok(()),
|
|
result => result.context("writing the completion script"),
|
|
}
|
|
}
|
|
|
|
fn script(shell: Shell) -> Vec<u8> {
|
|
let mut cmd = Ahab::command();
|
|
let name = cmd.get_name().to_string();
|
|
|
|
let mut script = Vec::new();
|
|
generate(shell, &mut cmd, name, &mut script);
|
|
script
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{Ahab, Shell, script};
|
|
use clap::{CommandFactory, ValueEnum};
|
|
|
|
#[test]
|
|
fn every_shell_gets_a_script_covering_the_subcommands() {
|
|
// asked of the parser rather than listed here, which is a list that
|
|
// silently stops covering the newest command
|
|
let subcommands: Vec<String> = Ahab::command()
|
|
.get_subcommands()
|
|
.map(|sub| sub.get_name().to_string())
|
|
.collect();
|
|
|
|
assert!(subcommands.len() > 1, "{subcommands:?}");
|
|
|
|
for shell in Shell::value_variants() {
|
|
let out = String::from_utf8(script(*shell)).expect("script is utf8");
|
|
|
|
for subcommand in &subcommands {
|
|
assert!(
|
|
out.contains(subcommand),
|
|
"{shell:?} script never mentions {subcommand}"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|