bashly 1.1.3 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44036d2bc4aabc216e7d60a788bfce201f71ad8230f4b44df5cb9d201500a0a5
4
- data.tar.gz: 30a1fb4efdafb7c305f0b1f1dcb38eaf8e05ed4a613b73c2ebd501cfe319bde7
3
+ metadata.gz: 17cea196efbe1bc65a6639258fe902503b75656c6a759ea5434a12d6a53d4529
4
+ data.tar.gz: 5e86d08e594250889bc351d5d6113bcfc40f8ec04ba39f72a7f19eec8329c7af
5
5
  SHA512:
6
- metadata.gz: 78109f5a7b1273746d0db4dfcce037862ee9964333c001b4db5bec3997074ec70aab849e7783c12cf1337b4c5086747e8591c94ed9d52e612bf1e281cdfff772
7
- data.tar.gz: 141f6ad7bf8a1a932f8d76774737dde4ef61f7222adc48c3932eba460d187dde4a194e9ee5771b3136bd699410e50874ecaa2f668a51684662c506f33013820c
6
+ metadata.gz: ade5312408fc08533dc6992673744920e941e142c09c9f05e58e66a08a6dfccfab100707cee319cb2ec388e60f9a73ae8ff735e8217c8f91820fc5e2e22af886
7
+ data.tar.gz: cf7f6da0438551ba2a10ed5c224d7ad6ac6b02d8675dca57c8ac01eb465e705a19bd2c3d1812b61b54ab52a433b5ce228b7f3b579e9de24f71c6f512caad1202
@@ -4,7 +4,7 @@ require 'tty-markdown'
4
4
  module Bashly
5
5
  module Commands
6
6
  class Render < Base
7
- help 'Render the bashly data structure using cutsom templates'
7
+ help 'Render the bashly data structure using custom templates'
8
8
 
9
9
  usage 'bashly render SOURCE TARGET [--watch --show PATH]'
10
10
  usage 'bashly render SOURCE --about'
@@ -31,7 +31,7 @@ module Bashly
31
31
  return unless of
32
32
 
33
33
  value.each_with_index do |val, i|
34
- send "assert_#{of}".to_sym, "#{key}[#{i}]", val
34
+ send :"assert_#{of}", "#{key}[#{i}]", val
35
35
  end
36
36
  end
37
37
 
@@ -91,16 +91,25 @@ module Bashly
91
91
  assert_hash key, value, keys: Script::Argument.option_keys
92
92
  assert_string "#{key}.name", value['name']
93
93
  assert_optional_string "#{key}.help", value['help']
94
- assert_optional_string "#{key}.default", value['default']
94
+ assert_string_or_array "#{key}.default", value['default']
95
95
  assert_optional_string "#{key}.validate", value['validate']
96
96
  assert_boolean "#{key}.required", value['required']
97
97
  assert_boolean "#{key}.repeatable", value['repeatable']
98
+ assert_boolean "#{key}.unique", value['unique']
98
99
 
99
100
  assert_array "#{key}.allowed", value['allowed'], of: :string
100
101
 
101
102
  refute value['name'].match(/^-/), "#{key}.name must not start with '-'"
102
103
 
103
104
  refute value['required'] && value['default'], "#{key} cannot have both nub`required` and nub`default`"
105
+
106
+ if value['unique']
107
+ assert value['repeatable'], "#{key}.unique does not make sense without nub`repeatable`"
108
+ end
109
+
110
+ if value['default'].is_a? Array
111
+ assert value['repeatable'], "#{key}.default array does not make sense without nub`repeatable`"
112
+ end
104
113
  end
105
114
 
106
115
  def assert_flag(key, value)
@@ -113,11 +122,12 @@ module Bashly
113
122
  assert_optional_string "#{key}.short", value['short']
114
123
  assert_optional_string "#{key}.help", value['help']
115
124
  assert_optional_string "#{key}.arg", value['arg']
116
- assert_optional_string "#{key}.default", value['default']
125
+ assert_string_or_array "#{key}.default", value['default']
117
126
  assert_optional_string "#{key}.validate", value['validate']
118
127
 
119
128
  assert_boolean "#{key}.private", value['private']
120
129
  assert_boolean "#{key}.repeatable", value['repeatable']
130
+ assert_boolean "#{key}.unique", value['unique']
121
131
  assert_boolean "#{key}.required", value['required']
122
132
  assert_array "#{key}.allowed", value['allowed'], of: :string
123
133
  assert_array "#{key}.conflicts", value['conflicts'], of: :string
