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..ea2e3f6d 100644
--- a/lib/bashly/config_validator.rb
+++ b/lib/bashly/config_validator.rb
@@ -118,6 +118,7 @@ def assert_flag(key, value)
assert_boolean "#{key}.private", value['private']
assert_boolean "#{key}.repeatable", value['repeatable']
+ assert_boolean "#{key}.unique", value['unique']
assert_boolean "#{key}.required", value['required']
assert_array "#{key}.allowed", value['allowed'], of: :string
assert_array "#{key}.conflicts", value['conflicts'], of: :string
@@ -140,6 +141,11 @@ 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..aa9e0d4f 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/files_array b/spec/approvals/libraries_validation/files_array
index f78264a3..b8d858f7 100644
--- a/spec/approvals/libraries_validation/files_array
+++ b/spec/approvals/libraries_validation/files_array
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ No newline at end of file
diff --git a/spec/approvals/libraries_validation/files_source b/spec/approvals/libraries_validation/files_source
index 21f98c90..71b194f4 100644
--- a/spec/approvals/libraries_validation/files_source
+++ b/spec/approvals/libraries_validation/files_source
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ No newline at end of file
diff --git a/spec/approvals/libraries_validation/files_target b/spec/approvals/libraries_validation/files_target
index 67580069..b404790b 100644
--- a/spec/approvals/libraries_validation/files_target
+++ b/spec/approvals/libraries_validation/files_target
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ No newline at end of file
diff --git a/spec/approvals/libraries_validation/handler_string b/spec/approvals/libraries_validation/handler_string
index 4fb9d1db..72c40f45 100644
--- a/spec/approvals/libraries_validation/handler_string
+++ b/spec/approvals/libraries_validation/handler_string
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ No newline at end of file
diff --git a/spec/approvals/libraries_validation/help_string b/spec/approvals/libraries_validation/help_string
index 8d40fb91..d7ae66c7 100644
--- a/spec/approvals/libraries_validation/help_string
+++ b/spec/approvals/libraries_validation/help_string
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ No newline at end of file
diff --git a/spec/approvals/libraries_validation/message_string b/spec/approvals/libraries_validation/message_string
index f9ecbea5..e933a42d 100644
--- a/spec/approvals/libraries_validation/message_string
+++ b/spec/approvals/libraries_validation/message_string
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ No newline at end of file
diff --git a/spec/approvals/libraries_validation/root_hash b/spec/approvals/libraries_validation/root_hash
index bf1c0a67..623ccc9c 100644
--- a/spec/approvals/libraries_validation/root_hash
+++ b/spec/approvals/libraries_validation/root_hash
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ No newline at end of file
diff --git a/spec/approvals/libraries_validation/usage_string b/spec/approvals/libraries_validation/usage_string
index 877e9c1e..63b157da 100644
--- a/spec/approvals/libraries_validation/usage_string
+++ b/spec/approvals/libraries_validation/usage_string
@@ -1 +1 @@
-#
\ No newline at end of file
+#
\ 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..da03f8f5 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_validation/*.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