bashly 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30efdcbeb1d466ddb9a273e1faee68a2f2a2d4290d75e6ea405e594c60cf029d
4
- data.tar.gz: 637e95e22f679ade3483129a473c3cb912c16db6c976a6eb49d47921ab2fd4c9
3
+ metadata.gz: b40fa2dc3cc6b3f0f65b961ea06dab0230eb0346eaa7c51575f12e27f16bcc3e
4
+ data.tar.gz: 704cc06b8d06539c123d2fabd450764fa8926705acc584ef47da87e5f2ab3e87
5
5
  SHA512:
6
- metadata.gz: 6bfd470d14131da08363c8b2f65412c09487927213a1ce2afdef0d1ebf06f3c655718d55275baed2502bd6a4f7f9c5ed723f1970e56d196b5d42585d0e84dd63
7
- data.tar.gz: b203ffe70e063a58f0e0fd3a0bfd4d5fff42ac4a9e23aaaa18ea68a89c2fd204a4aafb06fc13b23bf21084283b487fb207c84f46610242056be582e456283f41
6
+ metadata.gz: 6b5755ebda8ded8cc3a414063b8c9f7559b34fb5682d8f351f55f2be768ac4d39868cacca11c7b6a39741f3c00b13c8ee1f2d14d24307518f8e9954afabbe3d4
7
+ data.tar.gz: 540459bf266a62c289fd0fc0799f45e0e72bfbe3117dcf975ad623c022beba7327f97331d6a6539b69901ccf82fc2696a329622f0b7126951fc53cfdf583d0c7
data/README.md CHANGED
@@ -119,6 +119,15 @@ See the [examples](examples) folder for more examples.
119
119
  Configuration Reference
120
120
  --------------------------------------------------
121
121
 
