Skip to main content

codex_wrapper/command/
completion.rs

1/// Generate shell completion scripts.
2///
3/// Wraps `codex completion [SHELL]`.
4use crate::Codex;
5use crate::command::CodexCommand;
6use crate::error::Result;
7use crate::exec::{self, CommandOutput};
8
9/// Supported shells for completion generation.
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
11pub enum Shell {
12    #[default]
13    Bash,
14    Elvish,
15    Fish,
16    Powershell,
17    Zsh,
18}
19
20impl Shell {
21    pub(crate) fn as_arg(self) -> &'static str {
22        match self {
23            Self::Bash => "bash",
24            Self::Elvish => "elvish",
25            Self::Fish => "fish",
26            Self::Powershell => "powershell",
27            Self::Zsh => "zsh",
28        }
29    }
30}
31
32/// Generate shell completion scripts for the Codex CLI.
33#[derive(Debug, Clone)]
34pub struct CompletionCommand {
35    shell: Option<Shell>,
36}
37
38impl CompletionCommand {
39    #[must_use]
40    pub fn new() -> Self {
41        Self { shell: None }
42    }
43
44    /// Set the target shell (defaults to bash if not specified).
45    #[must_use]
46    pub fn shell(mut self, shell: Shell) -> Self {
47        self.shell = Some(shell);
48        self
49    }
50}
51
52impl Default for CompletionCommand {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl CodexCommand for CompletionCommand {
59    type Output = CommandOutput;
60
61    fn args(&self) -> Vec<String> {
62        let mut args = vec!["completion".into()];
63        if let Some(shell) = self.shell {
64            args.push(shell.as_arg().into());
65        }
66        args
67    }
68
69    async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
70        exec::run_codex(codex, self.args()).await
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn completion_default_args() {
80        assert_eq!(CompletionCommand::new().args(), vec!["completion"]);
81    }
82
83    #[test]
84    fn completion_zsh_args() {
85        assert_eq!(
86            CompletionCommand::new().shell(Shell::Zsh).args(),
87            vec!["completion", "zsh"]
88        );
89    }
90
91    #[test]
92    fn completion_fish_args() {
93        assert_eq!(
94            CompletionCommand::new().shell(Shell::Fish).args(),
95            vec!["completion", "fish"]
96        );
97    }
98}