theater_cli/commands/
completion.rs1use clap::{CommandFactory, Parser};
2use clap_complete::{generate, Shell};
3use std::io;
4use tracing::debug;
5
6use crate::error::{CliError, CliResult};
7use crate::CommandContext;
8
9#[derive(Debug, Parser)]
10#[command(
11 long_about = "Generate shell completion scripts.\n\nYou typically only need to re-run this after updating the theater CLI or changing the completion file location."
12)]
13pub struct CompletionArgs {
14 #[arg(value_enum)]
16 pub shell: Shell,
17
18 #[arg(short, long)]
20 pub output: Option<std::path::PathBuf>,
21}
22
23pub async fn execute_async(args: &CompletionArgs, ctx: &CommandContext) -> CliResult<()> {
25 debug!("Generating shell completion for: {:?}", args.shell);
26
27 let mut app = crate::Cli::command();
28 let app_name = app.get_name().to_string();
29
30 match &args.output {
31 Some(output_path) => {
32 debug!("Writing completion to file: {:?}", output_path);
33
34 let mut file = std::fs::File::create(output_path).map_err(|e| {
35 CliError::file_operation_failed(
36 "create completion file",
37 output_path.display().to_string(),
38 e,
39 )
40 })?;
41
42 generate(args.shell, &mut app, &app_name, &mut file);
43
44 ctx.output.success(&format!(
45 "Shell completion for {} written to: {}",
46 args.shell,
47 output_path.display()
48 ))?;
49 }
50 None => {
51 debug!("Writing completion to stdout");
52 generate(args.shell, &mut app, &app_name, &mut io::stdout());
53 }
54 }
55
56 if args.output.is_some() && !ctx.json {
59 show_installation_instructions(args.shell, ctx)?;
60 }
61
62 Ok(())
63}
64
65fn show_installation_instructions(shell: Shell, ctx: &CommandContext) -> CliResult<()> {
67 let instructions = match shell {
68 Shell::Bash => {
69 r#"
70To install bash completions:
71
721. Save the completion script:
73 theater completion bash > ~/.local/share/bash-completion/completions/theater
74
752. Or add to your ~/.bashrc:
76 eval "$(theater completion bash)"
77
783. Restart your shell or run:
79 source ~/.bashrc
80"#
81 }
82 Shell::Zsh => {
83 r#"
84To install zsh completions:
85
861. Save the completion script to a directory in your $fpath:
87 theater completion zsh > ~/.local/share/zsh/site-functions/_theater
88
892. Or add to your ~/.zshrc:
90 eval "$(theater completion zsh)"
91
923. Restart your shell or run:
93 source ~/.zshrc
94"#
95 }
96 Shell::Fish => {
97 r#"
98To install fish completions:
99
1001. Save the completion script:
101 theater completion fish > ~/.config/fish/completions/theater.fish
102
1032. Or add to your fish config:
104 theater completion fish | source
105
1063. Restart your shell
107"#
108 }
109 Shell::PowerShell => {
110 r#"
111To install PowerShell completions:
112
1131. Add to your PowerShell profile:
114 theater completion powershell | Out-String | Invoke-Expression
115
1162. Or save to a file and dot-source it in your profile:
117 theater completion powershell > theater_completion.ps1
118 . .\theater_completion.ps1
119"#
120 }
121 Shell::Elvish => {
122 r#"
123To install Elvish completions:
124
1251. Add to your ~/.config/elvish/rc.elv:
126 eval (theater completion elvish | slurp)
127"#
128 }
129 _ => "Please refer to your shell's documentation for completion installation.",
130 };
131
132 ctx.output.info(instructions)?;
133 Ok(())
134}