diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 5f224a6..0b544d9 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -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" diff --git a/cli/src/cli/generate/completion.rs b/cli/src/cli/generate/completion.rs index 8aedd76..a70b488 100644 --- a/cli/src/cli/generate/completion.rs +++ b/cli/src/cli/generate/completion.rs @@ -20,6 +20,12 @@ pub struct Completion { #[clap(short, long)] file: Option, + /// 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" @@ -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(), diff --git a/cli/usage.usage.kdl b/cli/usage.usage.kdl index e24a25c..7c860f8 100644 --- a/cli/usage.usage.kdl +++ b/cli/usage.usage.kdl @@ -52,6 +52,10 @@ cmd "generate" subcommand_required=true { flag "-f --file" help="A .usage.kdl spec file to use for generating completions" { arg "" } + 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 "" + } flag "--usage-cmd" help="A command which generates a usage spec e.g.: `mycli --usage` or `mycli completion usage` Defaults to \"$bin --usage\"" { arg "" } diff --git a/docs/cli/reference/commands.json b/docs/cli/reference/commands.json index 6e6dda0..8784796 100644 --- a/docs/cli/reference/commands.json +++ b/docs/cli/reference/commands.json @@ -245,6 +245,23 @@ "hide": false } }, + { + "name": "usage-bin", + "usage": "--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": "", + "required": true, + "hide": false + } + }, { "name": "usage-cmd", "usage": "--usage-cmd ", diff --git a/docs/cli/reference/generate/completion.md b/docs/cli/reference/generate/completion.md index 4ba93ae..ba28647 100644 --- a/docs/cli/reference/generate/completion.md +++ b/docs/cli/reference/generate/completion.md @@ -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 ` + +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 ` A command which generates a usage spec e.g.: `mycli --usage` or `mycli completion usage` Defaults to "$bin --usage" diff --git a/lib/src/complete/bash.rs b/lib/src/complete/bash.rs index 09f5e66..d69aedc 100644 --- a/lib/src/complete/bash.rs +++ b/lib/src/complete/bash.rs @@ -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 { @@ -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"# @@ -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 @@ -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, @@ -82,6 +84,7 @@ 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()), @@ -89,8 +92,8 @@ mod tests { 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, diff --git a/lib/src/complete/fish.rs b/lib/src/complete/fish.rs index 3def09f..866f037 100644 --- a/lib/src/complete/fish.rs +++ b/lib/src/complete/fish.rs @@ -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 { @@ -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"# @@ -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") @@ -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, @@ -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()), @@ -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, diff --git a/lib/src/complete/mod.rs b/lib/src/complete/mod.rs index 6613920..f00f076 100644 --- a/lib/src/complete/mod.rs +++ b/lib/src/complete/mod.rs @@ -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, diff --git a/lib/src/complete/zsh.rs b/lib/src/complete/zsh.rs index 3696bbd..fbf55ba 100644 --- a/lib/src/complete/zsh.rs +++ b/lib/src/complete/zsh.rs @@ -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 { @@ -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"#, @@ -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 }} @@ -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, @@ -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()), @@ -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, diff --git a/mise.toml b/mise.toml index 7e8002a..d3e41cd 100644 --- a/mise.toml +++ b/mise.toml @@ -107,3 +107,6 @@ run = "cargo insta test --accept" [task_config] includes = ['tasks'] + +[tasks.install-dev] +run = "cargo install --path cli --debug"