@@ -140,6 +150,15 @@ module Bashly
140
150
  if value['completions']
141
151
  assert value['arg'], "#{key}.completions does not make sense without nub`arg`"
142
152
  end
153
+
154
+ if value['unique']
155
+ assert value['arg'] && value['repeatable'],
156
+ "#{key}.unique does not make sense without nub`arg` and nub`repeatable`"
157
+ end
158
+
159
+ if value['default'].is_a? Array
160
+ assert value['repeatable'], "#{key}.default array does not make sense without nub`repeatable`"
161
+ end
143
162
  end
144
163
 
145
164
  def assert_env_var(key, value)
@@ -149,6 +168,9 @@ module Bashly
149
168
  assert_optional_string "#{key}.default", value['default']
150
169
  assert_boolean "#{key}.required", value['required']
151
170
  assert_boolean "#{key}.private", value['private']
171
+ assert_array "#{key}.allowed", value['allowed'], of: :string
172
+
173
+ refute value['required'] && value['default'], "#{key} cannot have both nub`required` and nub`default`"
152
174
  end
153
175
 
154
176
  def assert_command(key, value)
@@ -201,6 +223,16 @@ module Bashly
201
223
  refute repeatable_arg, "#{key}.catch_all makes no sense with repeatable arg (#{repeatable_arg})"
202
224
  end
203
225
 
226
+ if value['args']
227
+ repeatable_args = value['args'].count { |a| a['repeatable'] }
228
+ assert repeatable_args < 2, "#{key}.args cannot have more than one repeatable args"
229
+
230
+ if repeatable_args == 1
231
+ assert value['args'].last['repeatable'],
232
+ "#{key}.args cannot contain a repeatable arg unless it is the last one"
233
+ end
234
+ end
235
+
204
236
  if value['expose']
205
237
  assert value['commands'], "#{key}.expose makes no sense without nub`commands`"
206
238
  end
@@ -41,9 +41,10 @@ flag.arg:
41
41
  url: https://bashly.dannyb.co/configuration/flag/#arg
42
42
  example: |-
43
43
  flags:
44
- - long: --ssh
45
- short: -s
46
- help: Clone using SSH
44
+ - long: --user
45
+ short: -u
46
+ arg: name
47
+ help: Specify the user name
47
48
 
48
49
  flag.completions:
49
50
  help: Specify a list of additional completion suggestions when used in conjunction with `bashly add completions`. Must be accompanied by `arg`.
@@ -161,6 +162,17 @@ flag.short:
161
162
  arg: name
162
163
  help: Repository user name
163
164
 
165
+ flag.unique:
166
+ 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.
167
+ url: https://bashly.dannyb.co/configuration/flag/#unique
168
+ example: |-
169
+ flags:
170
+ - long: --path
171
+ arg: location
172
+ help: Set one or more paths
173
+ repeatable: true
174
+ unique: true
175
+
164
176
  flag.validate:
165
177
  help: Apply custom validation functions. Must be accompanied by `arg`.
166
178
 
@@ -34,5 +34,6 @@ missing_required_environment_variable: "missing required environment variable: %
34
34
  missing_dependency: "missing dependency: %{dependency}"
35
35
  disallowed_flag: "%{name} must be one of: %{allowed}"
36
36
  disallowed_argument: "%{name} must be one of: %{allowed}"
37
+ disallowed_environment_variable: "%{name} environment variable must be one of: %{allowed}"
37
38
  unsupported_bash_version: "bash version 4 or higher is required"
38
39
  validation_error: "validation error in %s:\\n%s"
@@ -1,4 +1,4 @@
1
- require 'date' # for use by template render scripts
1
+ require 'date' # for use by template render scripts
2
2
  require 'colsole'
3
3
 
4
4
  module Bashly
@@ -1,14 +1,26 @@
1
+ require 'shellwords'
2
+
1
3
  module Bashly
2
4
  module Script
3
5
  class Argument < Base
4
6
  class << self
5
7
  def option_keys
6
8
  @option_keys ||= %i[
7
- allowed default help name repeatable required validate
9
+ allowed default help name repeatable required unique validate
8
10
  ]
9
11
  end
10
12
  end
11
13
 
14
+ def default_string
15
+ if default.is_a?(Array)
16
+ Shellwords.shelljoin default
17
+ elsif default.is_a?(String) && repeatable
18
+ Shellwords.shellescape default
19
+ else
20
+ default
21
+ end
22
+ end
23
+
12
24
  def usage_string
13
25
  required ? label : "[#{label}]"
14
26
  end
