bashly 0.4.2 → 0.5.1

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: 4d486637f9d7ec6604d0495aec9f2396f69153f8cd193c126d51bc7dbc329a62
4
- data.tar.gz: 5c58b05ad9ccb84d432c42228b7594e678b033555e55ea275948d4e70be118c7
3
+ metadata.gz: ca34648c628c4e7fe167d5f5b0d253792e9b4d3c494b253ed68d0127e4935572
4
+ data.tar.gz: 5247da7780a8424dd0a808ace6d182ed4284597e094122d94a8716bfca8f343b
5
5
  SHA512:
6
- metadata.gz: 02fd6e6c50c5d370dde3d50047b0b6d317454c3d48531222711c6341c6e93d263cafa6a7d541bb939ff44a36b6025c9c8411e8f3820157c41e476312f4c64781
7
- data.tar.gz: 031ea1db4c68fb6b780f01862b216178804cdc44f2e86fc66bc11f2910fff6d03ed250d7a01dd1c566d74c8f002ae6e9441bb13292f3e74620db455c993029e2
6
+ metadata.gz: 2145d1f4125d762c3d583f560c4caa9f4b98cfc2500e7e7b9ac977f4284a190a150a26da6e935c4e59c689f5efcd627924a10091cff0d4d91f00c3f60d26b943
7
+ data.tar.gz: 9df4695f43e4c57371f876de1dee3eab587bb227b7b0ee51d52d1772faf119cbd59cb117f5a1e3cbb06ef49b5796cd02b6fecba685b733aa35c51442fe9baf19
data/README.md CHANGED
@@ -15,6 +15,7 @@ Create beautiful bash scripts from simple YAML configuration
15
15
 
16
16
  </div>
17
17
 
18
+
18
19
  ## Table of Contents
19
20
 
