diff --git a/lib/bashly/libraries/settings/settings.yml b/lib/bashly/libraries/settings/settings.yml index dfbfab3d..5af5f22a 100644 --- a/lib/bashly/libraries/settings/settings.yml +++ b/lib/bashly/libraries/settings/settings.yml @@ -42,6 +42,11 @@ tab_indent: false # `-abc` as if it is `-a -b -c`. compact_short_flags: true +# When true, the generated script will consider any argument in the form of +# `--flag=value` and `-f=value` as if it is `--flag value` and `-f value` +# respectively. +conjoined_flag_args: true + # Set to 'production' or 'development': # env: production Generate a smaller script, without file markers # env: development Generate with file markers diff --git a/lib/bashly/settings.rb b/lib/bashly/settings.rb index c0b6b720..4628df3b 100644 --- a/lib/bashly/settings.rb +++ b/lib/bashly/settings.rb @@ -6,6 +6,7 @@ class << self attr_writer( :commands_dir, :compact_short_flags, + :conjoined_flag_args, :config_path, :lib_dir, :partials_extension, @@ -24,6 +25,10 @@ def compact_short_flags @compact_short_flags ||= get :compact_short_flags end + def conjoined_flag_args + @conjoined_flag_args ||= get :conjoined_flag_args + end + def config_path @config_path ||= get(:config_path) % { source_dir: source_dir } end diff --git a/lib/bashly/views/command/normalize_input.gtx b/lib/bashly/views/command/normalize_input.gtx index d5066375..2a00f71f 100644 --- a/lib/bashly/views/command/normalize_input.gtx +++ b/lib/bashly/views/command/normalize_input.gtx @@ -1,36 +1,7 @@ = view_marker -> normalize_input() { -> local arg flags passthru -> passthru=false -> -> while [[ $# -gt 0 ]]; do -> arg="$1" -> if [[ $passthru == true ]]; then -> input+=("$arg") -> elif [[ $arg =~ ^(--[a-zA-Z0-9_\-]+)=(.+)$ ]]; then -> input+=("${BASH_REMATCH[1]}") -> input+=("${BASH_REMATCH[2]}") -> elif [[ $arg =~ ^(-[a-zA-Z0-9])=(.+)$ ]]; then -> input+=("${BASH_REMATCH[1]}") -> input+=("${BASH_REMATCH[2]}") - -if Settings.compact_short_flags -> elif [[ $arg =~ ^-([a-zA-Z0-9][a-zA-Z0-9]+)$ ]]; then -> flags="${BASH_REMATCH[1]}" -> for ((i = 0; i < ${#flags}; i++)); do -> input+=("-${flags:i:1}") -> done +if Settings.compact_short_flags || Settings.conjoined_flag_args + = render :normalize_input_function +else + = render :normalize_input_simple end - -> elif [[ "$arg" == "--" ]]; then -> passthru=true -> input+=("$arg") -> else -> input+=("$arg") -> fi -> -> shift -> done -> } -> \ No newline at end of file diff --git a/lib/bashly/views/command/normalize_input_function.gtx b/lib/bashly/views/command/normalize_input_function.gtx new file mode 100644 index 00000000..32d79b17 --- /dev/null +++ b/lib/bashly/views/command/normalize_input_function.gtx @@ -0,0 +1,39 @@ += view_marker + +> normalize_input() { +> local arg flags passthru +> passthru=false +> +> while [[ $# -gt 0 ]]; do +> arg="$1" +> if [[ $passthru == true ]]; then +> input+=("$arg") + +if Settings.conjoined_flag_args +> elif [[ $arg =~ ^(--[a-zA-Z0-9_\-]+)=(.+)$ ]]; then +> input+=("${BASH_REMATCH[1]}") +> input+=("${BASH_REMATCH[2]}") +> elif [[ $arg =~ ^(-[a-zA-Z0-9])=(.+)$ ]]; then +> input+=("${BASH_REMATCH[1]}") +> input+=("${BASH_REMATCH[2]}") +end + +if Settings.compact_short_flags +> elif [[ $arg =~ ^-([a-zA-Z0-9][a-zA-Z0-9]+)$ ]]; then +> flags="${BASH_REMATCH[1]}" +> for ((i = 0; i < ${#flags}; i++)); do +> input+=("-${flags:i:1}") +> done +end + +> elif [[ "$arg" == "--" ]]; then +> passthru=true +> input+=("$arg") +> else +> input+=("$arg") +> fi +> +> shift +> done +> } +> \ No newline at end of file diff --git a/lib/bashly/views/command/normalize_input_simple.gtx b/lib/bashly/views/command/normalize_input_simple.gtx new file mode 100644 index 00000000..c9ea0add --- /dev/null +++ b/lib/bashly/views/command/normalize_input_simple.gtx @@ -0,0 +1,6 @@ += view_marker + +> normalize_input() { +> input=("$@") +> } +> \ No newline at end of file diff --git a/schemas/settings.json b/schemas/settings.json index e8e552d0..499f3aba 100644 --- a/schemas/settings.json +++ b/schemas/settings.json @@ -103,7 +103,13 @@ }, "compact_short_flags": { "title": "compact short flags", - "description": "Whether to expand short flags of the current script\nhttps://bashly.dannyb.co/usage/settings/#compact_short_flags", + "description": "Whether to expand -abc to -a -b -c in the input line\nhttps://bashly.dannyb.co/usage/settings/#compact_short_flags", + "type": "boolean", + "default": true + }, + "conjoined_flag_args": { + "title": "conjoined flag args", + "description": "Whether to expand --flag=value to --flag value in the input line\nhttps://bashly.dannyb.co/usage/settings/#conjoined_flag_args", "type": "boolean", "default": true }, diff --git a/spec/approvals/fixtures/no-conjoined-flag-args b/spec/approvals/fixtures/no-conjoined-flag-args new file mode 100644 index 00000000..897c704d --- /dev/null +++ b/spec/approvals/fixtures/no-conjoined-flag-args @@ -0,0 +1,44 @@ +creating user files in src +skipped src/root_command.sh (exists) +created ./cli +run ./cli --help to test your bash script ++ ./cli --user=admin -p=secret -- --region=us-east-1 -static +# this file is located in 'src/root_command.sh' +# you can edit it freely and regenerate (it will not be overwritten) +args: +- ${args[--password]} = secret +- ${args[--user]} = admin + +other_args: +- ${other_args[*]} = --region=us-east-1 -static +- ${other_args[0]} = --region=us-east-1 +- ${other_args[1]} = -static ++ BASHLY_CONJOINED_FLAG_ARGS=no ++ bundle exec bashly generate +creating user files in src +skipped src/root_command.sh (exists) +created ./cli +run ./cli --help to test your bash script ++ ./cli --user admin -p secret --region=us-east-1 +# this file is located in 'src/root_command.sh' +# you can edit it freely and regenerate (it will not be overwritten) +args: +- ${args[--password]} = secret +- ${args[--user]} = admin + +other_args: +- ${other_args[*]} = --region=us-east-1 +- ${other_args[0]} = --region=us-east-1 ++ ./cli --user admin -p secret -- --region=us-east-1 -static +# this file is located in 'src/root_command.sh' +# you can edit it freely and regenerate (it will not be overwritten) +args: +- ${args[--password]} = secret +- ${args[--user]} = admin + +other_args: +- ${other_args[*]} = --region=us-east-1 -static +- ${other_args[0]} = --region=us-east-1 +- ${other_args[1]} = -static ++ ./cli --user=admin -p=secret -- --region=us-east-1 -static +missing required flag: --user, -u NAME diff --git a/spec/approvals/fixtures/no-input-normalization b/spec/approvals/fixtures/no-input-normalization new file mode 100644 index 00000000..7ef57e50 --- /dev/null +++ b/spec/approvals/fixtures/no-input-normalization @@ -0,0 +1,42 @@ +creating user files in src +skipped src/root_command.sh (exists) +created ./cli +run ./cli --help to test your bash script ++ echo '=== bad - since conjoined_flag_args is disabled' +=== bad - since conjoined_flag_args is disabled ++ ./cli --user=admin +missing required flag: --user, -u NAME ++ echo '=== bad - since compact_short_flags is disabled (-fd will be considered as catch_all)' +=== bad - since compact_short_flags is disabled (-fd will be considered as catch_all) ++ ./cli --user admin --password secret -fd +args: +- ${args[--password]} = secret +- ${args[--user]} = admin + +other_args: +- ${other_args[*]} = -fd +- ${other_args[0]} = -fd ++ echo '=== good' +=== good ++ ./cli --user admin -p secret -f -d --region=us-east-1 -static +args: +- ${args[--debug]} = 1 +- ${args[--force]} = 1 +- ${args[--password]} = secret +- ${args[--user]} = admin + +other_args: +- ${other_args[*]} = --region=us-east-1 -static +- ${other_args[0]} = --region=us-east-1 +- ${other_args[1]} = -static ++ echo '=== good' +=== good ++ ./cli --user admin -p secret -- --region=us-east-1 -static +args: +- ${args[--password]} = secret +- ${args[--user]} = admin + +other_args: +- ${other_args[*]} = --region=us-east-1 -static +- ${other_args[0]} = --region=us-east-1 +- ${other_args[1]} = -static diff --git a/spec/fixtures/workspaces/no-conjoined-flag-args/.gitignore b/spec/fixtures/workspaces/no-conjoined-flag-args/.gitignore new file mode 100644 index 00000000..573c0c4f --- /dev/null +++ b/spec/fixtures/workspaces/no-conjoined-flag-args/.gitignore @@ -0,0 +1 @@ +cli diff --git a/spec/fixtures/workspaces/no-conjoined-flag-args/README.md b/spec/fixtures/workspaces/no-conjoined-flag-args/README.md new file mode 100644 index 00000000..104f6d03 --- /dev/null +++ b/spec/fixtures/workspaces/no-conjoined-flag-args/README.md @@ -0,0 +1,2 @@ +This fixture tests that setting `conjoined_flag_args` to `false` indeed ignores +this `--flag=value` and `-f=value` patterns. diff --git a/spec/fixtures/workspaces/no-conjoined-flag-args/src/bashly.yml b/spec/fixtures/workspaces/no-conjoined-flag-args/src/bashly.yml new file mode 100644 index 00000000..704694c0 --- /dev/null +++ b/spec/fixtures/workspaces/no-conjoined-flag-args/src/bashly.yml @@ -0,0 +1,17 @@ +name: cli +help: Sample application +version: 0.1.0 + +catch_all: Server Params + +flags: +- long: --user + short: -u + arg: name + required: true + help: Protocol +- long: --password + short: -p + arg: name + required: true + help: User diff --git a/spec/fixtures/workspaces/no-conjoined-flag-args/src/root_command.sh b/spec/fixtures/workspaces/no-conjoined-flag-args/src/root_command.sh new file mode 100644 index 00000000..91e64307 --- /dev/null +++ b/spec/fixtures/workspaces/no-conjoined-flag-args/src/root_command.sh @@ -0,0 +1,3 @@ +echo "# this file is located in 'src/root_command.sh'" +echo "# you can edit it freely and regenerate (it will not be overwritten)" +inspect_args diff --git a/spec/fixtures/workspaces/no-conjoined-flag-args/test.sh b/spec/fixtures/workspaces/no-conjoined-flag-args/test.sh new file mode 100644 index 00000000..f8db5c84 --- /dev/null +++ b/spec/fixtures/workspaces/no-conjoined-flag-args/test.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +bundle exec bashly generate + +set -x + +# good +./cli --user=admin -p=secret -- --region=us-east-1 -static + +# Use ad-hoc setting through an environment variable +BASHLY_CONJOINED_FLAG_ARGS="no" bundle exec bashly generate + +# good - since conjoined flags is disabled +./cli --user admin -p secret --region=us-east-1 + +# good - since using -- +./cli --user admin -p secret -- --region=us-east-1 -static + +# bad - since using --flag=value +./cli --user=admin -p=secret -- --region=us-east-1 -static diff --git a/spec/fixtures/workspaces/no-input-normalization/.gitignore b/spec/fixtures/workspaces/no-input-normalization/.gitignore new file mode 100644 index 00000000..573c0c4f --- /dev/null +++ b/spec/fixtures/workspaces/no-input-normalization/.gitignore @@ -0,0 +1 @@ +cli diff --git a/spec/fixtures/workspaces/no-input-normalization/README.md b/spec/fixtures/workspaces/no-input-normalization/README.md new file mode 100644 index 00000000..ef954bdd --- /dev/null +++ b/spec/fixtures/workspaces/no-input-normalization/README.md @@ -0,0 +1,3 @@ +This fixture tests that disabling both `conjoined_flag_args` and +`compact_short_flags`, the resulting script uses simple normalization function +(i.e., no normalization at all - just input array assignment). diff --git a/spec/fixtures/workspaces/no-input-normalization/settings.yml b/spec/fixtures/workspaces/no-input-normalization/settings.yml new file mode 100644 index 00000000..e6a675c7 --- /dev/null +++ b/spec/fixtures/workspaces/no-input-normalization/settings.yml @@ -0,0 +1,8 @@ +# When true, the generated script will consider any argument in the form of +# `-abc` as if it is `-a -b -c`. +compact_short_flags: false + +# When true, the generated script will consider any argument in the form of +# `--flag=value` and `-f=value` as if it is `--flag value` and `-f value` +# respectively. +conjoined_flag_args: false diff --git a/spec/fixtures/workspaces/no-input-normalization/src/bashly.yml b/spec/fixtures/workspaces/no-input-normalization/src/bashly.yml new file mode 100644 index 00000000..37060e2d --- /dev/null +++ b/spec/fixtures/workspaces/no-input-normalization/src/bashly.yml @@ -0,0 +1,23 @@ +name: cli +help: Sample application to demonstrate the input normalization settings +version: 0.1.0 + +catch_all: Server Params + +flags: +- long: --user + short: -u + arg: name + required: true + help: Protocol +- long: --password + short: -p + arg: name + required: true + help: User +- long: --debug + short: -d + help: Print debug information +- long: --force + short: -f + help: Overwrite existing data diff --git a/spec/fixtures/workspaces/no-input-normalization/src/root_command.sh b/spec/fixtures/workspaces/no-input-normalization/src/root_command.sh new file mode 100644 index 00000000..dc4e7735 --- /dev/null +++ b/spec/fixtures/workspaces/no-input-normalization/src/root_command.sh @@ -0,0 +1 @@ +inspect_args diff --git a/spec/fixtures/workspaces/no-input-normalization/test.sh b/spec/fixtures/workspaces/no-input-normalization/test.sh new file mode 100644 index 00000000..c27fc32c --- /dev/null +++ b/spec/fixtures/workspaces/no-input-normalization/test.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +bundle exec bashly generate + +set -x + +echo "=== bad - since conjoined_flag_args is disabled" +./cli --user=admin + +echo "=== bad - since compact_short_flags is disabled (-fd will be considered as catch_all)" +./cli --user admin --password secret -fd + +echo "=== good" +./cli --user admin -p secret -f -d --region=us-east-1 -static + +echo "=== good" +./cli --user admin -p secret -- --region=us-east-1 -static