bashly 0.4.1rc1 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e31810f90eb5199f74dd9fd0dc0aedfb4bfd5dd4f38bc4e36473ab6c3e4f10d2
4
- data.tar.gz: 5de458e2eea4ec796e44a67cddeabaf848ef069ec2d37ad7ddb1f3cc660bad27
3
+ metadata.gz: ebe193249a02f2a5d25cd5a80a3172dbbc43ea16d18653368e4687841f19846c
4
+ data.tar.gz: d38bbde76e731eaf5a0455edc8b47ef011c6c8dba40ec9a220f7747bb98b238c
5
5
  SHA512:
6
- metadata.gz: 72a03554e17b648efda96ac0208bd4ee8223680717933a71907994ca3a3db3ffd629ea3572fc27143babb6634a65ad2f0b83fdeaeea2ab01d0c4755ea630f674
7
- data.tar.gz: eb955f344c428e92b82150b95256f3c9d90e3461353bb6b13cad68eeb17bf5e6220991590aa1d797b447ee5c92f414ef9b5042b13569a284595dac0cadd7babd
6
+ metadata.gz: d0963491e70542e96061395cbe7568d8c77014024ca53bdf2e56c93c3a2588bd5d46ea9e6952d8d0c1166772e46d47f69227c0e45e763970120a805079cd60a8
7
+ data.tar.gz: 9896cbf1635cf43f30c42452273c93bed40fbb4d126d9dcf921fdc6a9609b3db70a0a2cee5e7753e8974a182b550c3976ac8d45d968399ed870f0c27ca43d73e
data/README.md CHANGED
@@ -22,10 +22,10 @@ Create beautiful bash scripts from simple YAML configuration
22
22
  - [Prerequisites](#prerequisites)
23
23
  - [What is Bashly](#what-is-bashly)
24
24
  - [Usage](#usage)
25
- - [Using the input arguemnts in your code](#using-the-input-arguemnts-in-your-code)
25
+ - [Using the input arguments in your code](#using-the-input-arguments-in-your-code)
26
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)
27
+ - [Sample configuration for a script without commands](#sample-configuration-for-a-script-without-commands)
28
+ - [Sample configuration for a script with commands](#sample-configuration-for-a-script-with-commands)
29
29
  - [Configuration Reference](#configuration-reference)
30
30
  - [Command options](#command-options)
31
31
  - [Argument options](#argument-options)
@@ -113,7 +113,7 @@ Finally, edit the files in the `src` folder. Each of your script's commands
113
113
  get their own file. Once you edit, run `bashly generate` again to merge the
114
114
  content from your functions back into the script.
115
115
 
116
- ### Using the input arguemnts in your code
116
+ ### Using the input arguments in your code
117
117
 
118
118
  In order to access the parsed arguments in any of your partial scripts, you
119
119
  may simply access the `$args` associative array.
@@ -163,13 +163,13 @@ This is detected automatically by the contents of the configuration: If it
163
163
  contains a `commands` definition, it will generate a script with commands.
164
164
 
165
165
 
166
- ### Sample configuraiton for a script without commands
166
+ ### Sample configuration for a script without commands
167
167
 
168
168
  - Generate this script by running `bashly generate --minimal`
169
169
  - [See the initial sample bashly.yml file](examples/minimal/src/bashly.yml)
170
170
  - [See the generated bash script](examples/minimal/download)
171
171
 
172
- ### Sample configuraiton for a script with commands
172
+ ### Sample configuration for a script with commands
173
173
 
174
174
  - Generate this script by running `bashly generate`
175
175
  - [See the initial sample bashly.yml file](examples/commands/src/bashly.yml)
@@ -193,22 +193,22 @@ The `bashly.yml` configuration file consists of these types:
193
193
 
194
194
  ### Command options
195
195
 
196
- Unless otherwise specified, these definitiona can be used for both the root
196
+ Unless otherwise specified, these definitions can be used for both the root
197
197
  command and subcommands (under the `commands` definition).
198
198
 
199
-
200
199
  Option | Description
201
200
  -----------|-------------
202
201
  `name` | The name of the script or subcommand.
203
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*.
204
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.
205
204
  `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*.
205
+ `default` | Setting this to `true` on any command, will cause any unrecognized command line to be passed to this command. *Applicable only in subcommands*.
207
206
  `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.
207
+ `environment_variables` | Specify an array of [environment variables](#environment-variable-options) needed by your script.
208
+ `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.
209
+ `args` | Specify the array of [positional arguments](#argument-options) this script needs.
210
+ `flags` | Specify the array of option [flags](#flag-options) 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`.
212
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.
213
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.
214
214
 
@@ -223,6 +223,7 @@ bash function.
223
223
  `help` | The message to display when using `--help`. Can have multiple lines.
224
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.
225
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.
226
227
 
227
228
  ### Flag options
228
229
 
@@ -238,6 +239,7 @@ short form).
238
239
  `arg` | If the flag requires an argument, specify its name here.
239
240
  `required` | Specify if this flag is required.
240
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.
241
243
 
242
244
  #### Special handling for -v and -h
243
245
 
@@ -272,9 +274,9 @@ set.
272
274
  If you experience any issue, have a question or a suggestion, or if you wish
273
275
  to contribute, feel free to [open an issue][issues].
274
276
 
277
+
278
+
275
279
  [issues]: https://github.com/DannyBen/bashly/issues
276
280
  [rush]: https://github.com/DannyBen/rush-cli
277
281
  [alf]: https://github.com/DannyBen/alf
278
282
  [git-changelog]: https://github.com/DannyBen/git-changelog
279
-
280
-
@@ -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
@@ -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
@@ -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,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
 
@@ -175,6 +200,16 @@ module Bashly
175
200
  verify_commands if commands.any?
176
201
  end
177
202
 
203
+ # Returns an array of all the args with a whitelist
204
+ def whitelisted_args
205
+ args.select &:allowed
206
+ end
207
+
208
+ # Returns an array of all the flags with a whitelist arg
209
+ def whitelisted_flags
210
+ flags.select &:allowed
211
+ end
212
+
178
213
  private
179
214
 
180
215
  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.1rc1"
2
+ VERSION = "0.4.5"
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 -%>
@@ -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
  }
@@ -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,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.1rc1
4
+ version: 0.4.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-02-18 00:00:00.000000000 Z
11
+ date: 2021-06-24 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
@@ -138,11 +142,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
142
  version: 2.3.0
139
143
  required_rubygems_version: !ruby/object:Gem::Requirement
140
144
  requirements:
141
- - - ">"
145
+ - - ">="
142
146
  - !ruby/object:Gem::Version
143
- version: 1.3.1
147
+ version: '0'
144
148
  requirements: []
145
- rubygems_version: 3.2.3
149
+ rubygems_version: 3.2.16
146
150
  signing_key:
147
151
  specification_version: 4
148
152
  summary: Bash Command Line Tool Generator