cc_switch/cli/
completion.rs

1use crate::config::ConfigStorage;
2use anyhow::Result;
3use clap::CommandFactory;
4use colored::*;
5use std::io::stdout;
6
7/// Generate shell aliases for eval
8///
9/// # Arguments
10/// * `shell` - Shell type (fish, zsh, bash)
11///
12/// # Errors
13/// Returns error if shell is not supported
14pub fn generate_aliases(shell: &str) -> Result<()> {
15    match shell {
16        "fish" => {
17            println!("alias cs='cc-switch'");
18            println!("alias ccd='claude --dangerously-skip-permissions'");
19        }
20        "zsh" => {
21            println!("alias cs='cc-switch'");
22            println!("alias ccd='claude --dangerously-skip-permissions'");
23        }
24        "bash" => {
25            println!("alias cs='cc-switch'");
26            println!("alias ccd='claude --dangerously-skip-permissions'");
27        }
28        _ => {
29            anyhow::bail!(
30                "Unsupported shell: {}. Supported shells: fish, zsh, bash",
31                shell
32            );
33        }
34    }
35
36    Ok(())
37}
38
39/// Generate shell completion script
40///
41/// # Arguments
42/// * `shell` - Shell type (fish, zsh, bash, elvish, powershell, nushell)
43///
44/// # Errors
45/// Returns error if shell is not supported or generation fails
46pub fn generate_completion(shell: &str) -> Result<()> {
47    use crate::cli::Cli;
48
49    let mut app = Cli::command();
50
51    match shell {
52        "fish" => {
53            generate_fish_completion(&mut app);
54        }
55        "zsh" => {
56            clap_complete::generate(
57                clap_complete::shells::Zsh,
58                &mut app,
59                "cc-switch",
60                &mut stdout(),
61            );
62
63            // Add aliases for zsh
64            println!("\n# Useful aliases for cc-switch");
65            println!("# Add these aliases to your ~/.zshrc:");
66            println!("alias cs='cc-switch'");
67            println!("alias ccd='claude --dangerously-skip-permissions'");
68            println!("# Or run this command to add aliases temporarily:");
69            println!("alias cs='cc-switch'; alias ccd='claude --dangerously-skip-permissions'");
70
71            println!("\n# Zsh completion generated successfully");
72            println!("# Add this to your ~/.zsh/completions/_cc-switch");
73            println!("# Or add this line to your ~/.zshrc:");
74            println!("# fpath=(~/.zsh/completions $fpath)");
75            println!("# Then restart your shell or run 'source ~/.zshrc'");
76            println!(
77                "{}",
78                "# Aliases 'cs' and 'ccd' have been added for convenience".green()
79            );
80        }
81        "bash" => {
82            clap_complete::generate(
83                clap_complete::shells::Bash,
84                &mut app,
85                "cc-switch",
86                &mut stdout(),
87            );
88
89            // Add aliases for bash
90            println!("\n# Useful aliases for cc-switch");
91            println!("# Add these aliases to your ~/.bashrc or ~/.bash_profile:");
92            println!("alias cs='cc-switch'");
93            println!("alias ccd='claude --dangerously-skip-permissions'");
94            println!("# Or run this command to add aliases temporarily:");
95            println!("alias cs='cc-switch'; alias ccd='claude --dangerously-skip-permissions'");
96
97            println!("\n# Bash completion generated successfully");
98            println!("# Add this to your ~/.bash_completion or /etc/bash_completion.d/");
99            println!("# Then restart your shell or run 'source ~/.bashrc'");
100            println!(
101                "{}",
102                "# Aliases 'cs' and 'ccd' have been added for convenience".green()
103            );
104        }
105        "elvish" => {
106            clap_complete::generate(
107                clap_complete::shells::Elvish,
108                &mut app,
109                "cc-switch",
110                &mut stdout(),
111            );
112
113            // Add aliases for elvish
114            println!("\n# Useful aliases for cc-switch");
115            println!("fn cs {{|@args| cc-switch $@args }}");
116            println!("fn ccd {{|@args| claude --dangerously-skip-permissions $@args }}");
117
118            println!("\n# Elvish completion generated successfully");
119            println!(
120                "{}",
121                "# Aliases 'cs' and 'ccd' have been added for convenience".green()
122            );
123        }
124        "powershell" => {
125            clap_complete::generate(
126                clap_complete::shells::PowerShell,
127                &mut app,
128                "cc-switch",
129                &mut stdout(),
130            );
131
132            // Add aliases for PowerShell
133            println!("\n# Useful aliases for cc-switch");
134            println!("Set-Alias -Name cs -Value cc-switch");
135            println!("function ccd {{ claude --dangerously-skip-permissions @args }}");
136
137            println!("\n# PowerShell completion generated successfully");
138            println!(
139                "{}",
140                "# Aliases 'cs' and 'ccd' have been added for convenience".green()
141            );
142        }
143        _ => {
144            anyhow::bail!(
145                "Unsupported shell: {}. Supported shells: fish, zsh, bash, elvish, powershell",
146                shell
147            );
148        }
149    }
150
151    Ok(())
152}
153
154/// List available configuration aliases for shell completion
155///
156/// Outputs all stored configuration aliases, one per line
157/// Also includes 'cc' as a special alias for resetting to default
158/// For contexts where user types 'cc-switch use c' or similar, 'current' is prioritized first
159///
160/// # Errors
161/// Returns error if loading configurations fails
162pub fn list_aliases_for_completion() -> Result<()> {
163    let storage = ConfigStorage::load()?;
164
165    // Always include 'cc' for reset functionality
166    println!("cc");
167
168    // Prioritize 'current' first if it exists - this ensures when user types 'cc-switch use c'
169    // or 'cs use c', the 'current' configuration appears first in completion
170    if storage.configurations.contains_key("current") {
171        println!("current");
172    }
173
174    // Output all other stored aliases in alphabetical order
175    let mut aliases: Vec<String> = storage.configurations.keys().cloned().collect();
176    aliases.sort();
177
178    for alias_name in aliases {
179        if alias_name != "current" {
180            println!("{alias_name}");
181        }
182    }
183
184    Ok(())
185}
186
187/// Generate custom fish completion with dynamic alias completion
188///
189/// # Arguments
190/// * `app` - The CLI application struct
191fn generate_fish_completion(app: &mut clap::Command) {
192    // Generate basic completion
193    clap_complete::generate(
194        clap_complete::shells::Fish,
195        app,
196        "cc-switch",
197        &mut std::io::stdout(),
198    );
199
200    // Add custom completion for use subcommand with dynamic aliases
201    println!("\n# Custom completion for use subcommand with dynamic aliases");
202    println!(
203        "complete -c cc-switch -n '__fish_cc_switch_using_subcommand use' -f -a '(cc-switch --list-aliases)' -d 'Configuration alias name'"
204    );
205    // Also support 'switch' as alias for 'use'
206    println!("# Custom completion for switch subcommand (alias for use)");
207    println!(
208        "complete -c cc-switch -n '__fish_cc_switch_using_subcommand switch' -f -a '(cc-switch --list-aliases)' -d 'Configuration alias name'"
209    );
210    // Custom completion for remove subcommand with dynamic aliases
211    println!("# Custom completion for remove subcommand with dynamic aliases");
212    println!(
213        "complete -c cc-switch -n '__fish_cc_switch_using_subcommand remove' -f -a '(cc-switch --list-aliases)' -d 'Configuration alias name'"
214    );
215
216    // Add useful aliases that can be eval'd
217    println!("\n# To use these aliases immediately, run:");
218    println!("# eval \"(cc-switch alias fish)\"");
219    println!("\n# Or add them permanently to your ~/.config/fish/config.fish:");
220    println!("# echo \"alias cs='cc-switch'\" >> ~/.config/fish/config.fish");
221    println!(
222        "# echo \"alias ccd='claude --dangerously-skip-permissions'\" >> ~/.config/fish/config.fish"
223    );
224    println!("\n# IMPORTANT: For cs alias completion to work, you must also:");
225    println!(
226        "# 1. Add the completion script: cc-switch completion fish > ~/.config/fish/completions/cc-switch.fish"
227    );
228    println!("# 2. OR run: eval \"(cc-switch completion fish)\" | source");
229
230    // Add completion for the 'cs' alias
231    println!("\n# Completion for the 'cs' alias");
232    println!("complete -c cs -w cc-switch");
233
234    // Add completion for cs alias subcommands (but NOT configuration aliases at top level)
235    println!("\n# Completion for 'cs' alias subcommands");
236    println!(
237        "complete -c cs -n '__fish_use_subcommand' -f -a 'add remove list set-default-dir completion alias use switch current' -d 'Subcommand'"
238    );
239
240    println!("\n# Fish completion generated successfully");
241    println!("# Add this to your ~/.config/fish/completions/cc-switch.fish");
242    println!("# Then restart your shell or run 'source ~/.config/fish/config.fish'");
243    println!(
244        "{}",
245        "# Aliases 'cs' and 'ccd' have been added for convenience".green()
246    );
247}