aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart/src/commands/completion.rs
blob: 97d771c8ea90c57a86157a4f3c231914f70634f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use clap::Args;
use clap::CommandFactory as _;
use clap_complete::aot::Shell;
use mozart_core::console::IoInterface;

#[derive(Args)]
pub struct CompletionArgs {
    /// The shell to generate completions for (auto-detected from $SHELL if omitted)
    #[arg(value_enum)]
    pub shell: Option<Shell>,
}

pub async fn execute(
    args: &CompletionArgs,
    _cli: &super::Cli,
    _io: std::sync::Arc<std::sync::Mutex<Box<dyn IoInterface>>>,
) -> anyhow::Result<()> {
    let shell = match args.shell {
        Some(s) => s,
        None => detect_shell()?,
    };
    let mut cmd = super::Cli::command();
    clap_complete::aot::generate(shell, &mut cmd, "mozart", &mut std::io::stdout());
    Ok(())
}

fn detect_shell() -> anyhow::Result<Shell> {
    let shell_env = std::env::var("SHELL")
        .map_err(|_| anyhow::anyhow!("Could not auto-detect shell. Please specify one of: bash, elvish, fish, powershell, zsh"))?;
    let basename = std::path::Path::new(&shell_env)
        .file_name()
        .and_then(|s| s.to_str())
        .unwrap_or("");
    match basename {
        "bash" => Ok(Shell::Bash),
        "zsh" => Ok(Shell::Zsh),
        "fish" => Ok(Shell::Fish),
        "elvish" => Ok(Shell::Elvish),
        "pwsh" | "powershell" => Ok(Shell::PowerShell),
        _ => anyhow::bail!(
            "Unrecognized shell '{}'. Please specify one of: bash, elvish, fish, powershell, zsh",
            basename
        ),
    }
}