Skip to content

Commit

Permalink
fix: allow overriding usage in case of conflict (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx authored Dec 14, 2024
1 parent afcdb68 commit befe2f6
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 12 deletions.
2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ name = "usage_cli"
path = "src/lib.rs"

[dependencies]
clap = { version = "4", features = ["derive", "string"] }
clap = { version = "4", features = ["derive", "string", "env"] }
clap_usage = { workspace = true }
contracts = "0.6"
env_logger = "0.11"
Expand Down
7 changes: 7 additions & 0 deletions cli/src/cli/generate/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ pub struct Completion {
#[clap(short, long)]
file: Option<PathBuf>,

/// Override the bin used for calling back to usage-cli
///
/// You may need to set this if you have a different bin named "usage"
#[clap(long, default_value = "usage", env = "JDX_USAGE_BIN")]
usage_bin: String,

/// A command which generates a usage spec
/// e.g.: `mycli --usage` or `mycli completion usage`
/// Defaults to "$bin --usage"
Expand All @@ -45,6 +51,7 @@ impl Completion {
false => None,
};
let opts = CompleteOptions {
usage_bin: self.usage_bin.clone(),
shell: self.shell.clone(),
bin: self.bin.clone(),
cache_key: self.cache_key.clone(),
Expand Down
4 changes: 4 additions & 0 deletions cli/usage.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ cmd "generate" subcommand_required=true {
flag "-f --file" help="A .usage.kdl spec file to use for generating completions" {
arg "<FILE>"
}
flag "--usage-bin" help="Override the bin used for calling back to usage-cli" {
long_help "Override the bin used for calling back to usage-cli\n\nYou may need to set this if you have a different bin named \"usage\""
arg "<USAGE_BIN>"
}
flag "--usage-cmd" help="A command which generates a usage spec e.g.: `mycli --usage` or `mycli completion usage` Defaults to \"$bin --usage\"" {
arg "<USAGE_CMD>"
}
Expand Down
17 changes: 17 additions & 0 deletions docs/cli/reference/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,23 @@
"hide": false
}
},
{
"name": "usage-bin",
"usage": "--usage-bin <USAGE_BIN>",
"help": "Override the bin used for calling back to usage-cli",
"help_long": "Override the bin used for calling back to usage-cli\n\nYou may need to set this if you have a different bin named \"usage\"",
"help_first_line": "Override the bin used for calling back to usage-cli",
"short": [],
"long": ["usage-bin"],
"hide": false,
"global": false,
"arg": {
"name": "USAGE_BIN",
"usage": "<USAGE_BIN>",
"required": true,
"hide": false
}
},
{
"name": "usage-cmd",
"usage": "--usage-cmd <USAGE_CMD>",
Expand Down
6 changes: 6 additions & 0 deletions docs/cli/reference/generate/completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ A cache key to use for storing the results of calling the CLI with --usage-cmd

A .usage.kdl spec file to use for generating completions

### `--usage-bin <USAGE_BIN>`

Override the bin used for calling back to usage-cli

You may need to set this if you have a different bin named "usage"

### `--usage-cmd <USAGE_CMD>`

A command which generates a usage spec e.g.: `mycli --usage` or `mycli completion usage` Defaults to "$bin --usage"
Expand Down
11 changes: 7 additions & 4 deletions lib/src/complete/bash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::complete::CompleteOptions;
use heck::ToSnakeCase;

pub fn complete_bash(opts: &CompleteOptions) -> String {
let usage_bin = &opts.usage_bin;
let bin = &opts.bin;
let bin_snake = bin.to_snake_case();
let spec_variable = if let Some(cache_key) = &opts.cache_key {
Expand All @@ -16,9 +17,9 @@ pub fn complete_bash(opts: &CompleteOptions) -> String {
};
let mut out = vec![format!(
r#"_{bin_snake}() {{
if ! command -v usage &> /dev/null; then
if ! command -v {usage_bin} &> /dev/null; then
echo >&2
echo "Error: usage CLI not found. This is required for completions to work in {bin}." >&2
echo "Error: {usage_bin} CLI not found. This is required for completions to work in {bin}." >&2
echo "See https://usage.jdx.dev for more information." >&2
return 1
fi"#
Expand Down Expand Up @@ -48,7 +49,7 @@ __USAGE_EOF__"#,
local cur prev words cword was_split comp_args
_comp_initialize -n : -- "$@" || return
# shellcheck disable=SC2207
_comp_compgen -- -W "$(usage complete-word --shell bash -s "${{{spec_variable}}}" --cword="$cword" -- "${{words[@]}}")"
_comp_compgen -- -W "$({usage_bin} complete-word --shell bash -s "${{{spec_variable}}}" --cword="$cword" -- "${{words[@]}}")"
_comp_ltrim_colon_completions "$cur"
# shellcheck disable=SC2181
if [[ $? -ne 0 ]]; then
Expand All @@ -74,6 +75,7 @@ mod tests {
#[test]
fn test_complete_bash() {
assert_snapshot!(complete_bash(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "bash".to_string(),
bin: "mycli".to_string(),
cache_key: None,
Expand All @@ -82,15 +84,16 @@ mod tests {
include_bash_completion_lib: false,
}));
assert_snapshot!(complete_bash(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "bash".to_string(),
bin: "mycli".to_string(),
cache_key: Some("1.2.3".to_string()),
spec: None,
usage_cmd: Some("mycli complete --usage".to_string()),
include_bash_completion_lib: false,
}));

assert_snapshot!(complete_bash(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "bash".to_string(),
bin: "mycli".to_string(),
cache_key: None,
Expand Down
12 changes: 8 additions & 4 deletions lib/src/complete/fish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::complete::CompleteOptions;
use heck::ToSnakeCase;

pub fn complete_fish(opts: &CompleteOptions) -> String {
let usage_bin = &opts.usage_bin;
let bin = &opts.bin;
let bin_snake = bin.to_snake_case();
let spec_variable = if let Some(cache_key) = &opts.cache_key {
Expand All @@ -11,10 +12,10 @@ pub fn complete_fish(opts: &CompleteOptions) -> String {
};
let mut out = vec![format!(
r#"
# if "usage" is not installed show an error
if ! command -v usage &> /dev/null
# if "{usage_bin}" is not installed show an error
if ! command -v {usage_bin} &> /dev/null
echo >&2
echo "Error: usage CLI not found. This is required for completions to work in {bin}." >&2
echo "Error: {usage_bin} CLI not found. This is required for completions to work in {bin}." >&2
echo "See https://usage.jdx.dev for more information." >&2
return 1
end"#
Expand Down Expand Up @@ -45,7 +46,7 @@ set {spec_variable} '{spec_escaped}'"#
}

out.push(format!(
r#"complete -xc {bin} -a '(usage complete-word --shell fish -s "${spec_variable}" -- (commandline -cop) (commandline -t))'"#
r#"complete -xc {bin} -a '({usage_bin} complete-word --shell fish -s "${spec_variable}" -- (commandline -cop) (commandline -t))'"#
));

out.join("\n")
Expand All @@ -60,6 +61,7 @@ mod tests {
#[test]
fn test_complete_fish() {
assert_snapshot!(complete_fish(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "fish".to_string(),
bin: "mycli".to_string(),
cache_key: None,
Expand All @@ -68,6 +70,7 @@ mod tests {
include_bash_completion_lib: false,
}));
assert_snapshot!(complete_fish(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "fish".to_string(),
bin: "mycli".to_string(),
cache_key: Some("1.2.3".to_string()),
Expand All @@ -76,6 +79,7 @@ mod tests {
include_bash_completion_lib: false,
}));
assert_snapshot!(complete_fish(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "fish".to_string(),
bin: "mycli".to_string(),
cache_key: None,
Expand Down
1 change: 1 addition & 0 deletions lib/src/complete/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod fish;
mod zsh;

pub struct CompleteOptions {
pub usage_bin: String,
pub shell: String,
pub bin: String,
pub cache_key: Option<String>,
Expand Down
10 changes: 7 additions & 3 deletions lib/src/complete/zsh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::complete::CompleteOptions;
use heck::ToSnakeCase;

pub fn complete_zsh(opts: &CompleteOptions) -> String {
let usage_bin = &opts.usage_bin;
let bin = &opts.bin;
let bin_snake = bin.to_snake_case();
let spec_variable = if let Some(cache_key) = &opts.cache_key {
Expand Down Expand Up @@ -37,9 +38,9 @@ _{bin_snake}() {{
typeset -A opt_args
local curcontext="$curcontext" spec cache_policy
if ! command -v usage &> /dev/null; then
if ! command -v {usage_bin} &> /dev/null; then
echo >&2
echo "Error: usage CLI not found. This is required for completions to work in {bin}." >&2
echo "Error: {usage_bin} CLI not found. This is required for completions to work in {bin}." >&2
echo "See https://usage.jdx.dev for more information." >&2
return 1
fi"#,
Expand Down Expand Up @@ -73,7 +74,7 @@ __USAGE_EOF__"#,

out.push(format!(
r#"
_arguments "*: :(($(usage complete-word --shell zsh -s "$spec" -- "${{words[@]}}" )))"
_arguments "*: :(($({usage_bin} complete-word --shell zsh -s "$spec" -- "${{words[@]}}" )))"
return 0
}}
Expand Down Expand Up @@ -102,6 +103,7 @@ mod tests {
#[test]
fn test_complete_zsh() {
assert_snapshot!(complete_zsh(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "zsh".to_string(),
bin: "mycli".to_string(),
cache_key: None,
Expand All @@ -110,6 +112,7 @@ mod tests {
include_bash_completion_lib: false,
}));
assert_snapshot!(complete_zsh(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "zsh".to_string(),
bin: "mycli".to_string(),
cache_key: Some("1.2.3".to_string()),
Expand All @@ -118,6 +121,7 @@ mod tests {
include_bash_completion_lib: false,
}));
assert_snapshot!(complete_zsh(&CompleteOptions {
usage_bin: "usage".to_string(),
shell: "zsh".to_string(),
bin: "mycli".to_string(),
cache_key: None,
Expand Down
3 changes: 3 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,6 @@ run = "cargo insta test --accept"

[task_config]
includes = ['tasks']

[tasks.install-dev]
run = "cargo install --path cli --debug"

0 comments on commit befe2f6

Please sign in to comment.