diff --git a/Cargo.lock b/Cargo.lock index ac585d74..c1a7a02e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,7 +43,6 @@ dependencies = [ "predicates", "roff", "rstest", - "semver", "serde", "serde_json", "shell-words", diff --git a/Cargo.toml b/Cargo.toml index 6771f4e9..b488bbef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ num_cpus = "1.16" threadpool = "1.8" base64 = "0.22" natord = "1.0" -semver = "1.0" roff = "0.2" [dev-dependencies] diff --git a/src/bin/argc/completions/completion.sh b/src/bin/argc/completions/completion.sh deleted file mode 100644 index dba9af16..00000000 --- a/src/bin/argc/completions/completion.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -# @describe An elegant command-line argument parser - https://github.com/sigoden/argc - -# @option --argc-eval~ Use `eval "$(argc --argc-eval "$0" "$@")"` -# @option --argc-create~ Create a boilerplate argcfile -# @option --argc-build Generate bashscript without argc dependency -# @option --argc-mangen Generate man pages -# @option --argc-completions~[`_choice_completion`] Generate shell completion scripts -# @option --argc-compgen~[`_choice_compgen`] Generate completion candidates -# @option --argc-export Export command line definitions as json -# @option --argc-parallel~ Run functions in parallel -# @flag --argc-script-path Print current argcfile path -# @flag --argc-shell-path Print current shell path -# @flag --argc-help Print help information -# @flag --argc-version Print version information - -_choice_completion() { :; } -_choice_compgen() { :; } - -command eval "$(argc --argc-eval "$0" "$@")" diff --git a/src/bin/argc/main.rs b/src/bin/argc/main.rs index d161c6cc..78df1dcd 100644 --- a/src/bin/argc/main.rs +++ b/src/bin/argc/main.rs @@ -1,4 +1,3 @@ -mod completions; mod parallel; use anyhow::{anyhow, bail, Context, Result}; @@ -15,7 +14,6 @@ use std::{ }; use which::which; -const COMPLETION_SCRIPT: &str = include_str!("completions/completion.sh"); const ARGC_SCRIPT_NAMES: [&str; 6] = [ "Argcfile.sh", "Argcfile", @@ -124,7 +122,8 @@ fn run() -> Result { Some(v) => v.parse()?, None => bail!("Usage: argc --argc-completions [CMDS]..."), }; - let script = crate::completions::generate(shell, &args[3..]); + let commands = [vec!["argc".to_string()], args[3..].to_vec()].concat(); + let script = argc::generate_completions(shell, &commands); print!("{}", script); } "--argc-compgen" => { @@ -218,7 +217,8 @@ fn run_compgen(mut args: Vec) -> Option<()> { .unwrap_or_default(); let output = if &args[4] == "argc" && (args[3].is_empty() || args[5].starts_with("--argc")) { let cmd_args = &args[4..]; - argc::compgen(shell, "", COMPLETION_SCRIPT, cmd_args, no_color).ok()? + let script = get_argc_script_code(); + argc::compgen(shell, "", &script, cmd_args, no_color).ok()? } else if args[3].is_empty() { let cmd_args = &args[4..]; argc::compgen(shell, "", "# @arg path*", cmd_args, no_color).ok()? @@ -282,6 +282,39 @@ USAGE: ) } +fn get_argc_script_code() -> String { + let about = concat!( + env!("CARGO_PKG_DESCRIPTION"), + " - ", + env!("CARGO_PKG_REPOSITORY") + ); + format!( + r###"#!/usr/bin/env bash + +# @describe {about} + +# @option --argc-eval~ Use `eval "$(argc --argc-eval "$0" "$@")"` +# @option --argc-create~ Create a boilerplate argcfile +# @option --argc-build Generate bashscript without argc dependency +# @option --argc-mangen Generate man pages +# @option --argc-completions~[`_choice_completion`] Generate shell completion scripts +# @option --argc-compgen~[`_choice_compgen`] Generate completion candidates +# @option --argc-export Export command line definitions as json +# @option --argc-parallel~ Run functions in parallel +# @flag --argc-script-path Print current argcfile path +# @flag --argc-shell-path Print current shell path +# @flag --argc-help Print help information +# @flag --argc-version Print version information + +_choice_completion() {{ :; }} +_choice_compgen() {{ :; }} + +eval "$(argc --argc-eval "$0" "$@")" + +"### + ) +} + fn get_argc_version() -> String { let name = env!("CARGO_CRATE_NAME"); let version = env!("CARGO_PKG_VERSION"); diff --git a/src/bin/argc/completions/argc.bash b/src/completions/argc.bash similarity index 100% rename from src/bin/argc/completions/argc.bash rename to src/completions/argc.bash diff --git a/src/bin/argc/completions/argc.elv b/src/completions/argc.elv similarity index 100% rename from src/bin/argc/completions/argc.elv rename to src/completions/argc.elv diff --git a/src/bin/argc/completions/argc.fish b/src/completions/argc.fish similarity index 100% rename from src/bin/argc/completions/argc.fish rename to src/completions/argc.fish diff --git a/src/bin/argc/completions/argc.nu b/src/completions/argc.nu similarity index 100% rename from src/bin/argc/completions/argc.nu rename to src/completions/argc.nu diff --git a/src/bin/argc/completions/argc.ps1 b/src/completions/argc.ps1 similarity index 100% rename from src/bin/argc/completions/argc.ps1 rename to src/completions/argc.ps1 diff --git a/src/bin/argc/completions/argc.xsh b/src/completions/argc.xsh similarity index 84% rename from src/bin/argc/completions/argc.xsh rename to src/completions/argc.xsh index 9b9a46a2..3bf49542 100644 --- a/src/bin/argc/completions/argc.xsh +++ b/src/completions/argc.xsh @@ -30,4 +30,8 @@ def _argc_completer(context): return result -_add_one_completer('argc', _argc_completer, 'start') +if 'ARGC_XONSH_SCRIPTS' not in __xonsh__.env: + __xonsh__.env['ARGC_XONSH_SCRIPTS'] = [] + +if 'argc' not in __xonsh__.completers: + _add_one_completer('argc', _argc_completer, 'start') diff --git a/src/bin/argc/completions/argc.zsh b/src/completions/argc.zsh similarity index 100% rename from src/bin/argc/completions/argc.zsh rename to src/completions/argc.zsh diff --git a/src/bin/argc/completions/mod.rs b/src/completions/mod.rs similarity index 50% rename from src/bin/argc/completions/mod.rs rename to src/completions/mod.rs index 8c487808..d61714c0 100644 --- a/src/bin/argc/completions/mod.rs +++ b/src/completions/mod.rs @@ -1,6 +1,4 @@ -use argc::Shell; -use semver::Version; -use std::env; +use crate::Shell; const BASH_SCRIPT: &str = include_str!("argc.bash"); const ELVISH_SCRIPT: &str = include_str!("argc.elv"); @@ -10,70 +8,44 @@ const POWERSHELL_SCRIPT: &str = include_str!("argc.ps1"); const XONSH_SCRIPT: &str = include_str!("argc.xsh"); const ZSH_SCRIPT: &str = include_str!("argc.zsh"); -pub fn generate(shell: Shell, args: &[String]) -> String { +pub fn generate_completions(shell: Shell, commands: &[String]) -> String { match shell { Shell::Bash => { - let commands = [vec!["argc".to_string()], args.to_vec()].concat(); let commands = commands.join(" "); BASH_SCRIPT.replace("__COMMANDS__", &commands) } Shell::Elvish => { - let commands = [vec!["argc".to_string()], args.to_vec()].concat(); let commands = commands - .into_iter() + .iter() .map(|v| format!("\"{v}\"")) .collect::>() .join(" "); ELVISH_SCRIPT.replace("__COMMANDS__", &commands) } Shell::Fish => { - let commands = [vec!["argc".to_string()], args.to_vec()].concat(); let commands = commands.join(" "); FISH_SCRIPT.replace("__COMMANDS__", &commands) } Shell::Generic => String::new(), - Shell::Nushell => { - if env::var("NU_VERSION") - .ok() - .and_then(|v| Version::parse(&v).ok()) - .map(|v| v < Version::new(0, 89, 0)) - .unwrap_or_default() - { - // https://github.com/nushell/nushell/pull/11289 - NUSHELL_SCRIPT.replace("...$args", "$args") - } else { - NUSHELL_SCRIPT.to_string() - } - } + Shell::Nushell => NUSHELL_SCRIPT.to_string(), Shell::Powershell => { - let commands = [vec!["argc".to_string()], args.to_vec()].concat(); let commands = commands - .into_iter() + .iter() .map(|v| format!("\"{v}\"")) .collect::>() .join(","); POWERSHELL_SCRIPT.replace("__COMMANDS__", &commands) } Shell::Xonsh => { - let mut cmds = args.to_vec(); - let scripts_env_var = "ARGC_XONSH_SCRIPTS"; - if env::var(scripts_env_var).is_ok() { - format!("__xonsh__.env['{scripts_env_var}'].extend({cmds:?})") - } else { - cmds.insert(0, "argc".to_string()); - let code = format!("__xonsh__.env['{scripts_env_var}'] = {cmds:?}"); - format!("{XONSH_SCRIPT}\n{code}") - } + format!("{XONSH_SCRIPT}\n__xonsh__.env['ARGC_XONSH_SCRIPTS'].extend({commands:?})") } Shell::Zsh => { - let commands = [vec!["argc".to_string()], args.to_vec()].concat(); let commands = commands.join(" "); ZSH_SCRIPT.replace("__COMMANDS__", &commands) } Shell::Tcsh => { - let commands = [vec!["argc".to_string()], args.to_vec()].concat(); commands - .into_iter() + .iter() .map(|v| format!(r#"complete {v} 'p@*@`echo "$COMMAND_LINE'"''"'" | xargs argc --argc-compgen tcsh ""`@@';{}"#, "\n")) .collect::>().join("") } diff --git a/src/lib.rs b/src/lib.rs index 224b537d..aca0bc7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ mod argc_value; mod build; mod command; mod compgen; +mod completions; mod mangen; mod matcher; mod param; @@ -13,6 +14,7 @@ pub use argc_value::ArgcValue; pub use build::build; pub use command::CommandValue; pub use compgen::{compgen, Shell}; +pub use completions::generate_completions; pub use mangen::mangen; pub use param::{ChoiceValue, DefaultValue, EnvValue, FlagOptionValue, PositionalValue}; diff --git a/tests/compgen.rs b/tests/compgen.rs index 4db1d54a..779537c2 100644 --- a/tests/compgen.rs +++ b/tests/compgen.rs @@ -1073,7 +1073,7 @@ mod filedir { vec!["prog", "--oa", "./src/"], vec!["prog", "--oa", "C"], vec!["prog", "--oa", "./C"], - vec!["prog", "--ob", "src/bin/argc/completions/ar"], + vec!["prog", "--ob", "src/completions/ar"], vec!["prog", "--oc", "src/"], ], TEST_SHELL @@ -1091,7 +1091,7 @@ mod filedir { vec!["prog", "--oa", ".\\src\\"], vec!["prog", "--oa", "C"], vec!["prog", "--oa", ".\\C"], - vec!["prog", "--ob", "src\\bin\\argc\\completions\\ar"], + vec!["prog", "--ob", "src\\completions/ar"], vec!["prog", "--oc", "src\\"], ], TEST_SHELL diff --git a/tests/snapshots/integration__compgen__filedir__cd.snap b/tests/snapshots/integration__compgen__filedir__cd.snap index 2f5ae244..a8561d49 100644 --- a/tests/snapshots/integration__compgen__filedir__cd.snap +++ b/tests/snapshots/integration__compgen__filedir__cd.snap @@ -8,6 +8,7 @@ bin/ 0 bin/ blue bold build.rs 1 build.rs default command/ 0 command/ blue bold compgen.rs 1 compgen.rs default +completions/ 0 completions/ blue bold lib.rs 1 lib.rs default mangen.rs 1 mangen.rs default matcher.rs 1 matcher.rs default @@ -21,6 +22,7 @@ utils.rs 1 utils.rs default --oa=build.rs 1 build.rs default --oa=command/ 0 command/ blue bold --oa=compgen.rs 1 compgen.rs default +--oa=completions/ 0 completions/ blue bold --oa=lib.rs 1 lib.rs default --oa=mangen.rs 1 mangen.rs default --oa=matcher.rs 1 matcher.rs default @@ -34,6 +36,7 @@ bin/ 0 bin/ blue bold build.rs: 0 build.rs: default command/ 0 command/ blue bold compgen.rs: 0 compgen.rs: default +completions/ 0 completions/ blue bold lib.rs: 0 lib.rs: default mangen.rs: 0 mangen.rs: default matcher.rs: 0 matcher.rs: default @@ -47,11 +50,10 @@ foo=bin/ 0 bin/ blue bold foo=build.rs 1 build.rs default foo=command/ 0 command/ blue bold foo=compgen.rs 1 compgen.rs default +foo=completions/ 0 completions/ blue bold foo=lib.rs 1 lib.rs default foo=mangen.rs 1 mangen.rs default foo=matcher.rs 1 matcher.rs default foo=param.rs 1 param.rs default foo=parser.rs 1 parser.rs default foo=utils.rs 1 utils.rs default - - diff --git a/tests/snapshots/integration__compgen__filedir__cd_win.snap b/tests/snapshots/integration__compgen__filedir__cd_win.snap index 1f30cdad..d5c6d282 100644 --- a/tests/snapshots/integration__compgen__filedir__cd_win.snap +++ b/tests/snapshots/integration__compgen__filedir__cd_win.snap @@ -8,6 +8,7 @@ expression: data .\build.rs 1 .\build.rs 39 .\command\ 0 .\command\ 1;34 .\compgen.rs 1 .\compgen.rs 39 +.\completions\ 0 .\completions\ 1;34 .\lib.rs 1 .\lib.rs 39 .\mangen.rs 1 .\mangen.rs 39 .\matcher.rs 1 .\matcher.rs 39 @@ -21,6 +22,7 @@ expression: data .\build.rs: 0 .\build.rs: 39 .\command\ 0 .\command\ 1;34 .\compgen.rs: 0 .\compgen.rs: 39 +.\completions\ 0 .\completions\ 1;34 .\lib.rs: 0 .\lib.rs: 39 .\mangen.rs: 0 .\mangen.rs: 39 .\matcher.rs: 0 .\matcher.rs: 39 @@ -34,6 +36,7 @@ expression: data --oa=.\build.rs 1 .\build.rs 39 --oa=.\command\ 0 .\command\ 1;34 --oa=.\compgen.rs 1 .\compgen.rs 39 +--oa=.\completions\ 0 .\completions\ 1;34 --oa=.\lib.rs 1 .\lib.rs 39 --oa=.\mangen.rs 1 .\mangen.rs 39 --oa=.\matcher.rs 1 .\matcher.rs 39 @@ -47,11 +50,10 @@ foo=.\bin\ 0 .\bin\ 1;34 foo=.\build.rs 1 .\build.rs 39 foo=.\command\ 0 .\command\ 1;34 foo=.\compgen.rs 1 .\compgen.rs 39 +foo=.\completions\ 0 .\completions\ 1;34 foo=.\lib.rs 1 .\lib.rs 39 foo=.\mangen.rs 1 .\mangen.rs 39 foo=.\matcher.rs 1 .\matcher.rs 39 foo=.\param.rs 1 .\param.rs 39 foo=.\parser.rs 1 .\parser.rs 39 foo=.\utils.rs 1 .\utils.rs 39 - - diff --git a/tests/snapshots/integration__compgen__filedir__value_name.snap b/tests/snapshots/integration__compgen__filedir__value_name.snap index 508f3833..252b53ec 100644 --- a/tests/snapshots/integration__compgen__filedir__value_name.snap +++ b/tests/snapshots/integration__compgen__filedir__value_name.snap @@ -8,6 +8,7 @@ src/bin/ 0 bin/ blue bold src/build.rs 1 build.rs default src/command/ 0 command/ blue bold src/compgen.rs 1 compgen.rs default +src/completions/ 0 completions/ blue bold src/lib.rs 1 lib.rs default src/mangen.rs 1 mangen.rs default src/matcher.rs 1 matcher.rs default @@ -25,6 +26,7 @@ src/parser.rs 1 parser.rs default ./src/build.rs 1 build.rs default ./src/command/ 0 command/ blue bold ./src/compgen.rs 1 compgen.rs default +./src/completions/ 0 completions/ blue bold ./src/lib.rs 1 lib.rs default ./src/mangen.rs 1 mangen.rs default ./src/matcher.rs 1 matcher.rs default @@ -40,11 +42,10 @@ Cargo.toml 1 Cargo.toml default ./Cargo.lock 1 Cargo.lock default ./Cargo.toml 1 Cargo.toml default -************ COMPGEN `prog --ob src/bin/argc/completions/ar` ************ -src/bin/argc/completions/argc.zsh 1 argc.zsh default +************ COMPGEN `prog --ob src/completions/ar` ************ +src/completions/argc.zsh 1 argc.zsh default ************ COMPGEN `prog --oc src/` ************ src/bin/ 0 bin/ blue bold src/command/ 0 command/ blue bold - - +src/completions/ 0 completions/ blue bold diff --git a/tests/snapshots/integration__compgen__filedir__value_name_win.snap b/tests/snapshots/integration__compgen__filedir__value_name_win.snap index ca4498cc..2ac18918 100644 --- a/tests/snapshots/integration__compgen__filedir__value_name_win.snap +++ b/tests/snapshots/integration__compgen__filedir__value_name_win.snap @@ -8,6 +8,7 @@ src\bin\ 0 bin\ 1;34 src\build.rs 1 build.rs 39 src\command\ 0 command\ 1;34 src\compgen.rs 1 compgen.rs 39 +src\completions\ 0 completions\ 1;34 src\lib.rs 1 lib.rs 39 src\mangen.rs 1 mangen.rs 39 src\matcher.rs 1 matcher.rs 39 @@ -25,6 +26,7 @@ src\parser.rs 1 parser.rs 39 .\src\build.rs 1 build.rs 39 .\src\command\ 0 command\ 1;34 .\src\compgen.rs 1 compgen.rs 39 +.\src\completions\ 0 completions\ 1;34 .\src\lib.rs 1 lib.rs 39 .\src\mangen.rs 1 mangen.rs 39 .\src\matcher.rs 1 matcher.rs 39 @@ -40,11 +42,10 @@ src\parser.rs 1 parser.rs 39 .\Cargo.lock 1 Cargo.lock 39 .\Cargo.toml 1 Cargo.toml 39 -************ COMPGEN `prog --ob src\bin\argc\completions\ar` ************ -src\bin\argc\completions\argc.zsh 1 argc.zsh 39 +************ COMPGEN `prog --ob src\completions/ar` ************ +src\completions\ar 0 src\completions\ar 39 ************ COMPGEN `prog --oc src\` ************ src\bin\ 0 bin\ 1;34 src\command\ 0 command\ 1;34 - - +src\completions\ 0 completions\ 1;34