20
21
  - [Table of Contents](#table-of-contents)
@@ -22,20 +23,20 @@ Create beautiful bash scripts from simple YAML configuration
22
23
  - [Prerequisites](#prerequisites)
23
24
  - [What is Bashly](#what-is-bashly)
24
25
  - [Usage](#usage)
25
- - [Using the input arguemnts in your code](#using-the-input-arguemnts-in-your-code)
26
+ - [Using the input arguments in your code](#using-the-input-arguments-in-your-code)
26
27
  - [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
28
  - [Configuration Reference](#configuration-reference)
30
29
  - [Command options](#command-options)
31
30
  - [Argument options](#argument-options)
32
31
  - [Flag options](#flag-options)
33
32
  - [Environment Variable options](#environment-variable-options)
33
+ - [Extensible Scripts](#extensible-scripts)
34
34
  - [Real World Examples](#real-world-examples)
35
35
  - [Contributing / Support](#contributing--support)
36
36
 
37
37
  ---
38
38
 
39
+
39
40
  ## Installation
40
41
 
41
42
  ```shell
@@ -83,8 +84,17 @@ Bahsly is responsible for:
83
84
  - **YAML parsing**.
84
85
  - and more.
85
86
 
87
+
86
88
  ## Usage
87
89
 
90
+ The `bashly.yml` file can be set up to generate two types of scripts:
91
+
92
+ 1. Script with commands (for example, like `docker` or `git`).
93
+ 2. Script without commands (for example, like `ls`)
94
+
95
+ This is detected automatically by the contents of the configuration: If it
96
+ contains a `commands` definition, it will generate a script with commands.
97
+
88
98
  In an empty directory, create a sample configuration file by running
89
99
 
90
100
  ```shell
@@ -113,7 +123,7 @@ Finally, edit the files in the `src` folder. Each of your script's commands
113
123
  get their own file. Once you edit, run `bashly generate` again to merge the
114
124
  content from your functions back into the script.
115
125
 
116
- ### Using the input arguemnts in your code
126
+ ### Using the input arguments in your code
117
127
 
118
128
  In order to access the parsed arguments in any of your partial scripts, you
119
129
  may simply access the `$args` associative array.
@@ -152,32 +162,11 @@ $ ./download a --force
152
162
  downloading a with --force
153
163
  ```
154
164
 
155
- ## Examples
156
-
157
- The `bashly.yml` file can be set up to generate two types of scripts:
158
-
159
- 1. Script with commands (for example, like `docker` or `git`).
160
- 2. Script without commands (for example, like `ls`)
161
165
 
162
- This is detected automatically by the contents of the configuration: If it
163
- contains a `commands` definition, it will generate a script with commands.
164
-
165
-
166
- ### Sample configuraiton for a script without commands
167
-
168
- - Generate this script by running `bashly generate --minimal`
169
- - [See the initial sample bashly.yml file](examples/minimal/src/bashly.yml)
170
- - [See the generated bash script](examples/minimal/download)
171
-
172
- ### Sample configuraiton for a script with commands
173
-
174
- - Generate this script by running `bashly generate`
175
- - [See the initial sample bashly.yml file](examples/commands/src/bashly.yml)
176
- - [See the generated bash script](examples/commands/cli)
177
-
178
-
179
- See the [examples](examples) folder for more examples.
166
+ ## Examples
180
167
 
168
+ The [examples folder](examples#readme) contains many detailed and documented
169
+ example configuration files, with their output.
181
170
 
182
171
 
183
172
  ## Configuration Reference
@@ -193,24 +182,26 @@ The `bashly.yml` configuration file consists of these types:
193
182
 
194
183
  ### Command options
195
184
 
196
- Unless otherwise specified, these definitiona can be used for both the root
185
+ Unless otherwise specified, these definitions can be used for both the root
197
186
  command and subcommands (under the `commands` definition).
198
187
 
199
-
200
188
  Option | Description
201
189
  -----------|-------------
202
190
  `name` | The name of the script or subcommand.
203
191
  `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*.
204
192
  `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.
205
193
  `version` | The string to display when using `--version`. *Applicable only in the main command*.
206
- `default` | Setting this to `yes` on any command, will make unrecognized command line arguments to be passed to this command. *Applicable only in subcommands*.
194
+ `default` | Setting this to `true` on any command, will cause any unrecognized command line to be passed to this command. *Applicable only in subcommands*.
195
+ `extensible` | Specify that this command can be [externally extended](#extensible-scripts). *Applicable only in the main command*.
207
196
  `examples` | Specify an array of examples to show when using `--help`. Each example can have multiple lines.
208
- `environment_variables` | Specify an array of environment variables needed by your script.
209
- `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.
210
- `args` | Specify the array of positional arguments this script needs.
211
- `flags` | Specify the array of option flags this script needs.
197
+ `environment_variables` | Specify an array of [environment variables](#environment-variable-options) needed by your script.
198
+ `commands` | Specify the array of [commands](#command-options). Each command will have its own args and flags. Note: if `commands` is provided, you cannot specify flags or args at the same level.
199
+ `args` | Specify the array of [positional arguments](#argument-options) this script needs.
200
+ `flags` | Specify the array of option [flags](#flag-options) this script needs.
201
+ `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`.
212
202
  `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.
213
203
  `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.
204
+ `footer` | Add a custom message that will be displayed at the end of the `--help` text.
214
205
 
215
206
  ### Argument options
216
207
 
@@ -247,9 +238,7 @@ The `-v` and `-h` flags will be used as the short options for `--version` and
247
238
  `--help` respectively **only if you are not using them in any of your own
248
239
  flags**.
249
240
 
250
- ### Environment Variable options
251
-
252
- The below configuration generates this environment variable usage text:
241
+ ### Environment variable options
253
242
 
254
243
  If an environment variable is defined as required (false by default), the
255
244
  execution of the script will be halted with a friendly error if it is not
@@ -262,6 +251,81 @@ set.
262
251
  `required` | Specify if this variable is required.
263
252
 
264
253
 
254
+ ## Extensible Scripts
255
+
256
+ You may configure your generated bash script to delegate any unknown command
257
+ to an external executable, by setting the `extensible` option to either `true`,
258
+ or to a different external command.
259
+
260
+ This is similar to how `git` works. When you execute `git whatever`, the `git`
261
+ command will look for a file named `git-whatever` in the path, and execute it.
262
+
263
+ Note that this option cannot be specified together with the `default` option,
264
+ since both specify a handler for unknown commands.
265
+
266
+ Bashly supports two operation modes.
267
+
268
+ ### Extension Mode (`extensible: true`)
269
+
270
+ By setting `extensible` to `true`, a specially named executable will be called
271
+ when an unknown command is called by the user.
272
+
273
+ Given this `bashly.yml` configuration:
274
+
275
+ ```yaml
276
+ name: myscript
277
+ help: Example
278
+ version: 0.1.0
279
+ extensible: true
280
+
281
+ commands:
282
+ - name: upload
283
+ help: Upload a file
284
+ ```
285
+
286
+ And this user command:
287
+
288
+ ```
289
+ $ myscript something
290
+
291
+ ```
292
+
293
+ The generated script will look for an executable named `myscript-something`
294
+ in the path. If found, it will be called.
295
+
296
+ See the [extensible example](examples/extensible).
297
+
298
+
299
+ ### Delegate Mode (`extensible: <executable name>`)
300
+
301
+ By setting `extensible` to any string, unknown command calls by the user will
302
+ be delegated to the executable with that name.
303
+
304
+ Given this `bashly.yml` configuration:
305
+
306
+ ```yaml
307
+ name: mygit
308
+ help: Example
309
+ version: 0.1.0
310
+ extensible: git
311
+
312
+ commands:
313
+ - name: push
314
+ help: Push to my repository
315
+ ```
316
+
317
+ And this user command:
318
+
319
+ ```
320
+ $ mygit status
321
+
322
+ ```
323
+
324
+ The generated script will execute `git status`.
325
+
326
+ See the [extensible-delegate example](examples/extensible-delegate).
327
+
328
+
265
329
  ## Real World Examples
266
330
 
267
331
  - [Rush][rush] - a Personal Package Manager
@@ -274,9 +338,9 @@ set.
274
338
  If you experience any issue, have a question or a suggestion, or if you wish
275
339
  to contribute, feel free to [open an issue][issues].
276
340
 
341
+
342
+
277
343
  [issues]: https://github.com/DannyBen/bashly/issues
278
344
  [rush]: https://github.com/DannyBen/rush-cli
279
345
  [alf]: https://github.com/DannyBen/alf
280
346
  [git-changelog]: https://github.com/DannyBen/git-changelog
281
-
282
-
@@ -16,7 +16,6 @@ class String
16
16
  strip!
17
17
  split("\n").collect! do |line|
18
18
  if line.length > length
19
- line.gsub!(/([^\s]{#{length}})([^\s$])/, "\\1 \\2")
20
19
  line.gsub(/(.{1,#{length}})(\s+|$)/, "\\1\n").rstrip
21
20
  else
22
21
  line
@@ -8,12 +8,15 @@ module Bashly
8
8
  OPTION_KEYS = %i[
9
9
  allowed
10
10
  arg
11
+ catch_all
11
12
  default
12
13
  dependencies
13
14
  description
14
15
  environment_variables
15
16
  examples
17
+ extensible
16
18
  flags
19
+ footer
17
20
  group
18
21
  help
19
22
  long
@@ -28,6 +28,30 @@ 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
+ # Returns a used defined help string for the catch_all directive
45
+ def catch_all_help
46
+ return nil unless catch_all
47
+
48
+ if catch_all.is_a?(Hash) and catch_all['help'].is_a?(String)
49
+ catch_all['help']
50
+ else
51
+ nil
52
+ end
53
+ end
54
+
31
55
  # Returns only the names of the Commands
32
56
  def command_names
33
57
  commands.map &:name
@@ -159,6 +183,7 @@ module Bashly
159
183
  result << arg.usage_string
160
184
  end
161
185
  result << "[options]" unless flags.empty?
186
+ result << "[#{catch_all_label}]" if catch_all
162
187
  result.join " "
163
188
  end
164
189
 
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -0,0 +1,45 @@
1
+ # :command.command_fallback
2
+ <%- if default_command -%>
3
+ "" )
4
+ <%= function_name %>_usage
5
+ exit 1
6
+ ;;
7
+
8
+ * )
9
+ action="<%= default_command.name %>"
10
+ <%= default_command.function_name %>_parse_requirements "$@"
11
+ shift $#
12
+ ;;
13
+ <%- elsif extensible.is_a? String -%>
14
+ "" )
15
+ <%= function_name %>_usage
16
+ exit 1
17
+ ;;
18
+
19
+ * )
20
+ if [[ -x "$(command -v "<%= extensible %>")" ]]; then
21
+ exec <%= extensible %> "$@"
22
+ else
23
+ <%= function_name %>_usage
24
+ exit 1
25
+ fi
26
+ <%- elsif extensible -%>
27
+ "" )
28
+ <%= function_name %>_usage
29
+ exit 1
30
+ ;;
31
+
32
+ * )
33
+ if [[ -x "$(command -v "<%= function_name %>-$action")" ]]; then
34
+ shift
35
+ exec "<%= function_name %>-$action" "$@"
36
+ else
37
+ <%= function_name %>_usage
38
+ exit 1
39
+ fi
40
+ <%- else -%>
41
+ * )
42
+ <%= function_name %>_usage
43
+ exit 1
44
+ ;;
45
+ <%- end -%>
@@ -15,25 +15,7 @@ case $action in
15
15
  ;;
16
16
 
17
17
  <%- end -%>
18
- <%- if default_command -%>
19
- "" )
20
- <%= function_name %>_usage
21
- exit 1
22
- ;;
23
-
24
- * )
25
- action="<%= default_command.name %>"
26
- <%= default_command.function_name %>_parse_requirements "$@"
27
- shift $#
28
- ;;
29
-
30
- <%- else -%>
31
- * )
32
- <%= function_name %>_usage
33
- exit 1
34
- ;;
35
-
36
- <%- end -%>
18
+ <%= render :command_fallback %>
37
19
  esac
38
20
  <%- else -%>
39
21
  action="<%= action_name %>"
@@ -0,0 +1,2 @@
1
+ printf "<%= footer.gsub("\n", '\n').gsub('"', '\"') %>\n"
2
+ echo
@@ -7,4 +7,13 @@ inspect_args() {
7
7
  else
8
8
  echo args: none
9
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
10
19
  }
@@ -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" -%>
@@ -37,9 +37,10 @@
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
+ <%= render(:footer).indent 4 if footer %>
43
44
 
44
45
  fi
45
46
  }
@@ -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 -%>
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.2
4
+ version: 0.5.1
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: 2021-03-04 00:00:00.000000000 Z
11
+ date: 2021-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -92,6 +92,7 @@ files:
92
92
  - lib/bashly/templates/strings.yml
93
93
  - lib/bashly/version.rb
94
94
  - lib/bashly/views/argument/usage.erb
95
+ - lib/bashly/views/command/command_fallback.erb
95
96
  - lib/bashly/views/command/command_filter.erb
96
97
  - lib/bashly/views/command/command_functions.erb
97
98
  - lib/bashly/views/command/default_assignments.erb
@@ -101,6 +102,7 @@ files:
101
102
  - lib/bashly/views/command/dependencies_filter.erb
102
103
  - lib/bashly/views/command/environment_variables_filter.erb
103
104
  - lib/bashly/views/command/fixed_flags_filter.erb
105
+ - lib/bashly/views/command/footer.erb
104
106
  - lib/bashly/views/command/function.erb
105
107
  - lib/bashly/views/command/initialize.erb
106
108
  - lib/bashly/views/command/inspect_args.erb
@@ -146,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
148
  - !ruby/object:Gem::Version
147
149
  version: '0'
148
150
  requirements: []
149
- rubygems_version: 3.2.3
151
+ rubygems_version: 3.2.16
150
152
  signing_key:
151
153
  specification_version: 4
152
154
  summary: Bash Command Line Tool Generator