diff --git a/examples/repeatable-arg/README.md b/examples/repeatable-arg/README.md index 547b6689..53920b58 100644 --- a/examples/repeatable-arg/README.md +++ b/examples/repeatable-arg/README.md @@ -34,6 +34,9 @@ args: # needs to be converted to an array with `eval "data=(${args[file]})"` repeatable: true + # Setting unique to true will ignore non-unique repeating values + unique: true + examples: - upcase README.md LICENSE - upcase *.md @@ -125,5 +128,23 @@ args: ```` +### `$ ./upcase file1 file2 file1` + +````shell + +files: + path: file1: + content: content of file1 + upcase: CONTENT OF FILE1 + path: file2: + content: content of file2 + upcase: CONTENT OF FILE2 + +args: +- ${args[file]} = "file1" "file2" + + +```` + diff --git a/examples/repeatable-arg/src/bashly.yml b/examples/repeatable-arg/src/bashly.yml index 9c9c0c9e..de60bdec 100644 --- a/examples/repeatable-arg/src/bashly.yml +++ b/examples/repeatable-arg/src/bashly.yml @@ -13,6 +13,9 @@ args: # needs to be converted to an array with `eval "data=(${args[file]})"` repeatable: true + # Setting unique to true will ignore non-unique repeating values + unique: true + examples: - upcase README.md LICENSE - upcase *.md diff --git a/examples/repeatable-arg/test.sh b/examples/repeatable-arg/test.sh index f1ccc9c8..642b243d 100644 --- a/examples/repeatable-arg/test.sh +++ b/examples/repeatable-arg/test.sh @@ -9,3 +9,4 @@ bashly generate ./upcase -h ./upcase file1 ./upcase file* +./upcase file1 file2 file1 diff --git a/lib/bashly/config_validator.rb b/lib/bashly/config_validator.rb index e1fd661b..da55a0c9 100644 --- a/lib/bashly/config_validator.rb +++ b/lib/bashly/config_validator.rb @@ -95,12 +95,17 @@ def assert_arg(key, value) assert_optional_string "#{key}.validate", value['validate'] assert_boolean "#{key}.required", value['required'] assert_boolean "#{key}.repeatable", value['repeatable'] + assert_boolean "#{key}.unique", value['unique'] assert_array "#{key}.allowed", value['allowed'], of: :string refute value['name'].match(/^-/), "#{key}.name must not start with '-'" refute value['required'] && value['default'], "#{key} cannot have both nub`required` and nub`default`" + + if value['unique'] + assert value['repeatable'], "#{key}.unique does not make sense without nub`repeatable`" + end end def assert_flag(key, value) @@ -143,8 +148,7 @@ def assert_flag(key, value) end if value['unique'] - condition = value['arg'] && value['repeatable'] - assert condition, "#{key}.unique does not make sense without nub`arg` and nub`repeatable`" + assert value['arg'] && value['repeatable'], "#{key}.unique does not make sense without nub`arg` and nub`repeatable`" end end diff --git a/lib/bashly/script/argument.rb b/lib/bashly/script/argument.rb index 0b8aefa9..2e417456 100644 --- a/lib/bashly/script/argument.rb +++ b/lib/bashly/script/argument.rb @@ -4,7 +4,7 @@ class Argument < Base class << self def option_keys @option_keys ||= %i[ - allowed default help name repeatable required validate + allowed default help name repeatable required unique validate ] end end diff --git a/lib/bashly/views/command/parse_requirements_case_repeatable.gtx b/lib/bashly/views/command/parse_requirements_case_repeatable.gtx index 35d0a4c6..b78484c8 100644 --- a/lib/bashly/views/command/parse_requirements_case_repeatable.gtx +++ b/lib/bashly/views/command/parse_requirements_case_repeatable.gtx @@ -7,9 +7,17 @@ args.each do |arg| if arg.repeatable > args['{{ arg.name }}']="\"$1\"" > shift - > else - > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\"" - > shift + if arg.unique + > elif [[ ! "${args['{{ arg.name }}']}" =~ \"$1\" ]]; then + > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\"" + > shift + > else + > shift + else + > else + > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\"" + > shift + end else > args['{{ arg.name }}']=$1 diff --git a/spec/approvals/examples/repeatable-arg b/spec/approvals/examples/repeatable-arg index e99745d1..91ca79dc 100644 --- a/spec/approvals/examples/repeatable-arg +++ b/spec/approvals/examples/repeatable-arg @@ -47,3 +47,15 @@ files: args: - ${args[file]} = "file1" "file2" ++ ./upcase file1 file2 file1 + +files: + path: file1: + content: content of file1 + upcase: CONTENT OF FILE1 + path: file2: + content: content of file2 + upcase: CONTENT OF FILE2 + +args: +- ${args[file]} = "file1" "file2" diff --git a/spec/approvals/validations/arg_unique_without_repeatable b/spec/approvals/validations/arg_unique_without_repeatable new file mode 100644 index 00000000..e1c83442 --- /dev/null +++ b/spec/approvals/validations/arg_unique_without_repeatable @@ -0,0 +1 @@ +# \ No newline at end of file diff --git a/spec/fixtures/script/validations.yml b/spec/fixtures/script/validations.yml index bfedf331..b36d41da 100644 --- a/spec/fixtures/script/validations.yml +++ b/spec/fixtures/script/validations.yml @@ -42,6 +42,14 @@ - name: target help: Target filename +:arg_unique_without_repeatable: + name: invalid + help: arg must be repeatable when using unique + args: + - name: target + help: Target filename + unique: true + :command_catch_all_type: name: invalid help: catch_all must be boolean, string, or hash