@@ -327,6 +327,11 @@ module Bashly
327
327
  args.select(&:allowed)
328
328
  end
329
329
 
330
+ # Returns an array of all the environemnt_variables with a whitelist arg
331
+ def whitelisted_environment_variables
332
+ environment_variables.select(&:allowed)
333
+ end
334
+
330
335
  # Returns an array of all the flags with a whitelist arg
331
336
  def whitelisted_flags
332
337
  flags.select(&:allowed)
@@ -3,7 +3,7 @@ module Bashly
3
3
  class EnvironmentVariable < Base
4
4
  class << self
5
5
  def option_keys
6
- @option_keys ||= %i[default help name required private]
6
+ @option_keys ||= %i[allowed default help name required private]
7
7
  end
8
8
  end
9
9
 
@@ -7,7 +7,7 @@ module Bashly
7
7
  def option_keys
8
8
  @option_keys ||= %i[
9
9
  allowed arg completions conflicts default help long repeatable
10
- required short validate private
10
+ required short unique validate private
11
11
  ]
12
12
  end
13
13
  end
@@ -22,6 +22,16 @@ module Bashly
22
22
  end
23
23
  end
24
24
 
25
+ def default_string
26
+ if default.is_a?(Array)
27
+ Shellwords.shelljoin default
28
+ elsif default.is_a?(String) && repeatable
29
+ Shellwords.shellescape default
30
+ else
31
+ default
32
+ end
33
+ end
34
+
25
35
  def name
26
36
  long || short
27
37
  end
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = '1.1.3'
2
+ VERSION = '1.1.5'
3
3
  end
@@ -8,7 +8,11 @@ if allowed
8
8
  end
9
9
 
10
10
  if default
11
- > printf " {{ strings[:default] % { value: default } }}\n"
11
+ if default.is_a? Array
12
+ > printf " {{ strings[:default] % { value: default.join(', ') } }}\n"
13
+ else
14
+ > printf " {{ strings[:default] % { value: default } }}\n"
15
+ end
12
16
  end
13
17
 
14
18
  > echo
@@ -2,11 +2,11 @@ if default_args.any? or default_flags.any?
2
2
  = view_marker
3
3
 
4
4
  default_args.each do |arg|
5
- > [[ -n ${args['{{ arg.name }}']:-} ]] || args['{{ arg.name }}']="{{ arg.default }}"
5
+ > [[ -n ${args['{{ arg.name }}']:-} ]] || args['{{ arg.name }}']="{{ arg.default_string }}"
6
6
  end
7
7
 
8
8
  default_flags.each do |flag|
9
- > [[ -n ${args['{{ flag.name }}']:-} ]] || args['{{ flag.name }}']="{{ flag.default }}"
9
+ > [[ -n ${args['{{ flag.name }}']:-} ]] || args['{{ flag.name }}']="{{ flag.default_string }}"
10
10
  end
11
11
 
12
12
  >
@@ -1,13 +1,26 @@
1
- if default_environment_variables.any? or required_environment_variables.any?
2
- = view_marker
1
+ if environment_variables.any?
2
+ = view_marker
3
3
  = render(:environment_variables_default)
4
4
 
5
- if required_environment_variables.any?
6
- required_environment_variables.each do |env_var|
7
- > if [[ -z "${<%= env_var.name.upcase %>:-}" ]]; then
8
- > printf "{{ strings[:missing_required_environment_variable] % { var: env_var.name.upcase } }}\n" >&2
9
- > exit 1
10
- > fi
11
- end
5
+ environment_variables.each do |env_var|
6
+ > env_var_names+=("{{ env_var.name.upcase }}")
12
7
  end
