bashly 0.4.0 → 0.4.4

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: 14ee3d9cf49b4497ffbb7e374894cc0cfe18e1a1493a58c638cf4fd8896f30e2
4
- data.tar.gz: 18dd37e6cfc3efd1f3c3d103f943e5ba8db4b414b2b26bed1bb096728c40cd1d
3
+ metadata.gz: 3b9f48152171cac044c5f26ec11f6fcdad64d9bb5fcf3363ab23a609d24c5b3b
4
+ data.tar.gz: 7ffcba2d9cc3448f0e08972086c5518dfc7d5c0b2969f5f112045b6b5f114f4f
5
5
  SHA512:
6
- metadata.gz: 2564fbacc1cd7584e6a0a4da943a25fa70bb51e01a935e18e1c15cb98f3a95e75147f404f858f294df26e18499233e1f82d99f3b344a8464e8ecfccd90c5a0e2
7
- data.tar.gz: d638eff5ef4a4d407b558ba153e199ede105fe34b23ee00b7c8961c843cd8e5ef23e21de1396c92b6f3742f9ec7585f02ac182ccd19329b0008f5c2f5b702cc7
6
+ metadata.gz: 6fe841722c54b62f72ddce5afdd8448feb30e973a034e623146981b1166be57826238eec5d5e2ac18e3d8357872b5305709110302ae13a7ce5130a0aa46d3a87
7
+ data.tar.gz: 6d93748b46b22c2e42f5abcd8751e99454545da4293e7a8deeca28869be8df4eccc980d21ca4e4e2acb6b682a2b5451fddc5e339759f40bbb4202e15923cdceb
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  <div align='center'>
2
2
  <img src='logo.svg' width=280>
3
3
 
4
- Bashly - Bash CLI Framework and Generator
5
- ==================================================
4
+ # Bashly - Bash CLI Framework and Generator
6
5
 
7
6
  Create beautiful bash scripts from simple YAML configuration
8
7
 
@@ -16,10 +15,28 @@ Create beautiful bash scripts from simple YAML configuration
16
15
 
17
16
  </div>
18
17
 
