use std::io;
use clap::{Args, CommandFactory};
use clap_complete::{generate, Shell};
use serde::Serialize;
use crate::exit::Exit;
use crate::output::{self, Envelope, Outcome};
use crate::Cli;
#[derive(Debug, Args)]
pub struct CompletionsArgs {
#[arg(value_enum)]
pub shell: Shell,
}
#[derive(Debug, Serialize)]
struct CompletionsRefusalReport {
shell: &'static str,
reason: &'static str,
}
pub fn run(args: CompletionsArgs) -> Exit {
if output::json_enabled() {
let envelope = Envelope::new(
"cortex.completions",
Exit::Usage,
CompletionsRefusalReport {
shell: shell_name(args.shell),
reason: "cortex completions emits a shell script to stdout; \
it cannot be wrapped in the --json envelope. Re-run \
without --json.",
},
)
.with_outcome(Outcome::Usage);
return output::emit(&envelope, Exit::Usage);
}
let mut cmd = Cli::command();
let bin_name = cmd.get_name().to_string();
let mut stdout = io::stdout().lock();
generate(args.shell, &mut cmd, bin_name, &mut stdout);
Exit::Ok
}
fn shell_name(shell: Shell) -> &'static str {
match shell {
Shell::Bash => "bash",
Shell::Elvish => "elvish",
Shell::Fish => "fish",
Shell::PowerShell => "powershell",
Shell::Zsh => "zsh",
_ => "unknown",
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn shell_name_covers_documented_set() {
assert_eq!(shell_name(Shell::Bash), "bash");
assert_eq!(shell_name(Shell::Zsh), "zsh");
assert_eq!(shell_name(Shell::Fish), "fish");
assert_eq!(shell_name(Shell::PowerShell), "powershell");
assert_eq!(shell_name(Shell::Elvish), "elvish");
}
}