bashly 0.6.1 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +31 -350
  3. data/lib/bashly/commands/add.rb +1 -1
  4. data/lib/bashly/models/command.rb +18 -2
  5. data/lib/bashly/templates/lib/config.sh +5 -5
  6. data/lib/bashly/templates/strings.yml +1 -0
  7. data/lib/bashly/version.rb +1 -1
  8. data/lib/bashly/views/argument/usage.erb +4 -4
  9. data/lib/bashly/views/command/catch_all_filter.erb +7 -0
  10. data/lib/bashly/views/command/command_fallback.erb +5 -5
  11. data/lib/bashly/views/command/command_filter.erb +5 -5
  12. data/lib/bashly/views/command/command_functions.erb +2 -2
  13. data/lib/bashly/views/command/default_assignments.erb +4 -4
  14. data/lib/bashly/views/command/dependencies_filter.erb +4 -4
  15. data/lib/bashly/views/command/environment_variables_filter.erb +10 -5
  16. data/lib/bashly/views/command/fixed_flags_filter.erb +7 -7
  17. data/lib/bashly/views/command/initialize.erb +6 -1
  18. data/lib/bashly/views/command/parse_requirements.erb +6 -5
  19. data/lib/bashly/views/command/parse_requirements_case.erb +11 -11
  20. data/lib/bashly/views/command/parse_requirements_while.erb +5 -5
  21. data/lib/bashly/views/command/required_args_filter.erb +2 -2
  22. data/lib/bashly/views/command/required_flags_filter.erb +4 -4
  23. data/lib/bashly/views/command/usage_args.erb +6 -6
  24. data/lib/bashly/views/command/usage_commands.erb +12 -12
  25. data/lib/bashly/views/command/usage_environment_variables.erb +2 -2
  26. data/lib/bashly/views/command/usage_examples.erb +2 -2
  27. data/lib/bashly/views/command/usage_fixed_flags.erb +8 -8
  28. data/lib/bashly/views/command/usage_flags.erb +2 -2
  29. data/lib/bashly/views/command/user_lib.erb +2 -2
  30. data/lib/bashly/views/command/whitelist_filter.erb +4 -4
  31. data/lib/bashly/views/environment_variable/usage.erb +3 -0
  32. data/lib/bashly/views/flag/case.erb +3 -3
  33. data/lib/bashly/views/flag/usage.erb +4 -4
  34. data/lib/bashly.rb +0 -1
  35. metadata +11 -13
  36. data/lib/bashly/polyfills/hash.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a6c888335f32b6223149d91ed739e189ffbc6921afec05ff709380c76387338
4
- data.tar.gz: b964b4ac7a5fa86f8766b350a3240ee00882be5cfc574e97f001a832a506e342
3
+ metadata.gz: 5b02a163470ebeb4c59a97f475b40b760477d36df16189addb48049b11b8842a
4
+ data.tar.gz: 625b89b6a09fc59f6a4a19fceaf05f645dec0c45cc33cda3a445fe123f43dbb6
5
5
  SHA512:
6
- metadata.gz: e1e2757a735e55ffc4d4b27633d6df020184521ed8eb6377c0f26f8edd7442d28fb2a3c56c056de4558aab2204f7d522e15df6374f1962fcbaf26226f590d22b
7
- data.tar.gz: a8aa77fba152f005136ff8ee8aacdc7236f15975042c4066f6d94e7e400133e2ca4137ffbbe9bc6f458c2aae2784aa956721d9179862cd78bf95ec6f99f39bd3
6
+ metadata.gz: 6e2bd2c31ab003d916efa2590e8571b7cbf3b6e88c3cee9122f5bc24d57b9624e52d7589bffdf2604132d55b040ff735effc02d49e4b6a8479817122ce98f612
7
+ data.tar.gz: 8fe5d95ea5061d88fb0b0da02266b69ed6530379d3e030d5f71fd1edf8bd97c3690ea82a89c36bb55a27790363ccd52be4de9e4aa1ba5ae07cb0c8ce87b8fd89
data/README.md CHANGED
@@ -3,384 +3,67 @@
3
3
 
4
4
  # Bashly - Bash CLI Framework and Generator
5
5
 
6
- Create beautiful bash scripts from simple YAML configuration
6
+ Create feature-rich bash scripts using simple YAML configuration
7
7
 
