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

feat: make build scripts compatible with Bash strict mode #329

Merged
merged 7 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Each of these examples demonstrates one aspect or feature of argc.
- [multiline.sh](./multiline.sh) - how to use multiline help text.
- [nested-commands](./nested-commands.sh) - how to use nested commands.
- [hooks.sh](./hooks.sh) - how to use argc hooks.
- [strict.sh](./strict.sh) - how to use strict mode
- [parallel.sh](./parallel.sh) - how to use `--argc-parallel`.

- [args.sh](./args.sh) - all kinds of `@arg`.
Expand Down
25 changes: 25 additions & 0 deletions examples/strict.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

set -eu


# @flag --fa
# @option --oa
# @option --of*, multi-occurs + comma-separated list
# @option --oda=a default
# @option --oca[a|b] choice
# @option --ofa[`_choice_fn`] choice from fn
# @option --oxa~ capture all remaining args

main() {
( set -o posix ; set ) | grep ^argc_
echo "${argc__fn:-}" "$@"
}

_choice_fn() {
echo abc
echo def
echo ghi
}

eval "$(argc --argc-eval "$0" "$@")"
46 changes: 23 additions & 23 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ _argc_match_positionals() {
local takes=0
if [[ "${params[param_index]}" -eq 1 ]]; then
if [[ $param_index -eq 0 ]] &&
[[ $_argc_dash -gt 0 ]] &&
[[ ${_argc_dash:-} -gt 0 ]] &&
[[ $params_len -eq 2 ]] &&
[[ "${params[$((param_index + 1))]}" -eq 1 ]] \
; then
takes=$_argc_dash
takes=${_argc_dash:-}
else
local arg_diff=$((args_len - arg_index)) param_diff=$((params_len - param_index))
if [[ $arg_diff -gt $param_diff ]]; then
Expand Down Expand Up @@ -121,15 +121,15 @@ _argc_split_positionals() {
"_argc_require_params",
r#"
_argc_require_params() {
local message="$1" missed_envs item name render_name
local message="$1" missed_envs="" item name render_name
for item in "${@:2}"; do
name="${item%%:*}"
render_name="${item##*:}"
if [[ -z "${!name}" ]]; then
if [[ -z "${!name:-}" ]]; then
missed_envs="$missed_envs"$'\n'" $render_name"
fi
done
if [[ -n "$missed_envs" ]]; then
if [[ -n "${missed_envs}" ]]; then
_argc_die "$message$missed_envs"
fi
}
Expand All @@ -139,8 +139,8 @@ _argc_require_params() {
"_argc_validate_choices",
r#"
_argc_validate_choices() {
local render_name="$1" raw_choices="$2" choices item choice concated_choices
IFS=$'\n' read -d '' -r -a choices <<<"$raw_choices"
local render_name="$1" raw_choices="$2" choices item choice concated_choices=""
IFS=$'\n' read -r -d '' -a choices <<<"$raw_choices" || true
for choice in "${choices[@]}"; do
if [[ -z "$concated_choices" ]]; then
concated_choices="$choice"
Expand Down Expand Up @@ -246,7 +246,7 @@ fn build_root(cmd: &Command, wrap_width: Option<usize>) -> String {
# Modifying it manually is not recommended

_argc_run() {{
if [[ "$1" == "___internal___" ]]; then
if [[ "${{1:-}}" == "___internal___" ]]; then
_argc_die "error: no supported param"
fi
argc__args=("$(basename "$0" .sh)" "$@")
Expand All @@ -255,7 +255,7 @@ _argc_run() {{
_argc_len="${{#argc__args[@]}}"{dotenv}
_argc_tools=()
_argc_parse{require_tools}{before_hook}
if [ -n "$argc__fn" ]; then
if [ -n "${{argc__fn:-}}" ]; then
$argc__fn "${{argc__positionals[@]}}"{after_hook}
fi
}}
Expand Down Expand Up @@ -414,7 +414,7 @@ fn build_parse(cmd: &Command, suffix: &str) -> String {
parses.push(format!(
r#"
help)
local help_arg="${{argc__args[$((_argc_index + 1))]}}"
local help_arg="${{argc__args[$((_argc_index + 1))]:-}}"
case "$help_arg" in{subcmd_usages}
"")
_argc_usage{suffix}
Expand Down Expand Up @@ -508,7 +508,7 @@ _argc_parse{suffix}() {{
case "$_argc_key" in{combined_case}
esac
done{flag_option_bind_envs}{required_flag_options}{require_tools}
if [[ -n "$_argc_action" ]]; then
if [[ -n "${{_argc_action:-}}" ]]; then
$_argc_action
else{handle}
fi
Expand Down Expand Up @@ -540,7 +540,7 @@ fn build_parse_flag_option(param: &FlagOptionParam, signs: &str) -> String {
_argc_die "error: flag \`{long_name}\` don't accept any value"
fi
_argc_index=$((_argc_index + 1))
if [[ -n "${var_name}" ]]; then
if [[ -n "${{{var_name}:-}}" ]]; then
{variant}
else
{var_name}=1
Expand Down Expand Up @@ -569,8 +569,8 @@ fn build_parse_flag_option(param: &FlagOptionParam, signs: &str) -> String {
} else {
format!(
r#"
if [[ -z "${var_name}" ]]; then
{var_name}="${{_argc_take_args_values[0]}}"
if [[ -z "${{{var_name}:-}}" ]]; then
{var_name}="${{_argc_take_args_values[0]:-}}"
else
_argc_die "error: the argument \`{long_name}\` cannot be used multiple times"
fi"#
Expand Down Expand Up @@ -627,7 +627,7 @@ fn build_handle(cmd: &Command, suffix: &str) -> String {
};
let run_help = format!(
r#"
if [[ "${{argc__positionals[0]}}" == "help" ]] && [[ "${{#argc__positionals[@]}}" -eq 1 ]]; then
if [[ "${{argc__positionals[0]:-}}" == "help" ]] && [[ "${{#argc__positionals[@]}}" -eq 1 ]]; then
_argc_usage{suffix}
fi"#
);
Expand Down Expand Up @@ -746,7 +746,7 @@ fn build_positionals(cmd: &Command) -> String {
};
format!(
r#"
IFS=: read -r values_index values_size <<<"${{_argc_match_positionals_values[{index}]}}"
IFS=: read -r values_index values_size <<<"${{_argc_match_positionals_values[{index}]:-}}"
if [[ -n "$values_index" ]]; then{variant}{choice}{bind_env}{handle_nonexist}
fi"#
)
Expand All @@ -769,7 +769,7 @@ fn build_flag_option_bind_envs(cmd: &Command) -> String {
let code = if param.is_flag() {
format!(
r#"
if [[ -z "${var_name}" ]] && [[ -n "${env_name}" ]]; then
if [[ -z "${{{var_name}:-}}" ]] && [[ -n "${{{env_name}:-}}" ]]; then
if _argc_check_bool {env_name} "{render_name}"; then
{var_name}=1
fi
Expand All @@ -779,7 +779,7 @@ fn build_flag_option_bind_envs(cmd: &Command) -> String {
let handle_bind_env = build_handle_bind_env(param, &render_name, 2);
format!(
r#"
if [[ -z "${var_name}" ]] && [[ -n "${env_name}" ]]; then{handle_bind_env}
if [[ -z "${{{var_name}:-}}" ]] && [[ -n "${{{env_name}:-}}" ]]; then{handle_bind_env}
fi"#
)
};
Expand All @@ -796,7 +796,7 @@ fn build_positional_bind_env(param: &PositionalParam) -> String {
let handle_bind_env = build_handle_bind_env(param, &param.render_notation(), 3);
format!(
r#"
elif [[ -n "${env_name}" ]]; then{handle_bind_env}
elif [[ -n "${{{env_name}:-}}" ]]; then{handle_bind_env}
argc__positionals+=("${{_argc_env_values[@]}}")"#
)
}
Expand Down Expand Up @@ -881,7 +881,7 @@ fn build_default_flag_options(cmd: &Command) -> String {
let default = build_default(&var_name, param.default(), 3);
format!(
r#"
if [[ -z "${var_name}" ]]; then{default}
if [[ -z "${{{var_name}:-}}" ]]; then{default}
fi"#
)
})
Expand Down Expand Up @@ -933,19 +933,19 @@ fn build_envs(cmd: &Command) -> String {
} else if default.is_empty() {
format!(
r#"
if [[ -n "${var_name}" ]]; then{choice}
if [[ -n "${{{var_name}:-}}" ]]; then{choice}
fi"#
)
} else if choice.is_empty() {
format!(
r#"
if [[ -z "${var_name}" ]]; then{default}
if [[ -z "${{{var_name}:-}}" ]]; then{default}
fi"#
)
} else {
format!(
r#"
if [[ -z "${var_name}" ]]; then{default}
if [[ -z "${{{var_name}:-}}" ]]; then{default}
else{choice}
fi"#
)
Expand Down
25 changes: 20 additions & 5 deletions tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,34 @@ fn build_stdout() {
}

#[test]
fn build_outpath() {
let path = locate_script("examples/demo.sh");
fn run_build() {
let path = locate_script("examples/strict.sh");
let tmpdir = tmpdir();
let outpath = tmpdir.join("demo.sh");
let outpath = tmpdir.join("strict.sh");
Command::cargo_bin("argc")
.unwrap()
.arg("--argc-build")
.arg(&path)
.arg(&outpath)
.assert()
.success();
let script = std::fs::read_to_string(&outpath).unwrap();
assert!(script.contains("# ARGC-BUILD"));

// Command::cargo_bin("argc")
// .unwrap()
// .arg("--argc-run")
// .arg(&outpath)
// .args([
// "--fa",
// "--oa",
// "oa1",
// "--of=of1,of2",
// "--oca=a",
// "--ofa",
// "abc",
// ])
// .assert()
// .stdout(predicates::str::contains("argc__fn=main"))
// .success();
}

#[test]
Expand Down