zoi/cmd/
shell.rs

1use crate::cli::Cli;
2use clap::CommandFactory;
3use clap_complete::{Shell, generate};
4use colored::*;
5use std::fs;
6use std::io::{Error, ErrorKind};
7
8fn install_bash_completions(cmd: &mut clap::Command) -> Result<(), Error> {
9    println!("Installing bash completions...");
10    let home = dirs::home_dir()
11        .ok_or_else(|| Error::new(ErrorKind::NotFound, "Home directory not found"))?;
12    let completions_dir = home.join(".local/share/bash-completion/completions");
13    fs::create_dir_all(&completions_dir)?;
14    let path = completions_dir.join("zoi");
15    let mut file = fs::File::create(&path)?;
16    generate(Shell::Bash, cmd, "zoi", &mut file);
17    println!("Bash completions installed in: {:?}", path);
18    Ok(())
19}
20
21fn install_zsh_completions(cmd: &mut clap::Command) -> Result<(), Error> {
22    println!("Installing zsh completions...");
23    let home = dirs::home_dir()
24        .ok_or_else(|| Error::new(ErrorKind::NotFound, "Home directory not found"))?;
25    let completions_dir = home.join(".zsh/completions");
26    fs::create_dir_all(&completions_dir)?;
27    let path = completions_dir.join("_zoi");
28    let mut file = fs::File::create(&path)?;
29    generate(Shell::Zsh, cmd, "zoi", &mut file);
30    println!("Zsh completions installed in: {:?}", path);
31    println!("Ensure the directory is in your $fpath. Add this to your .zshrc if it's not:");
32    println!("  fpath=({:?} $fpath)", completions_dir);
33    Ok(())
34}
35
36fn install_fish_completions(cmd: &mut clap::Command) -> Result<(), Error> {
37    println!("Installing fish completions...");
38    let home = dirs::home_dir()
39        .ok_or_else(|| Error::new(ErrorKind::NotFound, "Home directory not found"))?;
40    let completions_dir = home.join(".config/fish/completions");
41    fs::create_dir_all(&completions_dir)?;
42    let path = completions_dir.join("zoi.fish");
43    let mut file = fs::File::create(&path)?;
44    generate(Shell::Fish, cmd, "zoi", &mut file);
45    println!("Fish completions installed in: {:?}", path);
46    Ok(())
47}
48
49fn install_elvish_completions(cmd: &mut clap::Command) -> Result<(), Error> {
50    println!("Installing elvish completions...");
51    let home = dirs::home_dir()
52        .ok_or_else(|| Error::new(ErrorKind::NotFound, "Home directory not found"))?;
53    let completions_dir = home.join(".config/elvish/completions");
54    fs::create_dir_all(&completions_dir)?;
55    let path = completions_dir.join("zoi.elv");
56    let mut file = fs::File::create(&path)?;
57    generate(Shell::Elvish, cmd, "zoi", &mut file);
58    println!("Elvish completions installed in: {:?}", path);
59    Ok(())
60}
61
62#[cfg(windows)]
63fn install_powershell_completions(cmd: &mut clap::Command) -> Result<(), Error> {
64    println!("Installing PowerShell completions...");
65    let home = dirs::home_dir()
66        .ok_or_else(|| Error::new(ErrorKind::NotFound, "Home directory not found"))?;
67    let profile_dir = home.join("Documents/PowerShell");
68    fs::create_dir_all(&profile_dir)?;
69    let profile_path = profile_dir.join("Microsoft.PowerShell_profile.ps1");
70
71    let mut file = fs::OpenOptions::new()
72        .append(true)
73        .create(true)
74        .open(&profile_path)?;
75    use std::io::Write;
76    writeln!(file, "")?;
77
78    let mut script_buf = Vec::new();
79    generate(Shell::PowerShell, cmd, "zoi", &mut script_buf);
80    file.write_all(&script_buf)?;
81
82    println!(
83        "PowerShell completion script appended to your profile: {:?}",
84        profile_path
85    );
86    println!("Please restart your shell or run '. $PROFILE' to activate it.");
87    Ok(())
88}
89
90pub fn run(shell: Shell) {
91    let mut cmd = Cli::command();
92
93    let result = if cfg!(windows) {
94        #[cfg(windows)]
95        {
96            if shell == Shell::PowerShell {
97                install_powershell_completions(&mut cmd)
98            } else {
99                eprintln!("On Windows, only PowerShell completions are supported.");
100                return;
101            }
102        }
103        #[cfg(not(windows))]
104        {
105            Ok(())
106        }
107    } else {
108        match shell {
109            Shell::Bash => install_bash_completions(&mut cmd),
110            Shell::Zsh => install_zsh_completions(&mut cmd),
111            Shell::Fish => install_fish_completions(&mut cmd),
112            Shell::Elvish => install_elvish_completions(&mut cmd),
113            Shell::PowerShell => {
114                eprintln!("PowerShell completions are only for Windows.");
115                return;
116            }
117            _ => {
118                eprintln!(
119                    "{}: Automatic installation for '{}' is not yet supported.",
120                    "Warning".yellow(),
121                    shell
122                );
123                println!(
124                    "Please generate them manually: zoi generate-completions {}",
125                    shell
126                );
127                return;
128            }
129        }
130    };
131
132    if let Err(e) = result {
133        eprintln!("{}: {}", "Error".red().bold(), e);
134    }
135}