Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-3029] Add support for shell completion #103

Merged
merged 9 commits into from
Aug 21, 2023
Merged

Conversation

dani-garcia
Copy link
Member

@dani-garcia dani-garcia commented Jul 14, 2023

Type of change

- [ ] Bug fix
- [x] New feature development
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
- [ ] Build/deploy pipeline (DevOps)
- [ ] Other

Objective

Add support for shell completion using the official crates from the Clap project.

I've made a command for each to be generated at runtime, but we could potentially also generate them at build time, though that will require to move the Cli and Commands structs to a separate file. Build time generation might make more sense if we ever want to distribute .deb or .rpm packages.

Code changes

  • Changed #[command(name)] to bws to represent the binary name, used by the shell completions.
  • Added a command:
    • Completions: Receives a single parameter for the type of shell to generate the completions for (Bash, zsh, pwsh, etc), if not provided it will try autodetecting the current shell.

Note that both these changes seem to ignore the hide parameter set in the deprecated commands, so we might want to consider holding off merging this until they are removed.

How to enable completions

This varies by shell, in zsh:
Edit the file ~/.zshrc and append to the end the following line:

source <(/path/to/bws completions zsh)

Screenshots

Screen.Recording.2023-07-14.at.18.27.32.mov

@bitwarden-bot
Copy link

bitwarden-bot commented Jul 14, 2023

Logo
Checkmarx One – Scan Summary & Details89d8e8cf-22b3-401d-bebd-09cca4a1e513

No New Or Fixed Issues Found

@Hinton
Copy link
Member

Hinton commented Jul 20, 2023

Do we know what the convention is for shell completion and manpages for rust packages? Feels somewhat odd to have the CLI itself generate them.

@dani-garcia
Copy link
Member Author

I don't think there are specific conventions for rust packages, usually man pages are included in the system install packages (so .deb or .rpm in Linux), and it's the system package manager that moves them to the correct place. We could generate them at build time and include them in the release zip, but without an automatic installation step that might end up confusing users.

Shell autocompletion on the other hand I've noticed a lot of software handle the generation from the CLI, I assume because they can't control which shell the user is running, and the generated autocomplete code is different for all of them, for example:

  • Trivy and K0s have a completion subcommand
  • Terraform has an --install-autocomplete flag

@Hinton
Copy link
Member

Hinton commented Aug 17, 2023

Please split this into two PRs. We'll try and get shell completion merged while thinking of what we should do about man pages.

@dani-garcia dani-garcia changed the title [PM-3029] Add support for shell completion and manpages [PM-3029] Add support for shell completion Aug 21, 2023
Copy link
Member

@Hinton Hinton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add this to the readme?

Comment on lines +21 to +43
## How to enable shell autocompletions

### Zsh

If completion is not enabled already, you need to enable it first:

```zsh
echo "autoload -U compinit; compinit" >> ~/.zshrc
```

Enable autocompletions for the current user:

```zsh
echo 'source <(/path/to/bws completions zsh)' >> ~/.zshrc
```

### Bash

Enable autocompletions for the current user:

```zsh
echo 'source <(/path/to/bws completions bash)' >> ~/.bashrc
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in the readme or the help docs? The readme is only really visible on crates.io

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help docs should probably only be updated after we make a release with these changes merged in I think, otherwise it might be confusing for users of the existing release.

crates/bws/src/main.rs Outdated Show resolved Hide resolved
crates/bws/src/main.rs Outdated Show resolved Hide resolved
Comment on lines 253 to 263
if let Commands::Completions { shell } = command {
let Some(shell) = shell.or_else(Shell::from_env) else {
eprintln!("Couldn't autodetect a valid shell. Run `bws completions --help` for more info.");
std::process::exit(1);
};

let mut cmd = Cli::command();
let name = cmd.get_name().to_string();
clap_complete::generate(shell, &mut cmd, name, &mut std::io::stdout());
return Ok(());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're starting to have a few if let here, should we try and use a switch?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point, we should probably consider extracting them to a separate function in the future because the process_commands is already getting pretty big, but that's a bigger refactoring.

@dani-garcia dani-garcia merged commit 3e07b43 into master Aug 21, 2023
39 checks passed
@dani-garcia dani-garcia deleted the complete_and_manpages branch November 14, 2023 19:29
dani-garcia added a commit that referenced this pull request May 1, 2024
## Type of change
```
- [ ] Bug fix
- [x] New feature development
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
- [ ] Build/deploy pipeline (DevOps)
- [ ] Other
```

## Objective
Implement support for generating manpages at compile-time. Extracted
from PR #103. The manpages also get generated in CI and uploaded as
artifacts.

Note that because the CLI struct needs to be accessed by a build script,
it had to be extracted to a separate self contained file.

 ## How to generate manpages locally

The manpages get generated by a build script, and are available in the
crate's build script OUT_DIR, to get it:
```
cargo build --message-format json > build.json
jq -r --slurp '.[] | select (.reason == "build-script-executed") | select(.package_id|contains("crates/bws")) .out_dir' build.json
```

The output path is going to be something like
`sdk/target/debug/build/bws-4acb75a675879df1/out`.

Copy them to a better location, and then you can view the pages: 
- `man ./my-pages/bws.1` 
- `man ./my-pages/bws-project.1` 
- `man ./my-pages/bws-secret.1` 
- …

If you install them in a system path, you could also just access them
with `man bws`, but that path is system specific. In Ubuntu I think it
is `/usr/share/man`

## Screenshots

![Screenshot 2023-07-14 at 18 28
54](https://github.com/bitwarden/sdk/assets/725423/549fbaf8-1d1a-4d77-b348-61e0ddba6911)


![image](https://github.com/bitwarden/sdk/assets/725423/6b0725d7-f307-42db-aa24-88aff7245e3b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants