From b062c93497754a93faeb2f4cdc17aab6aad4cc6a Mon Sep 17 00:00:00 2001 From: Danny Ben Shitrit Date: Thu, 7 Dec 2023 07:08:55 +0000 Subject: [PATCH] - Add support for `unique` in repeatable flag args --- examples/render-mandoc/README.md | 2 +- examples/render-mandoc/docs/download.1 | 27 +--------------- examples/repeatable-flag/README.md | 31 ++++++++++++++++++- examples/repeatable-flag/src/bashly.yml | 11 ++++++- examples/repeatable-flag/src/root_command.sh | 2 +- examples/repeatable-flag/test.sh | 1 + lib/bashly/config_validator.rb | 6 ++++ lib/bashly/docs/flag.yml | 11 +++++++ lib/bashly/script/flag.rb | 2 +- lib/bashly/views/flag/case_arg.gtx | 8 +++-- spec/approvals/cli/doc/full | 14 +++++++++ spec/approvals/cli/doc/index | 1 + spec/approvals/examples/repeatable-flag | 13 ++++++++ .../render/mandoc/render-1-download.1 | 2 -- spec/approvals/libraries_validation/libraries | 1 + .../flag_unique_without_repeatable_and_arg | 1 + spec/bashly/library_source_config_spec.rb | 2 +- spec/fixtures/script/validations.yml | 8 +++++ 18 files changed, 107 insertions(+), 36 deletions(-) create mode 100644 spec/approvals/libraries_validation/libraries create mode 100644 spec/approvals/validations/flag_unique_without_repeatable_and_arg diff --git a/examples/render-mandoc/README.md b/examples/render-mandoc/README.md index fcaf2215..2a78e659 100644 --- a/examples/render-mandoc/README.md +++ b/examples/render-mandoc/README.md @@ -102,7 +102,7 @@ ISSUE TRACKER AUTHORS Lana Lang. -Version 0.1.0 November 2023 download(1) +Version 0.1.0 December 2023 download(1) ```` diff --git a/examples/render-mandoc/docs/download.1 b/examples/render-mandoc/docs/download.1 index bd9a2656..589a33c7 100644 --- a/examples/render-mandoc/docs/download.1 +++ b/examples/render-mandoc/docs/download.1 @@ -1,60 +1,35 @@ -.\" Automatically generated by Pandoc 3.1.6 +.\" Automatically generated by Pandoc 3.1.9 .\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} .TH "download" "1" "December 2023" "Version 0.1.0" "Sample application" -.hy .SH NAME -.PP \f[B]download\f[R] - Sample application .SH SYNOPSIS -.PP \f[B]download\f[R] SOURCE [TARGET...] OPTIONS .SH DESCRIPTION -.PP Sample application .SH ARGUMENTS .SS SOURCE -.PP Source to download from .IP \[bu] 2 \f[I]Required\f[R] .IP \[bu] 2 Allowed Values: \f[B]server1, server2\f[R] .SS TARGET -.PP Target filename (default: same as source) .IP \[bu] 2 \f[I]Repeatable\f[R] .SH OPTIONS .SS --force, -f -.PP Overwrite existing files .SS --debug, -d -.PP Show debug information .SH DEPENDENCIES .SS aws-cli -.PP Download from .SH SEE ALSO -.PP \f[B]docker\f[R](1), \f[B]docker-compose.yml\f[R](5) .SH ISSUE TRACKER -.PP Report issues at .SH AUTHORS Lana Lang. diff --git a/examples/repeatable-flag/README.md b/examples/repeatable-flag/README.md index 14db6b2d..8e805242 100644 --- a/examples/repeatable-flag/README.md +++ b/examples/repeatable-flag/README.md @@ -36,6 +36,15 @@ flags: # needs to be converted to an array with `eval "data=(${args[--data]})"` repeatable: true +- long: --path + short: -p + arg: location + help: Specify one or more paths + repeatable: true + + # Setting this to true will ignore repeating arguments that are not unique + unique: true + - long: --verbose short: -v help: Set verbosity level @@ -47,6 +56,7 @@ flags: examples: - download -d one -d "two three" -vvv +- download -d one -p /usr/bin -p /tmp ```` ## `src/root_command.sh` @@ -61,7 +71,7 @@ for i in "${data[@]}"; do done # The --verbose arg will contain the number of times it was used by the user -verbose=${args[--verbose]} +verbose=${args[--verbose]:-1} echo "" echo "Verbosity level: $verbose" echo "" @@ -87,6 +97,9 @@ Options: --data, -d DATA (required) (repeatable) Provide data values + --path, -p LOCATION (repeatable) + Specify one or more paths + --verbose, -v (repeatable) Set verbosity level @@ -98,6 +111,7 @@ Options: Examples: download -d one -d "two three" -vvv + download -d one -p /usr/bin -p /tmp @@ -119,5 +133,20 @@ args: ```` +### `$ ./download -d one --path /bin --path /usr/lib --path /bin` + +````shell +Data elements: +one + +Verbosity level: 1 + +args: +- ${args[--data]} = "one" +- ${args[--path]} = "/bin" "/usr/lib" + + +```` + diff --git a/examples/repeatable-flag/src/bashly.yml b/examples/repeatable-flag/src/bashly.yml index 7896aa5d..dadad55b 100644 --- a/examples/repeatable-flag/src/bashly.yml +++ b/examples/repeatable-flag/src/bashly.yml @@ -15,6 +15,15 @@ flags: # needs to be converted to an array with `eval "data=(${args[--data]})"` repeatable: true +- long: --path + short: -p + arg: location + help: Specify one or more paths + repeatable: true + + # Setting this to true will ignore repeating arguments that are not unique + unique: true + - long: --verbose short: -v help: Set verbosity level @@ -26,4 +35,4 @@ flags: examples: - download -d one -d "two three" -vvv - +- download -d one -p /usr/bin -p /tmp diff --git a/examples/repeatable-flag/src/root_command.sh b/examples/repeatable-flag/src/root_command.sh index 539c25fe..773f5c37 100644 --- a/examples/repeatable-flag/src/root_command.sh +++ b/examples/repeatable-flag/src/root_command.sh @@ -7,7 +7,7 @@ for i in "${data[@]}"; do done # The --verbose arg will contain the number of times it was used by the user -verbose=${args[--verbose]} +verbose=${args[--verbose]:-1} echo "" echo "Verbosity level: $verbose" echo "" diff --git a/examples/repeatable-flag/test.sh b/examples/repeatable-flag/test.sh index 741bb4ce..bb12668b 100644 --- a/examples/repeatable-flag/test.sh +++ b/examples/repeatable-flag/test.sh @@ -8,3 +8,4 @@ bashly generate ./download -h ./download -d one -d "two three" -vvv +./download -d one --path /bin --path /usr/lib --path /bin diff --git a/lib/bashly/config_validator.rb b/lib/bashly/config_validator.rb index 033db37a..fb9f4a92 100644 --- a/lib/bashly/config_validator.rb +++ b/lib/bashly/config_validator.rb @@ -140,6 +140,12 @@ def assert_flag(key, value) if value['completions'] assert value['arg'], "#{key}.completions does not make sense without nub`arg`" end + + if value['unique'] + condition = value['arg'] && value['repeatable'] + assert condition, "#{key}.unique does not make sense without nub`arg` and nub`repeatable`" + end + end def assert_env_var(key, value) diff --git a/lib/bashly/docs/flag.yml b/lib/bashly/docs/flag.yml index 0e6dd3a8..9bd4c0f4 100644 --- a/lib/bashly/docs/flag.yml +++ b/lib/bashly/docs/flag.yml @@ -162,6 +162,17 @@ flag.short: arg: name help: Repository user name +flag.unique: + help: Specify that the arguments provided by this repeatable flag must be unique. When this is set to `true`, non-unique values will be ignored. + url: https://bashly.dannyb.co/configuration/flag/#unique + example: |- + flags: + - long: --path + arg: location + help: Set one or more paths + repeatable: true + unique: true + flag.validate: help: Apply custom validation functions. Must be accompanied by `arg`. diff --git a/lib/bashly/script/flag.rb b/lib/bashly/script/flag.rb index 5c524422..ebaf22c5 100644 --- a/lib/bashly/script/flag.rb +++ b/lib/bashly/script/flag.rb @@ -7,7 +7,7 @@ class << self def option_keys @option_keys ||= %i[ allowed arg completions conflicts default help long repeatable - required short validate private + required short unique validate private ] end end diff --git a/lib/bashly/views/flag/case_arg.gtx b/lib/bashly/views/flag/case_arg.gtx index 1498f330..f4d2018f 100644 --- a/lib/bashly/views/flag/case_arg.gtx +++ b/lib/bashly/views/flag/case_arg.gtx @@ -6,8 +6,12 @@ if repeatable > if [[ -z ${args['{{ name }}']+x} ]]; then > args['{{ name }}']="\"$2\"" - > else - > args['{{ name }}']="${args[{{ name }}]} \"$2\"" + if unique + > elif [[ ! "${args['{{ name }}']}" =~ "\"$2\"" ]]; then + else + > else + end + > args['{{ name }}']="${args['{{ name }}']} \"$2\"" > fi else diff --git a/spec/approvals/cli/doc/full b/spec/approvals/cli/doc/full index ccf6a461..f00a8f58 100644 --- a/spec/approvals/cli/doc/full +++ b/spec/approvals/cli/doc/full @@ -738,6 +738,20 @@ flag.short See https://bashly.dannyb.co/configuration/flag/#short +flag.unique + + Specify that the arguments provided by this repeatable flag must be unique. + When this is set to true, non-unique values will be ignored. + + flags: + - long: --path + arg: location + help: Set one or more paths + repeatable: true + unique: true + + See https://bashly.dannyb.co/configuration/flag/#unique + flag.validate Apply custom validation functions. Must be accompanied by arg. diff --git a/spec/approvals/cli/doc/index b/spec/approvals/cli/doc/index index 8ed0d70d..0f10911c 100644 --- a/spec/approvals/cli/doc/index +++ b/spec/approvals/cli/doc/index @@ -46,4 +46,5 @@ flag.private flag.repeatable flag.required flag.short +flag.unique flag.validate diff --git a/spec/approvals/examples/repeatable-flag b/spec/approvals/examples/repeatable-flag index 922c5e37..a31b315f 100644 --- a/spec/approvals/examples/repeatable-flag +++ b/spec/approvals/examples/repeatable-flag @@ -15,6 +15,9 @@ Options: --data, -d DATA (required) (repeatable) Provide data values + --path, -p LOCATION (repeatable) + Specify one or more paths + --verbose, -v (repeatable) Set verbosity level @@ -26,6 +29,7 @@ Options: Examples: download -d one -d "two three" -vvv + download -d one -p /usr/bin -p /tmp + ./download -d one -d 'two three' -vvv Data elements: @@ -37,3 +41,12 @@ Verbosity level: 3 args: - ${args[--data]} = "one" "two three" - ${args[--verbose]} = 3 ++ ./download -d one --path /bin --path /usr/lib --path /bin +Data elements: +one + +Verbosity level: 1 + +args: +- ${args[--data]} = "one" +- ${args[--path]} = "/bin" "/usr/lib" diff --git a/spec/approvals/libraries/render/mandoc/render-1-download.1 b/spec/approvals/libraries/render/mandoc/render-1-download.1 index 6b370e92..d925ee9a 100644 --- a/spec/approvals/libraries/render/mandoc/render-1-download.1 +++ b/spec/approvals/libraries/render/mandoc/render-1-download.1 @@ -23,10 +23,8 @@ OPTIONS Overwrite existing files EXAMPLES - download example.com download example.com ./output -f - Version 0.1.0 MONTH YEAR ... APPNAME diff --git a/spec/approvals/libraries_validation/libraries b/spec/approvals/libraries_validation/libraries new file mode 100644 index 00000000..6cdb85c6 --- /dev/null +++ b/spec/approvals/libraries_validation/libraries @@ -0,0 +1 @@ +Nothing raised \ No newline at end of file diff --git a/spec/approvals/validations/flag_unique_without_repeatable_and_arg b/spec/approvals/validations/flag_unique_without_repeatable_and_arg new file mode 100644 index 00000000..345f9e17 --- /dev/null +++ b/spec/approvals/validations/flag_unique_without_repeatable_and_arg @@ -0,0 +1 @@ +# \ No newline at end of file diff --git a/spec/bashly/library_source_config_spec.rb b/spec/bashly/library_source_config_spec.rb index 9b4739e5..f41b8efd 100644 --- a/spec/bashly/library_source_config_spec.rb +++ b/spec/bashly/library_source_config_spec.rb @@ -1,5 +1,5 @@ describe LibrarySourceConfig do - fixtures = Dir['spec/fixtures/libraries_errors/*.yml'] + fixtures = Dir['spec/fixtures/libraries/*.yml'] subject { described_class.new path } let(:path) { 'spec/fixtures/libraries/libraries.yml' } diff --git a/spec/fixtures/script/validations.yml b/spec/fixtures/script/validations.yml index 9991104c..1cc306df 100644 --- a/spec/fixtures/script/validations.yml +++ b/spec/fixtures/script/validations.yml @@ -248,6 +248,14 @@ allowed: [one, two] completions: [] +:flag_unique_without_repeatable_and_arg: + name: invalid + help: flag must have an arg and be repeatable when using unique + flags: + - long: --ssh + repeatable: true + unique: true + :root_alias: name: invalid help: root cannot have alias