8
8
  [![Gem Version](https://badge.fury.io/rb/bashly.svg)](https://badge.fury.io/rb/bashly)
9
9
  [![Build Status](https://github.com/DannyBen/bashly/workflows/Test/badge.svg)](https://github.com/DannyBen/bashly/actions?query=workflow%3ATest)
10
10
  [![Maintainability](https://api.codeclimate.com/v1/badges/8cf89047e50ca601e431/maintainability)](https://codeclimate.com/github/DannyBen/bashly/maintainability)
11
11
 
12
+ ## [bashly.dannyb.co](https://bashly.dannyb.co)
13
+
12
14
  ---
13
15
 
14
16
  ![demo](demo/cast.svg)
15
17
 
16
18
  </div>
17
19
 
20
+ Bashly is a command line application (written in Ruby) that lets you
21
+ generate feature-rich bash command line tools.
18
22
 
19
- ## Table of Contents
20
-
21
- - [Table of Contents](#table-of-contents)
22
- - [Installation](#installation)
23
- - [Prerequisites](#prerequisites)
24
- - [What is Bashly](#what-is-bashly)
25
- - [Usage](#usage)
26
- - [Using the input arguments in your code](#using-the-input-arguments-in-your-code)
27
- - [Examples](#examples)
28
- - [Configuration Reference](#configuration-reference)
29
- - [Command options](#command-options)
30
- - [Argument options](#argument-options)
31
- - [Flag options](#flag-options)
32
- - [Environment Variable options](#environment-variable-options)
33
- - [Extensible Scripts](#extensible-scripts)
34
- - [Bash Completions](#bash-completions)
35
- - [Real World Examples](#real-world-examples)
36
- - [Contributing / Support](#contributing--support)
37
-
38
- ---
39
-
40
-
41
- ## Installation
23
+ Bashly lets you focus on your specific code, without worrying about command line
24
+ argument parsing, usage texts, error messages and other functions that are
25
+ usually handled by a framework in any other programming language.
42
26
 
43
- ```shell
44
- $ gem install bashly
45
- ```
27
+ It is available both as a [ruby gem](https://rubygems.org/gems/bashly) and as
28
+ a [docker image](https://hub.docker.com/r/dannyben/bashly).
46
29
 
47
- or with Docker:
48
30
 
49
- ```shell
50
- $ alias bashly='docker run --rm -it --volume "$PWD:/app" dannyben/bashly'
51
- ```
31
+ ## Documentation
52
32
 
53
- ## Prerequisites
33
+ - [Bashly Homepage][docs]
34
+ - [Examples][examples]
54
35
 
55
- The bash scripts generated by bashly require bash 4 or higher due to heavy
56
- use of associative arrays.
36
+ ## How it works
57
37
 
38
+ 1. You provide a YAML configuration file, describing commands, sub-commands,
39
+ arguments, and flags. Running `bashly init` creates an initial sample YAML
40
+ file for you ([example](https://github.com/DannyBen/bashly/tree/master/examples/minimal#bashlyyml)).
41
+ 2. Bashly then automatically generates a bash script (when you run
42
+ `bashly generate`) that can parse and validate user input, provide help
43
+ messages, and run your code for each command ([example](https://github.com/DannyBen/bashly/blob/master/examples/minimal/download)).
44
+ 3. Your code for each command is kept in a separate file, and can be merged
45
+ again if you change it ([example](https://github.com/DannyBen/bashly/blob/master/examples/minimal/src/root_command.sh)).
58
46
 
59
- ## What is Bashly
47
+ ## Features
60
48
 
61
- Bashly is a command line application (written in Ruby) that lets you generate
62
- feature-rich bash command line tools.
63
-
64
- The design intention is to let you focus on your specific code, without
65
- worrying about command line argument parsing, usage texts, error messages
66
- and other functions that are usually handled by a framework in any other
67
- programming language.
68
-
69
- Bahsly is responsible for:
49
+ Bashly is responsible for:
70
50
 
71
51
  - Generating a **single, standalone bash script**.
72
- - Generating **usage texts** and help screens, showing your tool's arguments,
73
- flags and commands (works for subcommands also).
52
+ - Generating **usage texts** and help screens, showing your tool's arguments, flags and commands (works for sub-commands also).
74
53
  - Parsing the user's command line and extracting:
75
54
  - Optional or required **positional arguments**.
76
55
  - Optional or required **option flags** (with or without flag arguments).
77
- - **Commands** (and subcommands).
56
+ - **Commands** (and sub-commands).
78
57
  - Standard flags (like **--help** and **--version**).
79
58
  - Preventing your script from running unless the command line is valid.
80
- - Providing you with a place to input your code for each of the functions
81
- your tool performs, and merging it back to the final script.
82
- - Providing you with additional (optional) framework-style, standard
83
- library functions:
59
+ - Providing you with a place to input your code for each of the functions your tool performs, and merging it back to the final script.
60
+ - Providing you with additional (optional) framework-style, standard library functions:
84
61
  - **Color output**.
85
62
  - **Config file management** (INI format).
86
63
  - **YAML parsing**.
87
64
  - **Bash completions**.
88
65
  - and more.
89
66
 
90
-
91
- ## Usage
92
-
93
- The `bashly.yml` file can be set up to generate two types of scripts:
94
-
95
- 1. Script with commands (for example, like `docker` or `git`).
96
- 2. Script without commands (for example, like `ls`)
97
-
98
- This is detected automatically by the contents of the configuration: If it
99
- contains a `commands` definition, it will generate a script with commands.
100
-
101
- In an empty directory, create a sample configuration file by running
102
-
103
- ```shell
104
- $ bashly init
105
- # or, to generate a simpler configuration:
106
- $ bashly init --minimal
107
- ```
108
-
109
- This will create a sample `src/bashly.yml` file.
110
- You can edit this file to specify which arguments, flags and commands you
111
- need in your bash script.
112
-
113
- Then, generate an initial bash script and function placeholder scripts by
114
- running
115
-
116
- ```shell
117
- $ bashly generate
118
- ```
119
-
120
- This will:
121
-
122
- 1. Create the bash executable script.
123
- 2. Create files for you to edit in the `src` folder.
124
-
125
- Finally, edit the files in the `src` folder. Each of your script's commands
126
- get their own file. Once you edit, run `bashly generate` again to merge the
127
- content from your functions back into the script.
128
-
129
- ### Using the input arguments in your code
130
-
131
- In order to access the parsed arguments in any of your partial scripts, you
132
- may simply access the `$args` associative array.
133
-
134
- For example:
135
-
136
- 1. Generate a minimal configuration with `bashly init --minimal`
137
- 2. Generate the bash script with `bashly generate`
138
- 3. Run the script with `./download hello --force`
139
-
140
- You will notice that all the arguments of the associative array are printed
141
- on screen. This is done by the `inspect_args` function that was inserted into
142
- the generated partial script `src/root_command.sh`.
143
-
144
- You can now access these variables by modifying `sec/root_command.sh` like
145
- this:
146
-
147
-
148
- ```bash
149
- # src/root_command.sh
150
- source_url=${args[source]}
151
- force=${args[--force]}
152
-
153
- if [[ $force ]]; then
154
- echo "downloading $source_url with --force"
155
- else
156
- echo "downloading $source_url"
157
- fi
158
- ```
159
-
160
- After editing the file, run `bashly generate` (or `bashly g` for short) and
161
- run:
162
-
163
- ```
164
- $ ./download a --force
165
- downloading a with --force
166
- ```
167
-
168
-
169
- ## Examples
170
-
171
- The [examples folder](examples#readme) contains many detailed and documented
172
- example configuration files, with their output.
173
-
174
-
175
- ## Configuration Reference
176
-
177
- The `bashly.yml` configuration file consists of these types:
178
-
179
- - [Command](#command-options) - defines the root command as well as any
180
- subcommand.
181
- - [Argument](#argument-options) - defines positional arguments.
182
- - [Flag](#flag-options) - defines option flags.
183
- - [Environment Variable](#environment-variable-options) - defines
184
- environment variables required (or desired) by your script.
185
-
186
- ### Command options
187
-
188
- Unless otherwise specified, these definitions can be used for both the root
189
- command and subcommands (under the `commands` definition).
190
-
191
- Option | Description
192
- -----------|-------------
193
- `name` | The name of the script or subcommand.
194
- `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*.
195
- `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.
196
- `version` | The string to display when using `--version`. *Applicable only in the main command*.
197
- `default` | Setting this to `true` on any command, will cause any unrecognized command line to be passed to this command. *Applicable only in subcommands*.
198
- `extensible` | Specify that this command can be [externally extended](#extensible-scripts). *Applicable only in the main command*.
199
- `examples` | Specify an array of examples to show when using `--help`. Each example can have multiple lines.
200
- `environment_variables` | Specify an array of [environment variables](#environment-variable-options) needed by your script.
201
- `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.
202
- `args` | Specify the array of [positional arguments](#argument-options) this script needs.
203
- `flags` | Specify the array of option [flags](#flag-options) this script needs.
204
- `completions` | Specify an array of additional completion suggestions when used in conjunction with `bashly add comp`. See [Bash Completions](#bash-completions).
205
- `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`.
206
- `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.
207
- `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.
208
- `footer` | Add a custom message that will be displayed at the end of the `--help` text.
209
-
210
- ### Argument options
211
-
212
- The argument's value will be available to you as `${args[user]}` in your
213
- bash function.
214
-
215
- Option | Description
216
- -----------|-------------
217
- `name` | The name of the argument.
218
- `help` | The message to display when using `--help`. Can have multiple lines.
219
- `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.
220
- `default` | The value to use in case it is not provided by the user. Implies that this argument is optional.
221
- `allowed` | Limit the allowed values by providing an array.
222
-
223
- ### Flag options
224
-
225
- The flag's value will be available to you as `${args[--output]}` in your
226
- bash function (regardless of whether the user provided it with the long or
227
- short form).
228
-
229
- Option | Description
230
- -----------|-------------
231
- `long` | The long form of the flag.
232
- `short` | The short form of the flag.
233
- `help` | The text to display when using `--help`. Can have multiple lines.
234
- `arg` | If the flag requires an argument, specify its name here.
235
- `required` | Specify if this flag is required.
236
- `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.
237
- `allowed` | For flags with an argument, you can limit the allowed values by providing an array.
238
-
239
- #### Special handling for -v and -h
240
-
241
- The `-v` and `-h` flags will be used as the short options for `--version` and
242
- `--help` respectively **only if you are not using them in any of your own
243
- flags**.
244
-
245
- ### Environment variable options
246
-
247
- If an environment variable is defined as required (false by default), the
248
- execution of the script will be halted with a friendly error if it is not
249
- set.
250
-
251
- Option | Description
252
- -----------|-------------
253
- `name` | The name of the variable (it will be automatically capitalized).
254
- `help` | The message to display when using --help. Can have multiple lines.
255
- `required` | Specify if this variable is required.
256
-
257
-
258
- ## Extensible Scripts
259
-
260
- You may configure your generated bash script to delegate any unknown command
261
- to an external executable, by setting the `extensible` option to either `true`,
262
- or to a different external command.
263
-
264
- This is similar to how `git` works. When you execute `git whatever`, the `git`
265
- command will look for a file named `git-whatever` in the path, and execute it.
266
-
267
- Note that this option cannot be specified together with the `default` option,
268
- since both specify a handler for unknown commands.
269
-
270
- The `extensible` option supports two operation modes:
271
-
272
- ### Extension Mode (`extensible: true`)
273
-
274
- By setting `extensible` to `true`, a specially named executable will be called
275
- when an unknown command is called by the user.
276
-
277
- Given this `bashly.yml` configuration:
278
-
279
- ```yaml
280
- name: myscript
281
- help: Example
282
- version: 0.1.0
283
- extensible: true
284
-
285
- commands:
286
- - name: upload
287
- help: Upload a file
288
- ```
289
-
290
- And this user command:
291
-
292
- ```
293
- $ myscript something
294
-
295
- ```
296
-
297
- The generated script will look for an executable named `myscript-something`
298
- in the path. If found, it will be called.
299
-
300
- See the [extensible example](examples/extensible).
301
-
302
-
303
- ### Delegate Mode (`extensible: <executable name>`)
304
-
305
- By setting `extensible` to any string, unknown command calls by the user will
306
- be delegated to the executable with that name.
307
-
308
- Given this `bashly.yml` configuration:
309
-
310
- ```yaml
311
- name: mygit
312
- help: Example
313
- version: 0.1.0
314
- extensible: git
315
-
316
- commands:
317
- - name: push
318
- help: Push to my repository
319
- ```
320
-
321
- And this user command:
322
-
323
- ```
324
- $ mygit status
325
-
326
- ```
327
-
328
- The generated script will execute `git status`.
329
-
330
- See the [extensible-delegate example](examples/extensible-delegate).
331
-
332
-
333
- ## Bash Completions
334
-
335
- Bashly comes with built-in bash completions generator, provided by the
336
- [completely][completely] gem.
337
-
338
- By running any of the `bashly add comp` commands, you can add this
339
- functionality to your script in one of three ways:
340
-
341
- - `bashly add comp function` - creates a function in your `./src/lib` directory
342
- that echoes a completion script. You can then call this function from any
343
- command (for example `yourcli completions`) and your users will be able to
344
- install the completions by running `eval "$(yourcli completions)"`.
345
- - `bashly add comp script` - creates a standalone completion script that can be
346
- sourced or copies to the system's bash completions directory.
347
- - `bashly add comp yaml` - creates the "raw data" YAML file. This is intended
348
- mainly for development purposes.
349
-
350
- The bash completions generation is completely automatic, and you will have to
351
- rerun the `bashly add comp *` command whenever you change your `bashly.yml`
352
- file.
353
-
354
- In addition to suggesting subcommands and flags, you can instruct bashly to
355
- also suggest files, directories, users, git branches and more. To do this,
356
- add another option in your `bashly.yml` on the command you wish to alter:
357
-
358
- ```yaml
359
- # bashly.yml
360
- commands:
361
- - name: upload
362
- help: Upload a file
363
- completions:
364
- - <directory>
365
- - <user>
366
- - $(git branch 2> /dev/null)
367
-
368
- ```
369
-
370
- - Anything between `<...>` will be added using the `compgen -A action` flag.
371
- - Anything else, will be appended to the `compgen -W` flag.
372
-
373
- For more information about these custom completions, see the documentation for
374
- the [completely][completely] gem.
375
-
376
-
377
- ## Real World Examples
378
-
379
- - [Rush][rush] - a Personal Package Manager
380
- - [Alf][alf] - a generator for bash aliases and sub-aliases
381
- - [git-changelog][git-changelog] - a change log generator
382
-
383
-
384
67
  ## Contributing / Support
385
68
 
386
69
  If you experience any issue, have a question or a suggestion, or if you wish
@@ -389,8 +72,6 @@ to contribute, feel free to [open an issue][issues].
389
72
 
390
73
 
391
74
  [issues]: https://github.com/DannyBen/bashly/issues
392
- [rush]: https://github.com/DannyBen/rush-cli
393
- [alf]: https://github.com/DannyBen/alf
394
- [git-changelog]: https://github.com/DannyBen/git-changelog
395
- [completely]: https://github.com/DannyBen/completely
396
- [compgen]: https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
75
+ [docs]: https://bashly.dannyb.co/
76
+ [examples]: https://github.com/DannyBen/bashly/tree/master/examples#bashly-examples
77
+
@@ -13,7 +13,7 @@ module Bashly
13
13
 
14
14
  option "-f --force", "Overwrite existing files"
15
15
 
16
- param "FORMAT", "Output format, can be one of:\n function : generate a function file to be included in your script.\n script : generate a standalone bash completions script\n yaml : generate a yaml compatible with 'completely'"
16
+ param "FORMAT", "Output format, can be one of:\n function : generate a function file to be included in your script.\n script : generate a standalone bash completions script.\n yaml : generate a yaml compatible with completely."
17
17
  param "OUTPUT", "For the 'comp function' command: Name of the generated function.\nFor the 'comp script' or 'comp yaml' commands: path to output file.\nIn all cases, this is optional and will have sensible defaults."
18
18
 
19
19
  command "strings", "Copy an additional configuration file to your project, allowing you to customize all the tips and error strings."
@@ -5,7 +5,7 @@ module Bashly
5
5
 
6
6
  # Returns the name to be used as an action.
7
7
  # - If it is the root command, the action is "root"
8
- # - Else, it is all the parents, except the first tone (root) joined
8
+ # - Else, it is all the parents, except the first one (root) joined
9
9
  # by space. For example, for a command like "docker container run"
10
10
  # the action name is "container run".
11
11
  def action_name
@@ -54,6 +54,17 @@ module Bashly
54
54
  end
55
55
  end
56
56
 
57
+ # Returns true if catch_all is required
58
+ def catch_all_required?
59
+ catch_all.is_a?(Hash) and catch_all['required']
60
+ end
61
+
62
+ # Returns a string suitable for catch_all Usage pattern
63
+ def catch_all_usage
64
+ return nil unless catch_all
65
+ catch_all_required? ? catch_all_label : "[#{catch_all_label}]"
66
+ end
67
+
57
68
  # Returns only the names of the Commands
58
69
  def command_names
59
70
  commands.map &:name
@@ -92,6 +103,11 @@ module Bashly
92
103
  commands.find { |c| c.default }
93
104
  end
94
105
 
106
+ # Returns an array of all the default Environment Variables
107
+ def default_environment_variables
108
+ environment_variables.select &:default
109
+ end
110
+
95
111
  # Returns an array of all the default Flags
96
112
  def default_flags
97
113
  flags.select &:default
@@ -185,7 +201,7 @@ module Bashly
185
201
  result << arg.usage_string
186
202
  end
187
203
  result << "[options]" unless flags.empty?
188
- result << "[#{catch_all_label}]" if catch_all
204
+ result << catch_all_usage if catch_all
189
205
  result.join " "
190
206
  end
191
207
 
@@ -10,14 +10,14 @@
10
10
  # ---
11
11
 
12
12
  # Create a new config file.
13
- # There is normally no need to use this fucntion, it is used by other
13
+ # There is normally no need to use this function, it is used by other
14
14
  # functions as needed.
15
15
  config_init() {
16
16
  CONFIG_FILE=${CONFIG_FILE:=config.ini}
17
17
  [[ -f "$CONFIG_FILE" ]] || touch "$CONFIG_FILE"
18
18
  }
19
19
 
20
- # Get a value from the config
20
+ # Get a value from the config.
21
21
  # Usage: result=$(config_get hello)
22
22
  config_get() {
23
23
  key=$1
@@ -66,7 +66,7 @@ config_set() {
66
66
  printf "%b\n" "$output" > "$CONFIG_FILE"
67
67
  }
68
68
 
69
- # Delete a key from teh config.
69
+ # Delete a key from the config.
70
70
  # Usage: config_del key
71
71
  config_del() {
72
72
  key=$1
@@ -92,7 +92,7 @@ config_show() {
92
92
  cat "$CONFIG_FILE"
93
93
  }
94
94
 
95
- # Return an array of the keys in the config file
95
+ # Return an array of the keys in the config file.
96
96
  # Usage:
97
97
  #
98
98
  # for k in $(config_keys); do
@@ -114,7 +114,7 @@ config_keys() {
114
114
  echo "${keys[@]}"
115
115
  }
116
116
 
117
- # Returns true if the specified key exists in the config file
117
+ # Returns true if the specified key exists in the config file.
118
118
  # Usage:
119
119
  #
120
120
  # if config_has_key "key" ; then
@@ -31,3 +31,4 @@ missing_required_environment_variable: "missing required environment variable: %
31
31
  missing_dependency: "missing dependency: %{dependency}"
32
32
  disallowed_flag: "%{name} must be one of: %{allowed}"
33
33
  disallowed_argument: "%{name} must be one of: %{allowed}"
34
+ unsupported_bash_version: "bash version 4 or higher is required"
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.5"
3
3
  end
@@ -1,10 +1,10 @@
1
1
  # :argument.usage
2
2
  echo " <%= name.upcase %>"
3
3
  printf "<%= help.wrap(76).indent(4).sanitize_for_print %>\n"
4
- <%- if allowed -%>
4
+ % if allowed
5
5
  printf " <%= strings[:allowed] % { values: allowed.join(', ') } -%>\n"
6
- <%- end -%>
7
- <%- if default -%>
6
+ % end
7
+ % if default
8
8
  printf " <%= strings[:default] % { value: default } -%>\n"
9
- <%- end -%>
9
+ % end
10
10
  echo
@@ -0,0 +1,7 @@
1
+ # :command.catch_all_filter
2
+ % if catch_all_required?
3
+ if [[ ${#other_args[@]} -eq 0 ]]; then
4
+ printf "<%= strings[:missing_required_argument] % { arg: catch_all_label, usage: usage_string } %>\n"
5
+ exit 1
6
+ fi
7
+ % end
@@ -1,5 +1,5 @@
1
1
  # :command.command_fallback
2
- <%- if default_command -%>
2
+ % if default_command
3
3
  "" )
4
4
  <%= function_name %>_usage
5
5
  exit 1
@@ -10,7 +10,7 @@
10
10
  <%= default_command.function_name %>_parse_requirements "$@"
11
11
  shift $#
12
12
  ;;
13
- <%- elsif extensible.is_a? String -%>
13
+ % elsif extensible.is_a? String
14
14
  "" )
15
15
  <%= function_name %>_usage
16
16
  exit 1
@@ -23,7 +23,7 @@
23
23
  <%= function_name %>_usage
24
24
  exit 1
25
25
  fi
26
- <%- elsif extensible -%>
26
+ % elsif extensible
27
27
  "" )
28
28
  <%= function_name %>_usage
29
29
  exit 1
@@ -37,9 +37,9 @@
37
37
  <%= function_name %>_usage
38
38
  exit 1
39
39
  fi
40
- <%- else -%>
40
+ % else
41
41
  * )
42
42
  <%= function_name %>_usage
43
43
  exit 1
44
44
  ;;
45
- <%- end -%>
45
+ % end
@@ -1,12 +1,12 @@
1
1
  # :command.command_filter
2
- <%- if commands.any? -%>
2
+ % if commands.any?
3
3
  action=$1
4
4
 
5
5
  case $action in
6
6
  -* )
7
7
  ;;
8
8
 
9
- <%- commands.each do |command| -%>
9
+ % commands.each do |command|
10
10
  <%= command.aliases.join " | " %> )
11
11
  action="<%= command.name %>"
12
12
  shift
@@ -14,9 +14,9 @@ case $action in
14
14
  shift $#
15
15
  ;;
16
16
 
17
- <%- end -%>
17
+ % end
18
18
  <%= render :command_fallback %>
19
19
  esac
20
- <%- else -%>
20
+ % else
21
21
  action="<%= action_name %>"
22
- <%- end -%>
22
+ % end
@@ -1,4 +1,4 @@
1
1
  # :command.command_functions
2
- <%- deep_commands.each do |command| -%>
2
+ % deep_commands.each do |command|
3
3
  <%= command.render :function unless command.commands.any? %>
4
- <%- end -%>
4
+ % end
@@ -1,7 +1,7 @@
1
1
  # :command.default_assignments
2
- <%- default_args.each do |arg| -%>
2
+ % default_args.each do |arg|
3
3
  [[ -n ${args[<%= arg.name %>]} ]] || args[<%= arg.name %>]="<%= arg.default %>"
4
- <%- end -%>
5
- <%- default_flags.each do |flag| -%>
4
+ % end
5
+ % default_flags.each do |flag|
6
6
  [[ -n ${args[<%= flag.long %>]} ]] || args[<%= flag.long %>]="<%= flag.default %>"
7
- <%- end -%>
7
+ % end
@@ -1,9 +1,9 @@
1
1
  # :command.dependencies_filter
2
- <%- if dependencies -%>
3
- <%- dependencies.each do |dependency| -%>
2
+ % if dependencies
3
+ % dependencies.each do |dependency|
4
4
  if ! [[ -x "$(command -v <%= dependency %>)" ]]; then
5
5
  printf "<%= strings[:missing_dependency] % { dependency: dependency } -%>\n"
6
6
  exit 1
7
7
  fi
8
- <%- end -%>
9
- <%- end -%>
8
+ % end
9
+ % end
@@ -1,9 +1,14 @@
1
1
  # :command.environment_variables_filter
2
- <%- if required_environment_variables.any? -%>
3
- <%- required_environment_variables.each do |env_var| -%>
2
+ % if default_environment_variables.any?
3
+ % default_environment_variables.each do |env_var|
4
+ export <%= env_var.name.upcase %>="${<%= env_var.name.upcase %>:-<%= env_var.default %>}"
5
+ % end
6
+ % end
7
+ % if required_environment_variables.any?
8
+ % required_environment_variables.each do |env_var|
4
9
  if [[ -z "$<%= env_var.name.upcase %>" ]]; then
5
- printf "<%= strings[:missing_required_environment_variable] % { var: env_var.name.upcase } -%>\n"
10
+ printf "<%= strings[:missing_required_environment_variable] % { var: env_var.name.upcase } %>\n"
6
11
  exit 1
7
12
  fi
8
- <%- end -%>
9
- <%- end -%>
13
+ % end
14
+ % end
@@ -1,22 +1,22 @@
1
1
  # :command.fixed_flag_filter
2
2
  case "$1" in
3
- <%- if short_flag_exist? "-v" -%>
3
+ % if short_flag_exist? "-v"
4
4
  --version )
5
- <%- else -%>
5
+ % else
6
6
  --version | -v )
7
- <%- end -%>
7
+ % end
8
8
  version_command
9
9
  exit
10
10
  ;;
11
11
 
12
- <%- if short_flag_exist? "-h" -%>
12
+ % if short_flag_exist? "-h"
13
13
  --help )
14
- <%- else -%>
14
+ % else
15
15
  --help | -h )
16
- <%- end -%>
16
+ % end
17
17
  long_usage=yes
18
18
  <%= function_name %>_usage
19
- exit 1
19
+ exit
20
20
  ;;
21
21
 
22
22
  esac
@@ -2,7 +2,12 @@
2
2
  initialize() {
3
3
  version="<%= version %>"
4
4
  long_usage=''
5
- set -e
5
+ set -e
6
+
7
+ if [[ "${BASH_VERSINFO:-0}" -lt 4 ]]; then
8
+ printf "<%= strings[:unsupported_bash_version] -%>\n"
9
+ exit 1
10
+ fi
6
11
 
7
12
  <%= load_user_file("initialize.sh", placeholder: false).indent 2 %>
8
13
  }
@@ -1,9 +1,9 @@
1
1
  # :command.parse_requirements
2
- <%- if root_command? -%>
2
+ % if root_command?
3
3
  parse_requirements() {
4
- <%- else -%>
4
+ % else
5
5
  <%= function_name %>_parse_requirements() {
6
- <%- end -%>
6
+ % end
7
7
  <%= render(:fixed_flags_filter).indent 2 %>
8
8
  <%= render(:environment_variables_filter).indent 2 %>
9
9
  <%= render(:dependencies_filter).indent 2 %>
@@ -11,10 +11,11 @@ parse_requirements() {
11
11
  <%= render(:required_args_filter).indent 2 %>
12
12
  <%= render(:required_flags_filter).indent 2 %>
13
13
  <%= render(:parse_requirements_while).indent 2 %>
14
+ <%= render(:catch_all_filter).indent 2 %>
14
15
  <%= render(:default_assignments).indent 2 %>
15
16
  <%= render(:whitelist_filter).indent 2 %>
16
17
  }
17
18
 
18
- <%- commands.each do |command| %>
19
+ % commands.each do |command|
19
20
  <%= command.render :parse_requirements %>
20
- <%- end -%>
21
+ % end
@@ -1,25 +1,25 @@
1
1
  # :command.parse_requirements_case
2
- <%- if args.any? -%>
3
- <%- condition = "if" -%>
4
- <%- args.each do |arg| -%>
2
+ % if args.any?
3
+ % condition = "if"
4
+ % args.each do |arg|
5
5
  <%= condition %> [[ ! ${args[<%= arg.name %>]} ]]; then
6
6
  args[<%= arg.name %>]=$1
7
7
  shift
8
- <%- condition = "elif" -%>
9
- <%- end -%>
8
+ % condition = "elif"
9
+ % end
10
10
  else
11
- <%- if catch_all -%>
11
+ % if catch_all
12
12
  other_args+=("$1")
13
13
  shift
14
- <%- else -%>
14
+ % else
15
15
  printf "<%= strings[:invalid_argument] %>\n" "$key"
16
16
  exit 1
17
- <%- end -%>
17
+ % end
18
18
  fi
19
- <%- elsif catch_all -%>
19
+ % elsif catch_all
20
20
  other_args+=("$1")
21
21
  shift
22
- <%- else -%>
22
+ % else
23
23
  printf "<%= strings[:invalid_argument] %>\n" "$key"
24
24
  exit 1
25
- <%- end -%>
25
+ % end
@@ -2,21 +2,21 @@
2
2
  while [[ $# -gt 0 ]]; do
3
3
  key="$1"
4
4
  case "$key" in
5
- <%- flags.each do |flag| -%>
5
+ % flags.each do |flag|
6
6
  <%= flag.render(:case).indent 2 %>
7
7
 
8
- <%- end -%>
8
+ % end
9
9
 
10
10
  -* )
11
- <%- if catch_all -%>
11
+ % if catch_all
12
12
  other_args+=("$1")
13
13
  shift
14
14
  ;;
15
- <%- else -%>
15
+ % else
16
16
  printf "<%= strings[:invalid_flag] %>\n" "$key"
17
17
  exit 1
18
18
  ;;
19
- <%- end -%>
19
+ % end
20
20
 
21
21
  * )
22
22
  <%= render(:parse_requirements_case).indent 4 %>
@@ -1,5 +1,5 @@
1
1
  # :command.required_args_filter
2
- <%- required_args.each do |arg| -%>
2
+ % required_args.each do |arg|
3
3
  if [[ $1 && $1 != -* ]]; then
4
4
  args[<%= arg.name %>]=$1
5
5
  shift
@@ -8,4 +8,4 @@ else
8
8
  exit 1
9
9
  fi
10
10
 
11
- <%- end %>
11
+ % end
@@ -1,10 +1,10 @@
1
1
  # :command.required_flags_filter
2
- <%- if required_flags.any? -%>
2
+ % if required_flags.any?
3
3
  argstring="$*"
4
- <%- end -%>
5
- <%- required_flags.each do |flag| -%>
4
+ % end
5
+ % required_flags.each do |flag|
6
6
  if [[ <%= flag.aliases.map { |a| %Q["$argstring" != *#{a}*] }.join " && " %> ]]; then
7
7
  printf "<%= strings[:missing_required_flag] % { usage: flag.usage_string } %>\n"
8
8
  exit 1
9
9
  fi
10
- <%- end %>
10
+ % end
@@ -1,14 +1,14 @@
1
1
  # :command.usage_args
2
2
  printf "<%= strings[:arguments] %>\n"
3
- <%- if args.any? -%>
3
+ % if args.any?
4
4
 
5
- <%- args.each do |arg| -%>
5
+ % args.each do |arg|
6
6
  <%= arg.render(:usage) %>
7
- <%- end -%>
8
- <%- end -%>
9
- <%- if catch_all_help -%>
7
+ % end
8
+ % end
9
+ % if catch_all_help
10
10
 
11
11
  echo " <%= catch_all_label %>"
12
12
  printf "<%= catch_all_help.wrap(76).indent(4).sanitize_for_print %>\n"
13
13
  echo
14
- <%- end -%>
14
+ % end
@@ -1,18 +1,18 @@
1
1
  # :command.usage_commands
2
- <%- unless commands.first.group -%>
2
+ % unless commands.first.group
3
3
  printf "<%= strings[:commands] %>\n"
4
- <%- end -%>
5
- <%- maxlen = command_names.map(&:size).max -%>
6
- <%- commands.each do |command| -%>
7
- <%- summary = command.summary -%>
8
- <%- summary = strings[:default_command_summary] % { summary: summary } if command.default -%>
9
- <%- if command.group -%>
10
- <%- if command.name == commands.first.name -%>
4
+ % end
5
+ % maxlen = command_names.map(&:size).max
6
+ % commands.each do |command|
7
+ % summary = command.summary
8
+ % summary = strings[:default_command_summary] % { summary: summary } if command.default
9
+ % if command.group
10
+ % if command.name == commands.first.name
11
11
  printf "<%= strings[:group] % { group: command.group } %>\n"
12
- <%- else -%>
12
+ % else
13
13
  printf "\n<%= strings[:group] % { group: command.group } %>\n"
14
- <%- end -%>
15
- <%- end -%>
14
+ % end
15
+ % end
16
16
  echo " <%= command.name.ljust maxlen %> <%= summary %>"
17
- <%- end -%>
17
+ % end
18
18
  echo
@@ -1,6 +1,6 @@
1
1
  # :command.usage_environment_variables
2
2
  printf "<%= strings[:environment_variables] %>\n"
3
3
 
4
- <%- environment_variables.each do |env_var| -%>
4
+ % environment_variables.each do |env_var|
5
5
  <%= env_var.render(:usage) %>
6
- <%- end -%>
6
+ % end
@@ -1,7 +1,7 @@
1
1
  # :command.usage_examples
2
2
  printf "<%= strings[:examples] %>\n"
3
3
 
4
- <%- examples.each do |example| -%>
4
+ % examples.each do |example|
5
5
  printf "<%= example.wrap(78).indent(2).sanitize_for_print %>\n"
6
- <%- end -%>
6
+ % end
7
7
  echo
@@ -1,17 +1,17 @@
1
1
  # :command.usage_fixed_flags
2
- <%- if short_flag_exist? "-h" -%>
2
+ % if short_flag_exist? "-h"
3
3
  echo " --help"
4
- <%- else -%>
4
+ % else
5
5
  echo " --help, -h"
6
- <%- end -%>
6
+ % end
7
7
  printf " <%= strings[:help_flag_text] %>\n"
8
8
  echo
9
- <%- if root_command? -%>
10
- <%- if short_flag_exist? "-v" -%>
9
+ % if root_command?
10
+ % if short_flag_exist? "-v"
11
11
  echo " --version"
12
- <%- else -%>
12
+ % else
13
13
  echo " --version, -v"
14
- <%- end -%>
14
+ % end
15
15
  printf " <%= strings[:version_flag_text] %>\n"
16
16
  echo
17
- <%- end -%>
17
+ % end
@@ -1,4 +1,4 @@
1
1
  # :command.usage_flags
2
- <%- flags.each do |flag| -%>
2
+ % flags.each do |flag|
3
3
  <%= flag.render(:usage) %>
4
- <%- end -%>
4
+ % end
@@ -1,6 +1,6 @@
1
1
  # :command.user_lib
2
- <%- user_lib.each do |file| -%>
2
+ % user_lib.each do |file|
3
3
  # <%= ":#{file}" %>
4
4
  <%= File.read file %>
5
5
 
6
- <%- end -%>
6
+ % end
@@ -1,13 +1,13 @@
1
1
  # :command.whitelist_filter
2
- <%- whitelisted_args.each do |arg| -%>
2
+ % whitelisted_args.each do |arg|
3
3
  if [[ ! ${args[<%= arg.name %>]} =~ ^(<%= arg.allowed.join '|' %>)$ ]]; then
4
4
  printf "%s\n" "<%= strings[:disallowed_argument] % { name: arg.name, allowed: arg.allowed.join(', ') } %>"
5
5
  exit 1
6
6
  fi
7
- <%- end -%>
8
- <%- whitelisted_flags.each do |flag| -%>
7
+ % end
8
+ % whitelisted_flags.each do |flag|
9
9
  if [[ ! ${args[<%= flag.name %>]} =~ ^(<%= flag.allowed.join '|' %>)$ ]]; then
10
10
  printf "%s\n" "<%= strings[:disallowed_flag] % { name: flag.name, allowed: flag.allowed.join(', ') } %>"
11
11
  exit 1
12
12
  fi
13
- <%- end -%>
13
+ % end
@@ -1,4 +1,7 @@
1
1
  # :environment_variable.usage
2
2
  echo " <%= usage_string extended: true %>"
3
3
  printf "<%= help.wrap(76).indent(4).sanitize_for_print %>\n"
4
+ % if default
5
+ printf " <%= strings[:default] % { value: default } -%>\n"
6
+ % end
4
7
  echo
@@ -1,6 +1,6 @@
1
1
  # :flag.case
2
2
  <%= aliases.join " | " %> )
3
- <%- if arg -%>
3
+ % if arg
4
4
  if [[ $2 ]]; then
5
5
  args[<%= name %>]="$2"
6
6
  shift
@@ -9,8 +9,8 @@
9
9
  printf "%s\n" "<%= strings[:flag_requires_an_argument] % { name: name, usage: usage_string } %>"
10
10
  exit 1
11
11
  fi
12
- <%- else -%>
12
+ % else
13
13
  args[<%= name %>]=1
14
14
  shift
15
- <%- end -%>
15
+ % end
16
16
  ;;
@@ -1,10 +1,10 @@
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 -%>
4
+ % if allowed
5
5
  printf " <%= strings[:allowed] % { values: allowed.join(', ') } -%>\n"
6
- <%- end -%>
7
- <%- if default -%>
6
+ % end
7
+ % if default
8
8
  printf " <%= strings[:default] % { value: default } -%>\n"
9
- <%- end -%>
9
+ % end
10
10
  echo
data/lib/bashly.rb CHANGED
@@ -5,7 +5,6 @@ if ENV['BYEBUG']
5
5
  require 'lp'
6
6
  end
7
7
 
8
- requires 'bashly/polyfills'
9
8
  requires 'bashly/concerns'
10
9
 
11
10
  requires 'bashly/settings'
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.6.1
4
+ version: 0.6.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: 2021-07-21 00:00:00.000000000 Z
11
+ date: 2021-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -30,20 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.1'
34
- - - ">="
35
- - !ruby/object:Gem::Version
36
- version: 0.1.2
33
+ version: '0.2'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
38
  - - "~>"
42
39
  - !ruby/object:Gem::Version
43
- version: '0.1'
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: 0.1.2
40
+ version: '0.2'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: mister_bin
49
43
  requirement: !ruby/object:Gem::Requirement
@@ -102,7 +96,6 @@ files:
102
96
  - lib/bashly/models/environment_variable.rb
103
97
  - lib/bashly/models/flag.rb
104
98
  - lib/bashly/models/script.rb
105
- - lib/bashly/polyfills/hash.rb
106
99
  - lib/bashly/settings.rb
107
100
  - lib/bashly/templates/bashly.yml
108
101
  - lib/bashly/templates/lib/colors.sh
@@ -113,6 +106,7 @@ files:
113
106
  - lib/bashly/templates/strings.yml
114
107
  - lib/bashly/version.rb
115
108
  - lib/bashly/views/argument/usage.erb
109
+ - lib/bashly/views/command/catch_all_filter.erb
116
110
  - lib/bashly/views/command/command_fallback.erb
117
111
  - lib/bashly/views/command/command_filter.erb
118
112
  - lib/bashly/views/command/command_functions.erb
@@ -153,7 +147,11 @@ files:
153
147
  homepage: https://github.com/dannyben/bashly
154
148
  licenses:
155
149
  - MIT
156
- metadata: {}
150
+ metadata:
151
+ bug_tracker_uri: https://github.com/DannyBen/bashly/issues
152
+ changelog_uri: https://github.com/DannyBen/bashly/blob/master/CHANGELOG.md
153
+ homepage_uri: https://bashly.dannyb.co/
154
+ source_code_uri: https://github.com/DannyBen/bashly
157
155
  post_install_message:
158
156
  rdoc_options: []
159
157
  require_paths:
@@ -169,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
167
  - !ruby/object:Gem::Version
170
168
  version: '0'
171
169
  requirements: []
172
- rubygems_version: 3.2.16
170
+ rubygems_version: 3.2.25
173
171
  signing_key:
174
172
  specification_version: 4
175
173
  summary: Bash Command Line Tool Generator
@@ -1,12 +0,0 @@
1
- # :nocov:
2
-
3
- # Required for Ruby < 2.4
4
- if !Dir.respond_to? :empty?
5
- class Dir
6
- def self.empty?(path_name)
7
- exist?(path_name) && (entries(path_name) - ['.', '..']).empty?
8
- end
9
- end
10
- end
11
-
12
- # :nocov: