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

[#133] Added shell completion #134

Merged
merged 25 commits into from
Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f33ceb1
added concept completion implementation
MitchellBerend Oct 10, 2022
e38f514
cleaned up function call
MitchellBerend Oct 10, 2022
79820ab
updated clap_complete to correct version
MitchellBerend Oct 10, 2022
a6fbf59
ran formatter
MitchellBerend Oct 10, 2022
395f339
Merge branch 'main' into 133-shell-completion
MitchellBerend Oct 14, 2022
f32d5a9
Merge branch 'main' into 133-shell-completion
MitchellBerend Oct 14, 2022
7f557a7
updated clap completion to 4.0 version
MitchellBerend Oct 14, 2022
fafb893
added help text
MitchellBerend Oct 14, 2022
88af653
updated help text to get rid of doc test errors
MitchellBerend Oct 14, 2022
ea8388a
added a rename flag to the completion command
MitchellBerend Oct 15, 2022
9ff5ec1
Merge branch 'main' into 133-shell-completion
MitchellBerend Oct 15, 2022
23e6ecb
added integration test to check bash completion suggestion output
MitchellBerend Oct 15, 2022
42b59e9
fixed typo in test path
MitchellBerend Oct 15, 2022
3609f71
added completion test for macos
MitchellBerend Oct 15, 2022
97ca98e
added a section about autocomplete
MitchellBerend Oct 15, 2022
1c1041b
updated order of printout so the instruction is at the bottom and add…
MitchellBerend Oct 15, 2022
a1f9508
updated test outputs to reflect formatting change
MitchellBerend Oct 15, 2022
d025729
updated CHANGELOG
MitchellBerend Oct 15, 2022
1504fca
fixed formatting
MitchellBerend Oct 15, 2022
447ebf1
fixed formatting for zsh suggestion
MitchellBerend Oct 15, 2022
2e06eb2
fixed test line offsets
MitchellBerend Oct 15, 2022
ad856b8
updated suggestion definitions location to config/template
MitchellBerend Oct 15, 2022
33fbf40
Update src/config/cli.rs
MitchellBerend Oct 19, 2022
8139bfb
moved completion functions:
MitchellBerend Oct 19, 2022
8021d6e
added a renaming example to the readme
MitchellBerend Oct 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,28 @@ jobs:
ls -l $SYNC_DIR

if [[ ! -x $SYNC_DIR/rg ]]; then echo "error on: rg"; false; fi
- if: matrix.os == 'ubuntu-latest'
name: "Integration test: [ubuntu-latest] [check bash completion]"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cargo run -- completion bash --rename test-name > /dev/null 2> log

cat log | tail -n +5 > logg

diff logg tests/bash-completion
if [[ $? == 1 ]]; then logg test/bash-completion; false; fi
- if: matrix.os == 'macos-latest'
name: "Integration test: [macos-latest] [check zsh completion]"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cargo run -- completion zsh --rename test-name > /dev/null 2> log

cat log | tail -n +5 > logg

diff logg tests/zsh-completion
if [[ $? == 1 ]]; then logg test/zsh-completion; false; fi
- if: matrix.os != 'windows-latest'
name: "Integration test: [unix] [sync-ripgrep]"
env:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ available [on GitHub][2].
Adds new error message RepoError::NotFound when fetch_release_info
returns 404
(by [@crudiedo][crudiedo])
* [#133](https://github.com/chshersh/tool-sync/issues/133)
Added shell completion
(by [@MitchellBerend][MitchellBerend])


### Fixed

Expand Down
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ serde = { version = "1.0", features = ["derive"] }
ureq = { version = "2.5.0", features = ["json"] }
zip = { version = "0.6.3", default-features = false, features = ["deflate"] }

clap_complete = "4.0.2"
console = "0.15.2"
dirs = "4.0.0"
flate2 = "1.0"
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ By default `tool-sync` reads the configuration from from the `$HOME/.tool.toml`
path. But you can specify a custom location via the
`--config=/path/to/my/config` flag.

### Autocomplete

`tool-sync` can generate it's own autocomplete scripts for some common shell
emulators. you can run `tool completion --help` to see the supported shells.

If you decide to rename the `tool` binary a `--rename` flag will help make sure
the autocompletion will keep working.
MitchellBerend marked this conversation as resolved.
Show resolved Hide resolved

### Quick start

`tool-sync` has a command to generate a default configuration with examples and
Expand Down
52 changes: 52 additions & 0 deletions src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,58 @@ pub struct Cli {

#[derive(Subcommand, Debug)]
pub enum Command {
/// Generate shell completion scripts for GitHub CLI commands.
///
/// You will need to set up completions manually, follow the instructions below. The exact
/// config file locations might vary based on your system. Make sure to restart your
/// shell before testing whether completions are working.
///
/// ### bash
///
/// First, ensure that you install `bash-completion` using your package manager.
///
/// After, add this to your `~/.bash_profile`:
///
/// `eval "$(tool completion bash)"`
///
/// ### zsh
///
/// Generate a `_tool` completion script and put it somewhere in your `$fpath`:
///
/// `tool completion zsh > /usr/local/share/zsh/site-functions/_tool`
///
/// Ensure that the following is present in your `~/.zshrc`:
///
/// `autoload -U compinit`
/// `compinit -i`
///
/// Zsh version 5.7 or later is recommended.
///
/// ### fish
///
/// Generate a `tool.fish` completion script:
///
/// `tool completion fish > ~/.config/fish/completions/tool.fish`
///
/// ### PowerShell
///
/// Open your profile script with:
///
/// `mkdir -Path (Split-Path -Parent $profile) -ErrorAction SilentlyContinue`
/// `notepad $profile`
///
/// Add the line and save the file:
///
/// `Invoke-Expression -Command $(tool completion powershell | Out-String)`
MitchellBerend marked this conversation as resolved.
Show resolved Hide resolved
Completion {
shell: clap_complete::Shell,

/// If you want to renam the binary this option should be filled with the name you choose
MitchellBerend marked this conversation as resolved.
Show resolved Hide resolved
/// to rename `tool` to.
#[arg(long, value_name = "string")]
rename: Option<String>,
},

/// Sync all tools specified in configuration file or the only one specified in the command line
Sync { tool: Option<String> },

Expand Down
45 changes: 45 additions & 0 deletions src/config/template.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/// This file only holds the template that is used to generate a default .tool.toml.
use clap_complete::Shell;

use crate::sync::db;

pub fn generate_default_config() {
Expand Down Expand Up @@ -44,3 +46,46 @@ fn config_template() -> String {
version = env!("CARGO_PKG_VERSION"),
)
}

// This function can break when clap_complete adds support for a new shell type
Copy link
Owner

Choose a reason for hiding this comment

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

Will it break though? I see that the Shell type has the #[non_exhaustive] pragma. And we also handle all other shells with _.

So, in other words, the compiler won't output any errors if clap_complete adds new shells. They'll simply remain unsupported as now. And people can open new issues to request support for new shells 🙂

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added that comment to clarify why there is a separate function for a simple match statement. Maybe this should include an error message along the lines of:

This shell type is not implemented yet, please go over to https://github.com/chshersh/tool-sync to file an issue about its implementation.

pub fn rename_completion_suggestion(shell: &Shell, bin_name: &str) -> Result<(), RenameError> {
let completion_str: String = match shell {
Shell::Zsh => format!(r##"Generate a `_{bin_name}` completion script and put it somewhere in your `$fpath`:
MitchellBerend marked this conversation as resolved.
Show resolved Hide resolved
`{bin_name} completion zsh --rename {bin_name} > /usr/local/share/zsh/site-functions/_{bin_name}`

Ensure that the following is present in your `~/.zshrc`:

`autoload -U compinit`

`compinit -i`"##),
Shell::Bash => format!(r##"First, ensure that you install `bash-completion` using your package manager.

After, add this to your `~/.bash_profile`:

`eval "$({bin_name} completion bash --rename {bin_name})"`"##),
Shell::Fish => format!(r##"Generate a `tool.fish` completion script:

`{bin_name} completion fish --rename {bin_name} > ~/.config/fish/completions/{bin_name}.fish`"##),
Shell::Elvish => r##"This suggestion is missing, if you use this and know how to implement this please file an issue over at https://github.com/chshersh/tool-sync/issues"##.into(),
MitchellBerend marked this conversation as resolved.
Show resolved Hide resolved
Shell::PowerShell => format!(r##"Open your profile script with:

`mkdir -Path (Split-Path -Parent $profile) -ErrorAction SilentlyContinue`
`notepad $profile`

Add the line and save the file:

`Invoke-Expression -Command $({bin_name} completion powershell --rename {bin_name} | Out-String)`"##),
_ => return Err(RenameError::NewShellFound(shell.to_owned())),
};

eprintln!(
"\n\n############################\n{}\n############################",
completion_str
);

Ok(())
}

pub enum RenameError {
NewShellFound(Shell),
}
33 changes: 31 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ mod install;
mod model;
mod sync;

use clap::Parser;
use clap::{CommandFactory, Parser};
use clap_complete::generate;

use std::path::PathBuf;

use crate::config::cli::{Cli, Command};
use crate::config::template::{rename_completion_suggestion, RenameError};
use crate::infra::err;

const DEFAULT_CONFIG_PATH: &str = ".tool.toml";

pub fn run() {
let cli = Cli::parse();

Expand All @@ -18,6 +23,9 @@ pub fn run() {
let config_path = resolve_config_path(cli.config);

match cli.command {
Command::Completion { shell, rename } => {
generate_completion(shell, rename);
}
Command::DefaultConfig { path } => match path {
true => print_default_path(),
false => config::template::generate_default_config(),
Expand All @@ -27,7 +35,28 @@ pub fn run() {
}
}

const DEFAULT_CONFIG_PATH: &str = ".tool.toml";
fn generate_completion(shell: clap_complete::Shell, rename: Option<String>) {
let mut cmd: clap::Command = Cli::command();
match rename {
Some(cmd_name) => {
generate(shell, &mut cmd, &cmd_name, &mut std::io::stdout());
rename_completion_suggestion(&shell, &cmd_name)
.unwrap_or_else(|e| err::abort_suggest_issue(e));
}
None => {
let cmd_name: String = cmd.get_name().into();
generate(shell, &mut cmd, cmd_name, &mut std::io::stdout());
}
};
}

impl std::fmt::Display for RenameError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
match self {
RenameError::NewShellFound(shell) => write!(f, "[Rename error]: {}", shell),
}
}
}
MitchellBerend marked this conversation as resolved.
Show resolved Hide resolved

fn resolve_config_path(config_path: Option<PathBuf>) -> PathBuf {
match config_path {
Expand Down
7 changes: 7 additions & 0 deletions tests/bash-completion
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
############################
First, ensure that you install `bash-completion` using your package manager.

After, add this to your `~/.bash_profile`:

`eval "$(test-name completion bash --rename test-name)"`
############################
10 changes: 10 additions & 0 deletions tests/zsh-completion
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
############################
Generate a `_test-name` completion script and put it somewhere in your `$fpath`:
`test-name completion zsh --rename test-name > /usr/local/share/zsh/site-functions/_test-name`

Ensure that the following is present in your `~/.zshrc`:

`autoload -U compinit`

`compinit -i`
############################