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 all 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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,31 @@ 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


The following example will assume you have renamed the binary to `random-name`
and you are using bash. You can run the following command to get completion for
the current session of your shell.

```shell
random-name completion bash --rename random-name
```

If you want to have these autocomplete functions in the next (and the ones after
that) as well you can add the following to your `~/.bashrc`:

```shell
eval "$(random-name completion bash --rename random-name)"
```


### Quick start

`tool-sync` has a command to generate a default configuration with examples and
Expand Down
86 changes: 86 additions & 0 deletions src/completion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! This file contains all logic revolving the generation of the shell completion script

use clap_complete::Shell;

// This function can break when clap_complete adds support for a new shell type
pub fn rename_completion_suggestion(shell: &Shell, bin_name: &str) -> Result<(), RenameError> {
let completion_str: String = match shell {
Shell::Zsh => zsh_completion_help(bin_name),
Shell::Bash => bash_completion_help(bin_name),
Shell::Fish => fish_completion_help(bin_name),
Shell::Elvish => elvish_completion_help(bin_name),
Shell::PowerShell => powershell_completion_help(bin_name),
_ => return Err(RenameError::NewShellFound(shell.to_owned())),
};

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

Ok(())
}

pub enum RenameError {
NewShellFound(Shell),
}

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),
}
}
}

//##################//
// Helper functions //
//##################//

fn zsh_completion_help(bin_name: &str) -> String {
format!(
r##"Generate a `_{bin_name}` completion script and put it somewhere in your `$fpath`:
`{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`"##
)
}

fn bash_completion_help(bin_name: &str) -> String {
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})"`"##
)
}

fn fish_completion_help(bin_name: &str) -> String {
format!(
r##"Generate a `tool.fish` completion script:

`{bin_name} completion fish --rename {bin_name} > ~/.config/fish/completions/{bin_name}.fish`"##
)
}

fn elvish_completion_help(_bin_name: &str) -> String {
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()
}

fn powershell_completion_help(bin_name: &str) -> String {
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)`"##
)
}
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 rename the binary this option should be filled with the name you choose
/// 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
26 changes: 24 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
mod completion;
mod config;
mod infra;
mod install;
mod model;
mod sync;

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

use std::path::PathBuf;

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

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

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

Expand All @@ -18,6 +24,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 +36,20 @@ 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());
}
};
}

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`
############################