use clap::CommandFactory;
use clap_complete::Shell;
use std::io;
pub fn generate_completions<T: CommandFactory>(shell: Shell) {
let mut cmd = T::command();
let bin_name = cmd.get_name().to_string();
println!("# Shell completion for {bin_name}");
println!("#");
println!("# To enable completions, add this to your shell config:");
println!("#");
match shell {
Shell::Bash => {
println!("# For bash (~/.bashrc):");
println!("# source <({bin_name} completions bash)");
}
Shell::Zsh => {
println!("# For zsh (~/.zshrc):");
println!("# {bin_name} completions zsh > ~/.zsh/completions/_{bin_name}");
println!("# # Ensure fpath includes ~/.zsh/completions");
}
Shell::Fish => {
println!("# For fish (~/.config/fish/config.fish):");
println!("# {bin_name} completions fish | source");
}
_ => {
println!("# For {shell}:");
println!("# {bin_name} completions {shell} > /path/to/completions/_{bin_name}");
}
}
println!();
clap_complete::generate(shell, &mut cmd, bin_name, &mut io::stdout());
}
#[cfg(test)]
mod tests {
use super::*;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "test-cli")]
struct TestCli {
#[command(subcommand)]
command: TestCommands,
}
#[derive(Subcommand)]
enum TestCommands {
Version,
Test { arg: String },
}
#[test]
fn test_generate_completions_bash() {
generate_completions::<TestCli>(Shell::Bash);
}
#[test]
fn test_generate_completions_zsh() {
generate_completions::<TestCli>(Shell::Zsh);
}
#[test]
fn test_generate_completions_fish() {
generate_completions::<TestCli>(Shell::Fish);
}
#[test]
fn test_generate_completions_elvish() {
generate_completions::<TestCli>(Shell::Elvish);
}
#[test]
fn test_generate_completions_powershell() {
generate_completions::<TestCli>(Shell::PowerShell);
}
#[test]
fn test_all_shells_generate_without_panic() {
let shells = vec![
Shell::Bash,
Shell::Zsh,
Shell::Fish,
Shell::Elvish,
Shell::PowerShell,
];
for shell in shells {
generate_completions::<TestCli>(shell);
}
}
}