18
+ ## Table of Contents
19
+
20
+ - [Table of Contents](#table-of-contents)
21
+ - [Installation](#installation)
22
+ - [Prerequisites](#prerequisites)
23
+ - [What is Bashly](#what-is-bashly)
24
+ - [Usage](#usage)
25
+ - [Using the input arguemnts in your code](#using-the-input-arguemnts-in-your-code)
26
+ - [Examples](#examples)
27
+ - [Sample configuraiton for a script without commands](#sample-configuraiton-for-a-script-without-commands)
28
+ - [Sample configuraiton for a script with commands](#sample-configuraiton-for-a-script-with-commands)
29
+ - [Configuration Reference](#configuration-reference)
30
+ - [Command options](#command-options)
31
+ - [Argument options](#argument-options)
32
+ - [Flag options](#flag-options)
33
+ - [Environment Variable options](#environment-variable-options)
34
+ - [Real World Examples](#real-world-examples)
35
+ - [Contributing / Support](#contributing--support)
36
+
19
37
  ---
20
38
 
21
- Installation
22
- --------------------------------------------------
39
+ ## Installation
23
40
 
24
41
  ```shell
25
42
  $ gem install bashly
@@ -31,15 +48,13 @@ or with Docker:
31
48
  $ alias bashly='docker run --rm -it --volume "$PWD:/app" dannyben/bashly'
32
49
  ```
33
50
 
34
- Prerequisites
35
- --------------------------------------------------
51
+ ## Prerequisites
36
52
 
37
53
  The bash scripts generated by bashly require bash 4 or higher due to heavy
38
54
  use of associative arrays.
39
55
 
40
56
 
41
- What is Bashly
42
- --------------------------------------------------
57
+ ## What is Bashly
43
58
 
44
59
  Bashly is a command line application (written in Ruby) that lets you generate
45
60
  feature-rich bash command line tools.
@@ -68,8 +83,7 @@ Bahsly is responsible for:
68
83
  - **YAML parsing**.
69
84
  - and more.
70
85
 
71
- Usage
72
- --------------------------------------------------
86
+ ## Usage
73
87
 
74
88
  In an empty directory, create a sample configuration file by running
75
89
 
@@ -99,9 +113,46 @@ Finally, edit the files in the `src` folder. Each of your script's commands
99
113
  get their own file. Once you edit, run `bashly generate` again to merge the
100
114
  content from your functions back into the script.
101
115
 
116
+ ### Using the input arguemnts in your code
117
+
118
+ In order to access the parsed arguments in any of your partial scripts, you
119
+ may simply access the `$args` associative array.
120
+
121
+ For example:
122
+
123
+ 1. Generate a minimal configuration with `bashly init --minimal`
124
+ 2. Generate the bash script with `bashly generate`
125
+ 3. Run the script with `./download hello --force`
102
126
 
103
- Examples
104
- --------------------------------------------------
127
+ You will notice that all the arguments of the associative array are printed
128
+ on screen. This is done by the `inspect_args` function that was inserted into
129
+ the generated partial script `src/root_command.sh`.
130
+
131
+ You can now access these variables by modifying `sec/root_command.sh` like
132
+ this:
133
+
134
+
135
+ ```bash
136
+ # src/root_command.sh
137
+ source_url=${args[source]}
138
+ force=${args[--force]}
139
+
140
+ if [[ $force ]]; then
141
+ echo "downloading $source_url with --force"
142
+ else
143
+ echo "downloading $source_url"
144
+ fi
145
+ ```
146
+
147
+ After editing the file, run `bashly generate` (or `bashly g` for short) and
148
+ run:
149
+
150
+ ```
151
+ $ ./download a --force
152
+ downloading a with --force
153
+ ```
154
+
155
+ ## Examples
105
156
 
106
157
  The `bashly.yml` file can be set up to generate two types of scripts:
107
158
 
@@ -129,8 +180,7 @@ See the [examples](examples) folder for more examples.
129
180
 
130
181
 
131
182
 
132
- Configuration Reference
133
- --------------------------------------------------
183
+ ## Configuration Reference
134
184
 
135
185
  The `bashly.yml` configuration file consists of these types:
136
186
 
@@ -146,19 +196,19 @@ The `bashly.yml` configuration file consists of these types:
146
196
  Unless otherwise specified, these definitiona can be used for both the root
147
197
  command and subcommands (under the `commands` definition).
148
198
 
149
-
150
199
  Option | Description
151
200
  -----------|-------------
152
201
  `name` | The name of the script or subcommand.
153
202
  `short` | An additional, optional pattern - usually used to denote a one letter variation of the command name. You can add `*` as a suffix, to denote a "starts with" pattern - for example `short: m*`. *Applicable only in subcommands*.
154
203
  `help` | The header text to display when using `--help`. This option can have multiple lines. In this case, the first line will be used as summary wherever appropriate.
155
204
  `version` | The string to display when using `--version`. *Applicable only in the main command*.
156
- `default` | Setting this to `yes` on any command, will make unrecognized command line arguments to be passed to this command. *Applicable only in subcommands*.
205
+ `default` | Setting this to `true` on any command, will make unrecognized command line arguments to be passed to this command. *Applicable only in subcommands*.
157
206
  `examples` | Specify an array of examples to show when using `--help`. Each example can have multiple lines.
158
207
  `environment_variables` | Specify an array of environment variables needed by your script.
159
208
  `commands` | Specify the array of commands. Each command will have its own args and flags. Note: if `commands` is provided, you cannot specify flags or args at the same level.
160
209
  `args` | Specify the array of positional arguments this script needs.
161
210
  `flags` | Specify the array of option flags this script needs.
211
+ `catch_all` | Specify that this command should allow for additional arbitrary arguments or flags. It can be set in one of three ways:<br>- Set to `true` to just enable it.<br>- Set to a string, to use this string in the usage help text.<br>- Set to a hash containing `label` and `help` keys, to show a detailed help for it when running with `--help`.
162
212
  `dependencies` | Specify an array of any required external dependencies (commands). The script execution will be halted with a friendly error unless all dependency commands exist.
163
213
  `group` | In case you have many commands, use this option to specify a caption to display before this command. This option is purely for display purposes, and needs to be specified only for the first command in each group.
164
214
 
@@ -173,6 +223,7 @@ bash function.
173
223
  `help` | The message to display when using `--help`. Can have multiple lines.
174
224
  `required` | Specify if this argument is required. Note that once you define an optional argument (without required: true) then you cannot define required arguments after it.
175
225
  `default` | The value to use in case it is not provided by the user. Implies that this argument is optional.
226
+ `allowed` | Limit the allowed values by providing an array.
176
227
 
177
228
  ### Flag options
178
229
 
@@ -188,6 +239,7 @@ short form).
188
239
  `arg` | If the flag requires an argument, specify its name here.
189
240
  `required` | Specify if this flag is required.
190
241
  `default` | The value to use in case it is not provided by the user. Implies that this flag is optional, and only makes sense when the flag has an argument.
242
+ `allowed` | For flags with an argument, you can limit the allowed values by providing an array.
191
243
 
192
244
  #### Special handling for -v and -h
193
245
 
@@ -210,16 +262,14 @@ set.
210
262
  `required` | Specify if this variable is required.
211
263
 
212
264
 
213
- Real World Examples
214
- --------------------------------------------------
265
+ ## Real World Examples
215
266
 
216
267
  - [Rush][rush] - a Personal Package Manager
217
268
  - [Alf][alf] - a generator for bash aliases and sub-aliases
218
269
  - [git-changelog][git-changelog] - a change log generator
219
270
 
220
271
 
221
- Contributing / Support
222
- --------------------------------------------------
272
+ ## Contributing / Support
223
273
 
224
274
  If you experience any issue, have a question or a suggestion, or if you wish
225
275
  to contribute, feel free to [open an issue][issues].
@@ -3,14 +3,18 @@ module Bashly
3
3
  class Generate < Base
4
4
  help "Generate the bash script and required files"
5
5
 
6
- usage "bashly generate [--force]"
6
+ usage "bashly generate [--force --wrap FUNCTION]"
7
7
  usage "bashly generate (-h|--help)"
8
8
 
9
9
  option "-f --force", "Overwrite existing files"
10
+ option "-w --wrap FUNCTION", "Wrap the entire script in a function so it can also be sourced"
10
11
 
11
12
  environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"
12
13
  environment "BASHLY_TARGET_DIR", "The path to use for creating the bash script [default: .]"
13
14
 
15
+ example "bashly generate --force"
16
+ example "bashly generate --wrap my_function"
17
+
14
18
  def run
15
19
  create_user_files
16
20
  create_master_script
@@ -54,12 +58,15 @@ module Bashly
54
58
  end
55
59
 
56
60
  def create_master_script
57
- master_script = command.render('master_script').lint
58
- File.write master_script_path, master_script
61
+ File.write master_script_path, script.code
59
62
  FileUtils.chmod "+x", master_script_path
60
63
  say "created !txtgrn!#{master_script_path}"
61
64
  end
62
65
 
66
+ def script
67
+ @script ||= Models::Script.new(command, args['--wrap'])
68
+ end
69
+
63
70
  def master_script_path
64
71
  "#{Settings.target_dir}/#{command.name}"
65
72
  end
@@ -11,7 +11,8 @@ module Bashly
11
11
  def run
12
12
  config = Config.new "#{Settings.source_dir}/bashly.yml"
13
13
  command = Models::Command.new(config)
14
- puts command.render 'master_script'
14
+ script = Models::Script.new command
15
+ puts script.code
15
16
  end
16
17
  end
17
18
  end
@@ -6,10 +6,12 @@ module Bashly
6
6
  attr_reader :options
7
7
 
8
8
  OPTION_KEYS = %i[
9
+ allowed
9
10
  arg
11
+ catch_all
12
+ default
10
13
  dependencies
11
14
  description
12
- default
13
15
  environment_variables
14
16
  examples
15
17
  flags
@@ -28,6 +28,29 @@ module Bashly
28
28
  help ? "#{full_name} - #{summary}" : full_name
29
29
  end
30
30
 
31
+ # Returns a label for the catch_all directive
32
+ def catch_all_label
33
+ return nil unless catch_all
34
+
35
+ if catch_all.is_a? String
36
+ "#{catch_all.upcase}..."
37
+ elsif catch_all.is_a?(Hash) and catch_all['label'].is_a?(String)
38
+ "#{catch_all['label'].upcase}..."
39
+ else
40
+ "..."
41
+ end
42
+ end
43
+
44
+ def catch_all_help
45
+ return nil unless catch_all
46
+
47
+ if catch_all.is_a?(Hash) and catch_all['help'].is_a?(String)
48
+ catch_all['help']
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
31
54
  # Returns only the names of the Commands
32
55
  def command_names
33
56
  commands.map &:name
@@ -159,6 +182,7 @@ module Bashly
159
182
  result << arg.usage_string
160
183
  end
161
184
  result << "[options]" unless flags.empty?
185
+ result << "[#{catch_all_label}]" if catch_all
162
186
  result.join " "
163
187
  end
164
188
 
@@ -175,6 +199,16 @@ module Bashly
175
199
  verify_commands if commands.any?
176
200
  end
177
201
 
202
+ # Returns an array of all the args with a whitelist
203
+ def whitelisted_args
204
+ args.select &:allowed
205
+ end
206
+
207
+ # Returns an array of all the flags with a whitelist arg
208
+ def whitelisted_flags
209
+ flags.select &:allowed
210
+ end
211
+
178
212
  private
179
213
 
180
214
  def verify_commands
@@ -0,0 +1,33 @@
1
+ module Bashly
2
+ module Models
3
+ class Script
4
+ include Renderable
5
+
6
+ attr_reader :command, :function_name
7
+
8
+ def initialize(command, function_name = nil)
9
+ @command, @function_name = command, function_name
10
+ end
11
+
12
+ def code
13
+ if function_name
14
+ result = [header, render('wrapper')].join "\n"
15
+ else
16
+ result = [header, body].join "\n"
17
+ end
18
+
19
+ result.lint
20
+ end
21
+
22
+ private
23
+
24
+ def header
25
+ @header ||= render('header')
26
+ end
27
+
28
+ def body
29
+ @body ||= command.render('master_script')
30
+ end
31
+ end
32
+ end
33
+ end
@@ -15,6 +15,7 @@ command_shortcut: "Shortcut: %{short}"
15
15
  default_command_summary: "%{summary} (default)"
16
16
  required: "(required)"
17
17
  default: "Default: %{value}"
18
+ allowed: "Allowed: %{values}"
18
19
 
19
20
  # Fixed flags help text
20
21
  help_flag_text: Show this help
@@ -28,3 +29,5 @@ missing_required_argument: "missing required argument: %{arg}\\nusage: %{usage}"
28
29
  missing_required_flag: "missing required flag: %{usage}"
29
30
  missing_required_environment_variable: "missing required environment variable: %{var}"
30
31
  missing_dependency: "missing dependency: %{dependency}"
32
+ disallowed_flag: "%{name} must be one of: %{allowed}"
33
+ disallowed_argument: "%{name} must be one of: %{allowed}"
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.4"
3
3
  end
@@ -1,6 +1,9 @@
1
1
  # :argument.usage
2
2
  echo " <%= name.upcase %>"
3
3
  printf "<%= help.wrap(76).indent(4).sanitize_for_print %>\n"
4
+ <%- if allowed -%>
5
+ printf " <%= strings[:allowed] % { values: allowed.join(', ') } -%>\n"
6
+ <%- end -%>
4
7
  <%- if default -%>
5
8
  printf " <%= strings[:default] % { value: default } -%>\n"
6
9
  <%- end -%>
@@ -1,5 +1,19 @@
1
1
  # :command.inspect_args
2
2
  inspect_args() {
3
- echo args:
4
- for k in "${!args[@]}"; do echo "- \${args[$k]} = ${args[$k]}"; done
3
+ readarray -t sorted_keys < <(printf '%s\n' "${!args[@]}" | sort)
4
+ if (( ${#args[@]} )); then
5
+ echo args:
6
+ for k in "${sorted_keys[@]}"; do echo "- \${args[$k]} = ${args[$k]}"; done
7
+ else
8
+ echo args: none
9
+ fi
10
+
11
+ if (( ${#other_args[@]} )); then
12
+ echo
13
+ echo other_args:
14
+ echo "- \${other_args[*]} = ${other_args[*]}"
15
+ for i in "${!other_args[@]}"; do
16
+ echo "- \${other_args[$i]} = ${other_args[$i]}"
17
+ done
18
+ fi
5
19
  }
@@ -1,7 +1,3 @@
1
- #!/usr/bin/env bash
2
- # This script was generated by bashly (https://github.com/DannyBen/bashly)
3
- # Modifying it manually is not recommended
4
-
5
1
  <%= render :root_command if commands.empty? %>
6
2
  <%= render :version_command %>
7
3
  <%= render :usage %>
@@ -12,6 +12,7 @@ parse_requirements() {
12
12
  <%= render(:required_flags_filter).indent 2 %>
13
13
  <%= render(:parse_requirements_while).indent 2 %>
14
14
  <%= render(:default_assignments).indent 2 %>
15
+ <%= render(:whitelist_filter).indent 2 %>
15
16
  }
16
17
 
17
18
  <%- commands.each do |command| %>
@@ -8,9 +8,17 @@
8
8
  <%- condition = "elif" -%>
9
9
  <%- end -%>
10
10
  else
11
+ <%- if catch_all -%>
12
+ other_args+=("$1")
13
+ shift
14
+ <%- else -%>
11
15
  printf "<%= strings[:invalid_argument] %>\n" "$key"
12
16
  exit 1
17
+ <%- end -%>
13
18
  fi
19
+ <%- elsif catch_all -%>
20
+ other_args+=("$1")
21
+ shift
14
22
  <%- else -%>
15
23
  printf "<%= strings[:invalid_argument] %>\n" "$key"
16
24
  exit 1
@@ -8,9 +8,15 @@ while [[ $# -gt 0 ]]; do
8
8
  <%- end -%>
9
9
 
10
10
  -* )
11
+ <%- if catch_all -%>
12
+ other_args+=("$1")
13
+ shift
14
+ ;;
15
+ <%- else -%>
11
16
  printf "<%= strings[:invalid_flag] %>\n" "$key"
12
17
  exit 1
13
18
  ;;
19
+ <%- end -%>
14
20
 
15
21
  * )
16
22
  <%= render(:parse_requirements_case).indent 4 %>
@@ -1,6 +1,7 @@
1
1
  # :command.run
2
2
  run() {
3
3
  declare -A args
4
+ declare -a other_args
4
5
  parse_requirements "$@"
5
6
 
6
7
  <%- condition = "if" -%>
@@ -14,12 +15,7 @@ run() {
14
15
  fi
15
16
  <% condition = "elif" %>
16
17
  <%- end -%>
17
- <%= condition %> [[ ${args[--version]} ]]; then
18
- version_command
19
- elif [[ ${args[--help]} ]]; then
20
- long_usage=yes
21
- <%= name %>_usage
22
- elif [[ $action == "root" ]]; then
18
+ <%= condition %> [[ $action == "root" ]]; then
23
19
  root_command
24
20
  fi
25
21
  }
@@ -37,7 +37,7 @@
37
37
  printf "<%= strings[:options] %>\n"
38
38
  <%= render(:usage_fixed_flags).indent 4 %>
39
39
  <%= render(:usage_flags).indent 4 if flags.any? %>
40
- <%= render(:usage_args).indent 4 if args.any? %>
40
+ <%= render(:usage_args).indent 4 if args.any? or catch_all_help %>
41
41
  <%= render(:usage_environment_variables).indent 4 if environment_variables.any? %>
42
42
  <%= render(:usage_examples).indent 4 if examples %>
43
43
 
@@ -1,6 +1,14 @@
1
1
  # :command.usage_args
2
2
  printf "<%= strings[:arguments] %>\n"
3
+ <%- if args.any? -%>
3
4
 
4
5
  <%- args.each do |arg| -%>
5
6
  <%= arg.render(:usage) %>
6
7
  <%- end -%>
8
+ <%- end -%>
9
+ <%- if catch_all_help -%>
10
+
11
+ echo " <%= catch_all_label %>"
12
+ printf "<%= catch_all_help.wrap(76).indent(4).sanitize_for_print %>\n"
13
+ echo
14
+ <%- end -%>
@@ -0,0 +1,13 @@
1
+ # :command.whitelist_filter
2
+ <%- whitelisted_args.each do |arg| -%>
3
+ if [[ ! ${args[<%= arg.name %>]} =~ ^(<%= arg.allowed.join '|' %>)$ ]]; then
4
+ printf "%s\n" "<%= strings[:disallowed_argument] % { name: arg.name, allowed: arg.allowed.join(', ') } %>"
5
+ exit 1
6
+ fi
7
+ <%- end -%>
8
+ <%- whitelisted_flags.each do |flag| -%>
9
+ if [[ ! ${args[<%= flag.name %>]} =~ ^(<%= flag.allowed.join '|' %>)$ ]]; then
10
+ printf "%s\n" "<%= strings[:disallowed_flag] % { name: flag.name, allowed: flag.allowed.join(', ') } %>"
11
+ exit 1
12
+ fi
13
+ <%- end -%>
@@ -1,7 +1,7 @@
1
1
  # :flag.case
2
2
  <%= aliases.join " | " %> )
3
3
  <%- if arg -%>
4
- if [[ $2 && $2 != -* ]]; then
4
+ if [[ $2 ]]; then
5
5
  args[<%= name %>]="$2"
6
6
  shift
7
7
  shift
@@ -1,6 +1,9 @@
1
1
  # :flag.usage
2
2
  echo " <%= usage_string extended: true %>"
3
3
  printf "<%= help.wrap(76).indent(4).sanitize_for_print %>\n"
4
+ <%- if allowed -%>
5
+ printf " <%= strings[:allowed] % { values: allowed.join(', ') } -%>\n"
6
+ <%- end -%>
4
7
  <%- if default -%>
5
8
  printf " <%= strings[:default] % { value: default } -%>\n"
6
9
  <%- end -%>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ # This script was generated by bashly (https://github.com/DannyBen/bashly)
3
+ # Modifying it manually is not recommended
@@ -0,0 +1,6 @@
1
+ # :script.wrapper
2
+ <%= function_name %>() {
3
+ <%= body.indent 2 %>
4
+ }
5
+
6
+ (return 0 2>/dev/null) || <%= function_name %> "$@"
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.4.0
4
+ version: 0.4.4
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: 2020-10-21 00:00:00.000000000 Z
11
+ date: 2021-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -80,6 +80,7 @@ files:
80
80
  - lib/bashly/models/command.rb
81
81
  - lib/bashly/models/environment_variable.rb
82
82
  - lib/bashly/models/flag.rb
83
+ - lib/bashly/models/script.rb
83
84
  - lib/bashly/polyfills/hash.rb
84
85
  - lib/bashly/settings.rb
85
86
  - lib/bashly/templates/bashly.yml
@@ -120,9 +121,12 @@ files:
120
121
  - lib/bashly/views/command/usage_flags.erb
121
122
  - lib/bashly/views/command/user_lib.erb
122
123
  - lib/bashly/views/command/version_command.erb
124
+ - lib/bashly/views/command/whitelist_filter.erb
123
125
  - lib/bashly/views/environment_variable/usage.erb
124
126
  - lib/bashly/views/flag/case.erb
125
127
  - lib/bashly/views/flag/usage.erb
128
+ - lib/bashly/views/script/header.erb
129
+ - lib/bashly/views/script/wrapper.erb
126
130
  homepage: https://github.com/dannyben/bashly
127
131
  licenses:
128
132
  - MIT
@@ -142,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
146
  - !ruby/object:Gem::Version
143
147
  version: '0'
144
148
  requirements: []
145
- rubygems_version: 3.1.4
149
+ rubygems_version: 3.2.16
146
150
  signing_key:
147
151
  specification_version: 4
148
152
  summary: Bash Command Line Tool Generator