122
+ The `bashly.yml` configuration file consists of these types:
123
+
124
+ - [Command](#command-options) - defines the root command as well as any
125
+ subcommand.
126
+ - [Argument](#argument-options) - defines positional arguments.
127
+ - [Flag](#flag-options) - defines option flags.
128
+ - [Environment Variable](#environment-variable-options) - defines
129
+ environment variables required (or desired) by your script.
130
+
122
131
  ### Command options
123
132
 
124
133
  Unless otherwise specified, these definitiona can be used for both the root
@@ -149,11 +158,9 @@ examples:
149
158
  - myscript download
150
159
  - myscript download --force
151
160
 
152
- # Specify an array of environment variables needed by your script
153
- # This is used purely for displaying in the help text (when using --help)
154
- # The help for each variable can have multiple lines.
155
- environment_variable:
156
- VARIABLE_NAME: Variable help text
161
+ # Specify an array of environment variables needed by your script.
162
+ environment_variables:
163
+ - ... see below ...
157
164
 
158
165
  # Specify the array of subcommands to generate.
159
166
  # Each subcommand will have its own args and flags.
@@ -164,12 +171,18 @@ commands:
164
171
  # Specify the array of positional arguments this script needs.
165
172
  # If this is provided, then you cannot specify commands.
166
173
  args:
167
- - ...
174
+ - ... see below ...
168
175
 
169
176
  # Specify the array of option flags this script needs.
170
177
  # If this is provided, then you cannot specify commands.
171
178
  flags:
172
- - ...
179
+ - ... see below ...
180
+
181
+ # Specify an array of any required external dependencies (commands).
182
+ # The script execution will be halted with a friendly error unless all
183
+ # dependency commands exist.
184
+ dependencies:
185
+ - curl
173
186
  ```
174
187
 
175
188
 
@@ -208,8 +221,9 @@ required: true
208
221
  The below configuration generates this flag:
209
222
 
210
223
  ```
211
- -o, --output DIRECTORY (required)
212
- Specify the output directory
224
+ Options:
225
+ -o, --output DIRECTORY (required)
226
+ Specify the output directory
213
227
  ```
214
228
 
215
229
  The flag's value will be available to you as `${args[--output]}` in your
@@ -234,6 +248,33 @@ arg: directory
234
248
  required: true
235
249
  ```
236
250
 
251
+ ### Environment Variable options
252
+
253
+ The below configuration generates this environment variable usage text:
254
+
255
+ ```
256
+ Environment Variables:
257
+ SECRET_KEY (required)
258
+ Your API secret key
259
+ ```
260
+
261
+ If an environment variable is defined as required (false by default), the
262
+ execution of the script will be halted with a friendly error if it is not
263
+ set.
264
+
265
+ ```yaml
266
+ # The name of the variable (it will be automatically capitalized).
267
+ name: secret_key
268
+
269
+ # The message to display when using --help.
270
+ # This can have multiple lines.
271
+ help: Your API secret key
272
+
273
+ # Specify if this variable is required.
274
+ required: true
275
+ ```
276
+
277
+
237
278
 
238
279
  Real World Examples
239
280
  --------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  class String
2
- def escape_newlines
3
- gsub "\n", "\\n"
2
+ def sanitize_for_print
3
+ gsub("\n", "\\n").gsub("\"", "\\\"")
4
4
  end
5
5
 
6
6
  def indent(offset)
@@ -9,7 +9,7 @@ class String
9
9
  end
10
10
 
11
11
  def to_underscore
12
- gsub(/(.)([A-Z])/,'\1_\2').gsub(' ', '_').downcase
12
+ gsub(/(.)([A-Z])/,'\1_\2').gsub(/[\- ]/, '_').downcase
13
13
  end
14
14
 
15
15
  def wrap(length = 80)
@@ -7,6 +7,7 @@ module Bashly
7
7
 
8
8
  OPTION_KEYS = %i[
9
9
  arg
10
+ dependencies
10
11
  description
11
12
  environment_variables
12
13
  examples
@@ -55,6 +55,14 @@ module Bashly
55
55
  result
56
56
  end
57
57
 
58
+ # Returns an array of EnvironmentVariables
59
+ def environment_variables
60
+ return [] unless options["environment_variables"]
61
+ options["environment_variables"].map do |options|
62
+ EnvironmentVariable.new options
63
+ end
64
+ end
65
+
58
66
  # Returns the bash filename that is expected to hold the user code
59
67
  # for this command
60
68
  def filename
@@ -107,6 +115,11 @@ module Bashly
107
115
  args.select &:required
108
116
  end
109
117
 
118
+ # Returns an array of all the required EnvironmentVariables
119
+ def required_environment_variables
120
+ environment_variables.select &:required
121
+ end
122
+
110
123
  # Returns an array of all the required Flags
111
124
  def required_flags
112
125
  flags.select &:required
@@ -0,0 +1,11 @@
1
+ module Bashly
2
+ module Models
3
+ class EnvironmentVariable < Base
4
+ def usage_string(extended: false)
5
+ result = [name.upcase]
6
+ result << "(required)" if required and extended
7
+ result.join " "
8
+ end
9
+ end
10
+ end
11
+ end
@@ -3,7 +3,8 @@ help: Sample application
3
3
  version: 0.1.0
4
4
 
5
5
  environment_variables:
6
- API_KEY: Set your API key
6
+ - name: api_key
7
+ help: Set your API key
7
8
 
8
9
  commands:
9
10
  - name: download
@@ -27,7 +28,8 @@ commands:
27
28
  - cli download example.com ./output -f
28
29
 
29
30
  environment_variables:
30
- DEFAULT_TARGET_LOCATION: Set the default location to download to
31
+ - name: default_target_location
32
+ help: Set the default location to download to
31
33
 
32
34
  - name: upload
33
35
  short: u
@@ -16,4 +16,5 @@ invalid_argument: "invalid argument: %{arg}"
16
16
  invalid_flag: "invalid option: %{flag}"
17
17
  missing_required_argument: "missing required argument: %{arg}\\nusage: %{usage}"
18
18
  missing_required_flag: "missing required flag: %{usage}"
19
-
19
+ missing_required_environment_variable: "missing required environment variable: %{var}"
20
+ missing_dependency: "missing dependency: %{dependency}"
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,4 +1,4 @@
1
1
  # :argument.usage
2
2
  echo " <%= name.upcase %>"
3
- echo -e "<%= help.wrap(76).indent(4).escape_newlines %>"
3
+ echo -e "<%= help.wrap(76).indent(4).sanitize_for_print %>"
4
4
  echo
@@ -10,7 +10,7 @@ case $action in
10
10
  <%= command.aliases.join " | " %> )
11
11
  action="<%= command.name %>"
12
12
  shift
13
- <%= command.function_name %>_parse_args "$@"
13
+ <%= command.function_name %>_parse_requirements "$@"
14
14
  shift $#
15
15
  ;;
16
16
 
@@ -0,0 +1,9 @@
1
+ # :command.dependencies_filter
2
+ <%- if dependencies -%>
3
+ <%- dependencies.each do |dependency| -%>
4
+ if ! [[ -x "$(command -v <%= dependency %>)" ]]; then
5
+ echo -e "<%= strings[:missing_dependency] % { dependency: dependency } -%>"
6
+ exit 1
7
+ fi
8
+ <%- end -%>
9
+ <%- end -%>
@@ -0,0 +1,9 @@
1
+ # :command.environment_variables_filter
2
+ <%- if required_environment_variables.any? -%>
3
+ <%- required_environment_variables.each do |env_var| -%>
4
+ if [[ -z "$<%= env_var.name.upcase %>" ]]; then
5
+ echo -e "<%= strings[:missing_required_environment_variable] % { var: env_var.name.upcase } -%>"
6
+ exit 1
7
+ fi
8
+ <%- end -%>
9
+ <%- end -%>
@@ -8,7 +8,7 @@
8
8
  <%= render :inspect_args %>
9
9
  <%= render :user_lib if user_lib.any? %>
10
10
  <%= render :command_functions %>
11
- <%= render :parse_args %>
11
+ <%= render :parse_requirements %>
12
12
  <%= render :initialize %>
13
13
  <%= render :run %>
14
14
 
@@ -0,0 +1,18 @@
1
+ # :command.parse_requirements
2
+ <%- if root_command? -%>
3
+ parse_requirements() {
4
+ <%- else -%>
5
+ <%= function_name %>_parse_requirements() {
6
+ <%- end -%>
7
+ <%= render(:fixed_flags_filter).indent 2 %>
8
+ <%= render(:environment_variables_filter).indent 2 %>
9
+ <%= render(:dependencies_filter).indent 2 %>
10
+ <%= render(:command_filter).indent 2 %>
11
+ <%= render(:required_args_filter).indent 2 %>
12
+ <%= render(:required_flags_filter).indent 2 %>
13
+ <%= render(:parse_requirements_while).indent 2 %>
14
+ }
15
+
16
+ <%- commands.each do |command| %>
17
+ <%= command.render :parse_requirements %>
18
+ <%- end -%>
@@ -1,4 +1,4 @@
1
- # :command.parse_args_case
1
+ # :command.parse_requirements_case
2
2
  <%- if args.any? -%>
3
3
  <%- condition = "if" -%>
4
4
  <%- args.each do |arg| -%>
@@ -1,4 +1,4 @@
1
- # :command.parse_args_while
1
+ # :command.parse_requirements_while
2
2
  while [[ $# -gt 0 ]]; do
3
3
  key="$1"
4
4
  case "$key" in
@@ -13,7 +13,7 @@ while [[ $# -gt 0 ]]; do
13
13
  ;;
14
14
 
15
15
  * )
16
- <%= render(:parse_args_case).indent 4 %>
16
+ <%= render(:parse_requirements_case).indent 4 %>
17
17
  ;;
18
18
 
19
19
  esac
@@ -1,7 +1,7 @@
1
1
  # :command.run
2
2
  run() {
3
3
  declare -A args
4
- parse_args "$@"
4
+ parse_requirements "$@"
5
5
 
6
6
  <%- condition = "if" -%>
7
7
  <%- deep_commands.each do |command| -%>
@@ -7,7 +7,7 @@
7
7
  <%- else -%>
8
8
  echo -e "<%= full_name %>"
9
9
  echo
10
- echo -e "<%= help.wrap(78).indent(2).escape_newlines %>"
10
+ echo -e "<%= help.wrap(78).indent(2).sanitize_for_print %>"
11
11
  echo
12
12
  <%- end -%>
13
13
  else
@@ -32,7 +32,7 @@
32
32
  <%= render(:usage_fixed_flags).indent 4 %>
33
33
  <%= render(:usage_flags).indent 4 if flags.any? %>
34
34
  <%= render(:usage_args).indent 4 if args.any? %>
35
- <%= render(:usage_environment_variables).indent 4 if environment_variables %>
35
+ <%= render(:usage_environment_variables).indent 4 if environment_variables.any? %>
36
36
  <%= render(:usage_examples).indent 4 if examples %>
37
37
 
38
38
  fi
@@ -1,7 +1,6 @@
1
1
  # :command.usage_environment_variables
2
2
  echo -e "<%= strings[:environment_variables] %>"
3
- <%- environment_variables.each do |name, description| -%>
4
- echo " <%= name %>"
5
- echo -e "<%= description.wrap(76).indent(4).escape_newlines %>"
3
+
4
+ <%- environment_variables.each do |env_var| -%>
5
+ <%= env_var.render(:usage) %>
6
6
  <%- end -%>
7
- echo
@@ -2,6 +2,6 @@
2
2
  echo -e "<%= strings[:examples] %>"
3
3
 
4
4
  <%- examples.each do |example| -%>
5
- echo -e "<%= example.wrap(78).indent(2).escape_newlines %>"
5
+ echo -e "<%= example.wrap(78).indent(2).sanitize_for_print %>"
6
6
  <%- end -%>
7
7
  echo
@@ -0,0 +1,4 @@
1
+ # :environment_variable.usage
2
+ echo " <%= usage_string extended: true %>"
3
+ echo -e "<%= help.wrap(76).indent(4).sanitize_for_print %>"
4
+ echo
@@ -1,4 +1,4 @@
1
1
  # :flag.usage
2
2
  echo " <%= usage_string extended: true %>"
3
- echo -e "<%= help.wrap(76).indent(4).escape_newlines %>"
3
+ echo -e "<%= help.wrap(76).indent(4).sanitize_for_print %>"
4
4
  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: 0.2.4
4
+ version: 0.3.0
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: 2019-11-26 00:00:00.000000000 Z
11
+ date: 2019-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -78,6 +78,7 @@ files:
78
78
  - lib/bashly/models/argument.rb
79
79
  - lib/bashly/models/base.rb
80
80
  - lib/bashly/models/command.rb
81
+ - lib/bashly/models/environment_variable.rb
81
82
  - lib/bashly/models/flag.rb
82
83
  - lib/bashly/polyfills/hash.rb
83
84
  - lib/bashly/settings.rb
@@ -95,14 +96,16 @@ files:
95
96
  - lib/bashly/views/command/default_initialize_script.erb
96
97
  - lib/bashly/views/command/default_root_script.erb
97
98
  - lib/bashly/views/command/default_script.erb
99
+ - lib/bashly/views/command/dependencies_filter.erb
100
+ - lib/bashly/views/command/environment_variables_filter.erb
98
101
  - lib/bashly/views/command/fixed_flags_filter.erb
99
102
  - lib/bashly/views/command/function.erb
100
103
  - lib/bashly/views/command/initialize.erb
101
104
  - lib/bashly/views/command/inspect_args.erb
102
105
  - lib/bashly/views/command/master_script.erb
103
- - lib/bashly/views/command/parse_args.erb
104
- - lib/bashly/views/command/parse_args_case.erb
105
- - lib/bashly/views/command/parse_args_while.erb
106
+ - lib/bashly/views/command/parse_requirements.erb
107
+ - lib/bashly/views/command/parse_requirements_case.erb
108
+ - lib/bashly/views/command/parse_requirements_while.erb
106
109
  - lib/bashly/views/command/required_args_filter.erb
107
110
  - lib/bashly/views/command/required_flags_filter.erb
108
111
  - lib/bashly/views/command/root_command.erb
@@ -116,6 +119,7 @@ files:
116
119
  - lib/bashly/views/command/usage_flags.erb
117
120
  - lib/bashly/views/command/user_lib.erb
118
121
  - lib/bashly/views/command/version_command.erb
122
+ - lib/bashly/views/environment_variable/usage.erb
119
123
  - lib/bashly/views/flag/case.erb
120
124
  - lib/bashly/views/flag/usage.erb
121
125
  homepage: https://github.com/dannyben/bashly
@@ -1,16 +0,0 @@
1
- # :command.parse_args
2
- <%- if root_command? -%>
3
- parse_args() {
4
- <%- else -%>
5
- <%= function_name %>_parse_args() {
6
- <%- end -%>
7
- <%= render(:fixed_flags_filter).indent 2 %>
8
- <%= render(:command_filter).indent 2 %>
9
- <%= render(:required_args_filter).indent 2 %>
10
- <%= render(:required_flags_filter).indent 2 %>
11
- <%= render(:parse_args_while).indent 2 %>
12
- }
13
-
14
- <%- commands.each do |command| %>
15
- <%= command.render 'parse_args' %>
16
- <%- end -%>