seaplane_cli/cli/cmds/
completion.rs

1use clap::{value_parser, ArgMatches, Command};
2use clap_complete::Shell;
3
4use crate::{
5    cli::{CliCommand, Seaplane},
6    error::Result,
7    printer::printer,
8    Ctx,
9};
10
11// @TODO @SIZE this str is ~3.5kb, it can be stored compressed at around 1.4kb. However that would
12// require a code to do the compression/decompression which is larger than the 2.1kb savings. There
13// are other locations in the code may benefit as well; if the uncompressed sum of those becomes
14// greater than code required to do the compression, we may look at compressing these large strings
15// to keep the binary size minimal.
16static COMPLETION_HELP: &str = "DISCUSSION:
17    Enabling shell completion scripts depends on the shell you're using, the
18    operating system (or distribution of operating system), or even your
19    individual setup. Consult your shell or operating system documentation for
20    full details.
21
22    This guide covers several common setups.
23
24    BASH:
25
26    Completion scripts are often stored either system wide in
27    `/etc/bash_completion.d/` or individually by user in
28    `$HOME/.local/share/bash-completion/completions/`. In either case, the file
29    is typically the name of the binary who we are trying to complete, in our
30    case that is `seaplane`.
31
32    e.g. to configure completions for just our user:
33
34      $ mkdir -p ~/.local/share/bash-completion/completions/
35      $ seaplane shell-completion bash > ~/.local/share/bash-completion/completions/seaplane
36
37    Alternative, it is common to eval the completions during shell startup. To
38    do so, one needs only place the following command in their `.bashrc` or
39    similar:
40
41      eval \"$(seaplane shell-completion bash)\"
42
43    Whichever method you choose, you may need to close and re-open your terminal
44    for the changes to take affect.
45
46    ZSH:
47
48    ZSH completions are commonly stored in the directories pointed to by your
49    `$fpath` variable. To use the completions generated by seaplane you must
50    either add the completion script to one of the existing directories, or add
51    your custom directory to the `$fpath` list. A common directory to either
52    create, or use if it exists is `~/.zfunc`
53
54      $ mkdir -p ~/.zfunc
55
56    Then in your `.zshrc` file, either add:
57
58      compinit
59      fpath+=~/.zfunc
60
61    Note, if your `.zshrc` file already had a line `compinit`, just ensure the
62    `fpath+=~/.zfunc` comes afterwards.
63
64    ZSH looks for files beginning with an underscore and the name of the binary
65    to complete, in our case that would be `_seaplane`:
66
67      $ seaplane shell-completion zsh > ~/.zfunc/_seaplane
68
69    Like BASH, you could alternatively use an `eval` command in your `.zshrc`:
70
71      eval \"$(seaplane shell-completion zsh)\"
72
73    Ensure you close and open your terminal to utilize the completions.
74
75    FISH:
76
77    Completion scripts are commonly stored in `$HOME/.config/fish/completions/`
78    using the file name of the binary to complete with a `.fish` extension:
79
80      $ seaplane shell-completion fish > ~/.config/fish/completions/seaplane.fish
81
82    Ensure you close and open your terminal to utilize the completions.
83
84    POWERSHELL:
85
86    These completion scripts require PowerShell v5.0 or newer. Windows 10 and 11
87    already have a new enough version, but on Windows 7 you will need to download
88    and update it manually which is out of scope for this guide.
89
90    The completions are loaded from a 'profile.' You check if a profile already exists using the command:
91
92      PS C:\\> Test-Path $profile
93
94    If this returns `False`, you must first create a profile:
95
96      PS C:\\> New-Item -path $profile -type file -force
97
98    This creates a file at
99    `${env:USERPROFILE}\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1`.
100
101    Inside this profile file, we can either place the completion script inline,
102    or `source` a separate file (our completion script). This guide will demo
103    placing the completion script inline:
104
105      PS C:\\> seaplane shell-completion powershell \\
106        >> ${env:USERPROFILE}\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1
107";
108
109#[derive(Copy, Clone, Debug)]
110pub struct SeaplaneShellCompletion;
111
112impl SeaplaneShellCompletion {
113    pub fn command() -> Command {
114        Command::new("shell-completion")
115            .about("Generate shell completion scripts for the Seaplane CLI")
116            .after_help(COMPLETION_HELP)
117            .arg(
118                arg!(shell ignore_case required)
119                    .help("The shell to generate completion scripts for")
120                    .value_parser(value_parser!(Shell)),
121            )
122    }
123}
124
125impl CliCommand for SeaplaneShellCompletion {
126    fn run(&self, ctx: &mut Ctx) -> Result<()> {
127        let mut app = Seaplane::command();
128
129        clap_complete::generate(ctx.args.shell.unwrap(), &mut app, "seaplane", &mut *printer());
130
131        Ok(())
132    }
133
134    fn update_ctx(&self, matches: &ArgMatches, ctx: &mut Ctx) -> Result<()> {
135        // unwrap is safe because clap won't let this value be empty
136        ctx.args.shell = matches.get_one::<Shell>("shell").copied();
137        Ok(())
138    }
139}