13
- end
8
+ end
9
+
10
+ if required_environment_variables.any?
11
+ required_environment_variables.each do |env_var|
12
+ > if [[ -z "${<%= env_var.name.upcase %>:-}" ]]; then
13
+ > printf "{{ strings[:missing_required_environment_variable] % { var: env_var.name.upcase } }}\n" >&2
14
+ > exit 1
15
+ > fi
16
+ end
17
+ end
18
+
19
+ if whitelisted_environment_variables.any?
20
+ whitelisted_environment_variables.each do |env_var|
21
+ > if [[ -n "${<%= env_var.name.upcase %>:-}" ]] && [[ ! ${<%= env_var.name.upcase %>:-} =~ ^({{ env_var.allowed.join '|' }})$ ]]; then
22
+ > printf "%s\n" "{{ strings[:disallowed_environment_variable] % { name: env_var.name.upcase, allowed: env_var.allowed.join(', ') } }}" >&2
23
+ > exit 1
24
+ > fi
25
+ end
26
+ end
@@ -4,7 +4,9 @@
4
4
  > if ((${#args[@]})); then
5
5
  > readarray -t sorted_keys < <(printf '%s\n' "${!args[@]}" | sort)
6
6
  > echo args:
7
- > for k in "${sorted_keys[@]}"; do echo "- \${args[$k]} = ${args[$k]}"; done
7
+ > for k in "${sorted_keys[@]}"; do
8
+ > echo "- \${args[$k]} = ${args[$k]}"
9
+ > done
8
10
  > else
9
11
  > echo args: none
10
12
  > fi
@@ -22,8 +24,18 @@
22
24
  > readarray -t sorted_keys < <(printf '%s\n' "${!deps[@]}" | sort)
23
25
  > echo
24
26
  > echo deps:
25
- > for k in "${sorted_keys[@]}"; do echo "- \${deps[$k]} = ${deps[$k]}"; done
27
+ > for k in "${sorted_keys[@]}"; do
28
+ > echo "- \${deps[$k]} = ${deps[$k]}"
29
+ > done
26
30
  > fi
27
31
  >
32
+ > if ((${#env_var_names[@]})); then
33
+ > readarray -t sorted_names < <(printf '%s\n' "${env_var_names[@]}" | sort)
34
+ > echo
35
+ > echo "environment variables:"
36
+ > for k in "${sorted_names[@]}"; do
37
+ > echo "- \$$k = ${!k:-}"
38
+ > done
39
+ > fi
28
40
  > }
29
41
  >
@@ -7,9 +7,17 @@ args.each do |arg|
7
7
  if arg.repeatable
8
8
  > args['{{ arg.name }}']="\"$1\""
9
9
  > shift
10
- > else
11
- > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\""
12
- > shift
10
+ if arg.unique
11
+ > elif [[ ! "${args['{{ arg.name }}']}" =~ \"$1\" ]]; then
12
+ > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\""
13
+ > shift
14
+ > else
15
+ > shift
16
+ else
17
+ > else
18
+ > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\""
19
+ > shift
20
+ end
13
21
 
14
22
  else
15
23
  > args['{{ arg.name }}']=$1
@@ -4,6 +4,7 @@
4
4
  > declare -A args=()
5
5
  > declare -A deps=()
6
6
  > declare -a other_args=()
7
+ > declare -a env_var_names=()
7
8
  > declare -a input=()
8
9
  > normalize_input "$@"
9
10
  > parse_requirements "${input[@]}"
@@ -3,6 +3,10 @@
3
3
  > printf " %s\n" "{{ usage_string(extended: true).color(:environment_variable) }}"
4
4
  > printf "{{ help.wrap(76).indent(4).sanitize_for_print }}\n"
5
5
 
6
+ if allowed
7
+ > printf " {{ strings[:allowed] % { values: allowed.join(', ') } }}\n"
8
+ end
9
+
6
10
  if default
7
11
  > printf " {{ strings[:default] % { value: default } }}\n"
8
12
  end
@@ -6,8 +6,12 @@
6
6
  if repeatable
7
7
  > if [[ -z ${args['{{ name }}']+x} ]]; then
8
8
  > args['{{ name }}']="\"$2\""
9
- > else
10
- > args['{{ name }}']="${args[{{ name }}]} \"$2\""
9
+ if unique
10
+ > elif [[ ! "${args['{{ name }}']}" =~ \"$2\" ]]; then
11
+ else
12
+ > else
13
+ end
14
+ > args['{{ name }}']="${args['{{ name }}']} \"$2\""
11
15
  > fi
12
16
 
13
17
  else
@@ -4,11 +4,15 @@
4
4
  > printf "{{ help.wrap(76).indent(4).sanitize_for_print }}\n"
5
5
 
6
6
  if allowed
7
- > printf " {{ strings[:allowed] % { values: allowed.join(', ') } }}\n"
7
+ > printf " {{ strings[:allowed] % { values: allowed.join(', ') } }}\n"
8
8
  end
9
9
 
10
10
  if default
11
- > printf " {{ strings[:default] % { value: default } }}\n"
11
+ if default.is_a? Array
12
+ > printf " {{ strings[:default] % { value: default.join(', ') } }}\n"
13
+ else
14
+ > printf " {{ strings[:default] % { value: default } }}\n"
15
+ end
12
16
  end
13
17
 
14
18
  > echo
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bashly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-25 00:00:00.000000000 Z
11
+ date: 2023-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole