workhelix_cli_common/
completions.rs1use clap::CommandFactory;
7use clap_complete::Shell;
8use std::io;
9
10pub fn generate_completions<T: CommandFactory>(shell: Shell) {
34 let mut cmd = T::command();
35 let bin_name = cmd.get_name().to_string();
36
37 println!("# Shell completion for {bin_name}");
39 println!("#");
40 println!("# To enable completions, add this to your shell config:");
41 println!("#");
42
43 match shell {
44 Shell::Bash => {
45 println!("# For bash (~/.bashrc):");
46 println!("# source <({bin_name} completions bash)");
47 }
48 Shell::Zsh => {
49 println!("# For zsh (~/.zshrc):");
50 println!("# {bin_name} completions zsh > ~/.zsh/completions/_{bin_name}");
51 println!("# # Ensure fpath includes ~/.zsh/completions");
52 }
53 Shell::Fish => {
54 println!("# For fish (~/.config/fish/config.fish):");
55 println!("# {bin_name} completions fish | source");
56 }
57 _ => {
58 println!("# For {shell}:");
59 println!("# {bin_name} completions {shell} > /path/to/completions/_{bin_name}");
60 }
61 }
62
63 println!();
64
65 clap_complete::generate(shell, &mut cmd, bin_name, &mut io::stdout());
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use clap::{Parser, Subcommand};
73
74 #[derive(Parser)]
75 #[command(name = "test-cli")]
76 struct TestCli {
77 #[command(subcommand)]
78 command: TestCommands,
79 }
80
81 #[derive(Subcommand)]
82 enum TestCommands {
83 Version,
84 Test { arg: String },
85 }
86
87 #[test]
88 fn test_generate_completions_bash() {
89 generate_completions::<TestCli>(Shell::Bash);
91 }
92
93 #[test]
94 fn test_generate_completions_zsh() {
95 generate_completions::<TestCli>(Shell::Zsh);
96 }
97
98 #[test]
99 fn test_generate_completions_fish() {
100 generate_completions::<TestCli>(Shell::Fish);
101 }
102
103 #[test]
104 fn test_generate_completions_elvish() {
105 generate_completions::<TestCli>(Shell::Elvish);
106 }
107
108 #[test]
109 fn test_generate_completions_powershell() {
110 generate_completions::<TestCli>(Shell::PowerShell);
111 }
112
113 #[test]
114 fn test_all_shells_generate_without_panic() {
115 let shells = vec![
116 Shell::Bash,
117 Shell::Zsh,
118 Shell::Fish,
119 Shell::Elvish,
120 Shell::PowerShell,
121 ];
122
123 for shell in shells {
124 generate_completions::<TestCli>(shell);
125 }
126 }
127}