bashly 0.8.1 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bashly/commands/generate.rb +40 -4
  3. data/lib/bashly/concerns/renderable.rb +19 -6
  4. data/lib/bashly/config_validator.rb +11 -0
  5. data/lib/bashly/extensions/string.rb +2 -2
  6. data/lib/bashly/script/command.rb +126 -24
  7. data/lib/bashly/templates/strings.yml +1 -0
  8. data/lib/bashly/version.rb +1 -1
  9. data/lib/bashly/views/README.md +6 -0
  10. data/lib/bashly/views/argument/usage.gtx +15 -0
  11. data/lib/bashly/views/argument/validations.gtx +11 -0
  12. data/lib/bashly/views/command/catch_all_filter.gtx +10 -0
  13. data/lib/bashly/views/command/command_fallback.gtx +42 -0
  14. data/lib/bashly/views/command/command_filter.gtx +29 -0
  15. data/lib/bashly/views/command/command_functions.gtx +5 -0
  16. data/lib/bashly/views/command/default_assignments.gtx +13 -0
  17. data/lib/bashly/views/command/default_initialize_script.gtx +7 -0
  18. data/lib/bashly/views/command/default_root_script.gtx +4 -0
  19. data/lib/bashly/views/command/default_script.gtx +5 -0
  20. data/lib/bashly/views/command/dependencies_filter.gtx +10 -0
  21. data/lib/bashly/views/command/environment_variables_filter.gtx +18 -0
  22. data/lib/bashly/views/command/fixed_flags_filter.gtx +20 -0
  23. data/lib/bashly/views/command/footer.gtx +5 -0
  24. data/lib/bashly/views/command/function.gtx +6 -0
  25. data/lib/bashly/views/command/initialize.gtx +12 -0
  26. data/lib/bashly/views/command/inspect_args.gtx +21 -0
  27. data/lib/bashly/views/command/long_usage.gtx +13 -0
  28. data/lib/bashly/views/command/master_script.gtx +17 -0
  29. data/lib/bashly/views/command/normalize_input.gtx +25 -0
  30. data/lib/bashly/views/command/parse_requirements.gtx +26 -0
  31. data/lib/bashly/views/command/parse_requirements_case.gtx +11 -0
  32. data/lib/bashly/views/command/parse_requirements_case_catch_all.gtx +23 -0
  33. data/lib/bashly/views/command/parse_requirements_case_repeatable.gtx +24 -0
  34. data/lib/bashly/views/command/parse_requirements_case_simple.gtx +25 -0
  35. data/lib/bashly/views/command/parse_requirements_while.gtx +33 -0
  36. data/lib/bashly/views/command/required_args_filter.gtx +13 -0
  37. data/lib/bashly/views/command/required_flags_filter.gtx +12 -0
  38. data/lib/bashly/views/command/root_command.gtx +6 -0
  39. data/lib/bashly/views/command/run.gtx +28 -0
  40. data/lib/bashly/views/command/usage.gtx +50 -0
  41. data/lib/bashly/views/command/usage_args.gtx +20 -0
  42. data/lib/bashly/views/command/usage_commands.gtx +18 -0
  43. data/lib/bashly/views/command/usage_environment_variables.gtx +10 -0
  44. data/lib/bashly/views/command/usage_examples.gtx +10 -0
  45. data/lib/bashly/views/command/usage_fixed_flags.gtx +13 -0
  46. data/lib/bashly/views/command/usage_flags.gtx +7 -0
  47. data/lib/bashly/views/command/user_filter.gtx +13 -0
  48. data/lib/bashly/views/command/user_lib.gtx +11 -0
  49. data/lib/bashly/views/command/version_command.gtx +6 -0
  50. data/lib/bashly/views/command/whitelist_filter.gtx +41 -0
  51. data/lib/bashly/views/environment_variable/usage.gtx +11 -0
  52. data/lib/bashly/views/flag/case.gtx +6 -0
  53. data/lib/bashly/views/flag/case_arg.gtx +25 -0
  54. data/lib/bashly/views/flag/case_no_arg.gtx +11 -0
  55. data/lib/bashly/views/flag/conflicts.gtx +22 -0
  56. data/lib/bashly/views/flag/usage.gtx +15 -0
  57. data/lib/bashly/views/flag/validations.gtx +11 -0
  58. data/lib/bashly/views/wrapper/bash3_bouncer.gtx +7 -0
  59. data/lib/bashly/views/wrapper/header.gtx +5 -0
  60. data/lib/bashly/views/wrapper/wrapper.gtx +8 -0
  61. metadata +89 -60
  62. data/lib/bashly/concerns/command_scopes.rb +0 -83
  63. data/lib/bashly/views/argument/usage.erb +0 -10
  64. data/lib/bashly/views/argument/validations.erb +0 -8
  65. data/lib/bashly/views/command/catch_all_filter.erb +0 -7
  66. data/lib/bashly/views/command/command_fallback.erb +0 -45
  67. data/lib/bashly/views/command/command_filter.erb +0 -22
  68. data/lib/bashly/views/command/command_functions.erb +0 -4
  69. data/lib/bashly/views/command/default_assignments.erb +0 -7
  70. data/lib/bashly/views/command/default_initialize_script.erb +0 -6
  71. data/lib/bashly/views/command/default_root_script.erb +0 -3
  72. data/lib/bashly/views/command/default_script.erb +0 -4
  73. data/lib/bashly/views/command/dependencies_filter.erb +0 -9
  74. data/lib/bashly/views/command/environment_variables_filter.erb +0 -14
  75. data/lib/bashly/views/command/fixed_flags_filter.erb +0 -24
  76. data/lib/bashly/views/command/footer.erb +0 -3
  77. data/lib/bashly/views/command/function.erb +0 -4
  78. data/lib/bashly/views/command/initialize.erb +0 -8
  79. data/lib/bashly/views/command/inspect_args.erb +0 -19
  80. data/lib/bashly/views/command/master_script.erb +0 -14
  81. data/lib/bashly/views/command/normalize_input.erb +0 -24
  82. data/lib/bashly/views/command/parse_requirements.erb +0 -22
  83. data/lib/bashly/views/command/parse_requirements_case.erb +0 -8
  84. data/lib/bashly/views/command/parse_requirements_case_catch_all.erb +0 -18
  85. data/lib/bashly/views/command/parse_requirements_case_repeatable.erb +0 -18
  86. data/lib/bashly/views/command/parse_requirements_case_simple.erb +0 -18
  87. data/lib/bashly/views/command/parse_requirements_while.erb +0 -26
  88. data/lib/bashly/views/command/required_args_filter.erb +0 -7
  89. data/lib/bashly/views/command/required_flags_filter.erb +0 -7
  90. data/lib/bashly/views/command/root_command.erb +0 -4
  91. data/lib/bashly/views/command/run.erb +0 -23
  92. data/lib/bashly/views/command/usage.erb +0 -50
  93. data/lib/bashly/views/command/usage_args.erb +0 -14
  94. data/lib/bashly/views/command/usage_commands.erb +0 -18
  95. data/lib/bashly/views/command/usage_environment_variables.erb +0 -6
  96. data/lib/bashly/views/command/usage_examples.erb +0 -7
  97. data/lib/bashly/views/command/usage_fixed_flags.erb +0 -17
  98. data/lib/bashly/views/command/usage_flags.erb +0 -4
  99. data/lib/bashly/views/command/user_filter.erb +0 -11
  100. data/lib/bashly/views/command/user_lib.erb +0 -6
  101. data/lib/bashly/views/command/version_command.erb +0 -4
  102. data/lib/bashly/views/command/whitelist_filter.erb +0 -33
  103. data/lib/bashly/views/environment_variable/usage.erb +0 -7
  104. data/lib/bashly/views/flag/case.erb +0 -4
  105. data/lib/bashly/views/flag/case_arg.erb +0 -19
  106. data/lib/bashly/views/flag/case_no_arg.erb +0 -8
  107. data/lib/bashly/views/flag/conflicts.erb +0 -18
  108. data/lib/bashly/views/flag/usage.erb +0 -10
  109. data/lib/bashly/views/flag/validations.erb +0 -8
  110. data/lib/bashly/views/wrapper/bash3_bouncer.erb +0 -5
  111. data/lib/bashly/views/wrapper/header.erb +0 -4
  112. data/lib/bashly/views/wrapper/wrapper.erb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4be359964fc41fae59f83eae85c594a4e0edec41e0cc5752fec25850b7b7ca43
4
- data.tar.gz: 62023932e59ae5b9856a9617f9148a7e28bfab5bca5cebca98d3fefbf401ae21
3
+ metadata.gz: 5bec052fd6ce0ffa90e32f48c5899a6f9ff7807750ffbe126b61b8cbd72a6210
4
+ data.tar.gz: 69d88a7b5a307ea324156a53f379b78d27b4b376dbe3fb3763307f4fd34ab7c3
5
5
  SHA512:
6
- metadata.gz: a0e222c6ead53cfef4597653d9ce51b6e9fffd1a3556acd72eff5447b9a203371a0097cd42f4058405cd473e7f0c55f4f9a448d45d3b1af73898b74a79706df4
7
- data.tar.gz: 8362eff89fccaad8c9a1f370270e33426d0089bbe131eec4fc55f586413afaa556caa81e62389daefb400941122db96fa1f8b4e04d3780a4d45ea88060dfdc1e
6
+ metadata.gz: cba455f059a94e300ad787e1a9ed69455160f915302033217350101e5d57e53c3f64c91192f942d6e18ad1995e1317082dcd46bf715b8f0ac7401080d409cc54
7
+ data.tar.gz: 48ce5d30512a9aa8ba0401c66cb1619f1f4926bcc041e0309a19543a5a99395f098b3c6d1bad0adfdf9076560e438f26849214ca3c33dbe24158beb34badd0ca
@@ -1,3 +1,5 @@
1
+ require 'filewatcher'
2
+
1
3
  module Bashly
2
4
  module Commands
3
5
  class Generate < Base
@@ -9,7 +11,8 @@ module Bashly
9
11
  option "-f --force", "Overwrite existing files"
10
12
  option "-q --quiet", "Disable on-screen progress report"
11
13
  option "-u --upgrade", "Upgrade all added library functions"
12
- option "-w --wrap FUNCTION", "Wrap the entire script in a function so it can also be sourced"
14
+ option "-w --watch", "Watch the source directory for changes and regenerate on change"
15
+ option "-r --wrap FUNCTION", "Wrap the entire script in a function so it can also be sourced"
13
16
  option "-e --env ENV", "Force the generation environment (see BASHLY_ENV)"
14
17
 
15
18
  environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"
@@ -27,17 +30,50 @@ module Bashly
27
30
 
28
31
  example "bashly generate --force"
29
32
  example "bashly generate --wrap my_function"
33
+ example "bashly g -uw"
34
+
35
+ attr_reader :watching
30
36
 
31
37
  def run
38
+ Settings.env = args['--env'] if args['--env']
39
+ @watching = args['--watch']
40
+
41
+ generate
42
+ watch if watching
43
+ end
44
+
45
+ private
46
+
47
+ def watch
48
+ quiet_say "!txtgrn!watching!txtrst! #{Settings.source_dir}\n"
49
+
50
+ Filewatcher.new([Settings.source_dir]).watch do
51
+ reset
52
+ generate
53
+
54
+ rescue Bashly::ConfigurationError => e
55
+ say! "!undred!#{e.class}!txtrst!\n#{e.message}"
56
+
57
+ ensure
58
+ quiet_say "!txtgrn!waiting\n"
59
+
60
+ end
61
+ end
62
+
63
+ def generate
32
64
  with_valid_config do
33
- Settings.env = args['--env'] if args['--env']
34
65
  quiet_say "creating !txtgrn!production!txtrst! version" if Settings.production?
35
66
  generate_all_files
36
- quiet_say "run !txtpur!#{master_script_path} --help!txtrst! to test your bash script"
67
+ quiet_say "run !txtpur!#{master_script_path} --help!txtrst! to test your bash script" unless watching
37
68
  end
38
69
  end
39
70
 
40
- private
71
+ def reset
72
+ @config = nil
73
+ @config_validator = nil
74
+ @command = nil
75
+ @script = nil
76
+ end
41
77
 
42
78
  def quiet_say(message)
43
79
  say message unless args['--quiet']
@@ -1,12 +1,9 @@
1
- require 'erb'
1
+ require 'gtx'
2
2
 
3
3
  module Bashly
4
4
  module Renderable
5
5
  def render(view)
6
- template = File.read view_path(view)
7
- erb = ERB.new(template, trim_mode: '%-')
8
- erb.filename = "#{views_subfolder}.#{view}"
9
- erb.result binding
6
+ GTX.render_file view_path(view), context: binding, filename: "#{views_subfolder}.#{view}"
10
7
  end
11
8
 
12
9
  def strings
@@ -18,10 +15,26 @@ module Bashly
18
15
  "# #{id}" unless Settings.production?
19
16
  end
20
17
 
18
+ # Reads a file from the userspace (Settings.source_dir) and returns
19
+ # its contents. If the file is not found, returns a string with a hint.
20
+ def load_user_file(file, placeholder: true)
21
+ path = "#{Settings.source_dir}/#{file}"
22
+
23
+ content = if File.exist? path
24
+ File.read(path).remove_front_matter
25
+ elsif placeholder
26
+ %q[echo "error: cannot load file"]
27
+ else
28
+ ''
29
+ end
30
+
31
+ Settings.production? ? content : "#{view_marker path}\n#{content}"
32
+ end
33
+
21
34
  private
22
35
 
23
36
  def view_path(view)
24
- "#{self_views_path}/#{view}.erb"
37
+ "#{self_views_path}/#{view}.gtx"
25
38
  end
26
39
 
27
40
  def self_views_path
@@ -41,6 +41,11 @@ module Bashly
41
41
  "#{key} must be a boolean or a string"
42
42
  end
43
43
 
44
+ def assert_expose(key, value)
45
+ return unless value
46
+ assert [true, false, nil, 'always'].include?(value), "#{key} must be a boolean, or the string 'always'"
47
+ end
48
+
44
49
  def assert_arg(key, value)
45
50
  assert_hash key, value, Script::Argument.option_keys
46
51
  assert_string "#{key}.name", value['name']
@@ -117,6 +122,7 @@ module Bashly
117
122
 
118
123
  assert_boolean "#{key}.private", value['private']
119
124
  assert_boolean "#{key}.default", value['default']
125
+ assert_expose "#{key}.expose", value['expose']
120
126
  assert_version "#{key}.version", value['version']
121
127
  assert_catch_all "#{key}.catch_all", value['catch_all']
122
128
  assert_string_or_array "#{key}.alias", value['alias']
@@ -141,11 +147,16 @@ module Bashly
141
147
  refute repeatable_arg, "#{key}.catch_all makes no sense with repeatable arg (#{repeatable_arg})"
142
148
  end
143
149
 
150
+ if value['expose']
151
+ assert value['commands'], "#{key}.expose makes no sense without commands"
152
+ end
153
+
144
154
  if key == "root"
145
155
  refute value['alias'], "#{key}.alias makes no sense"
146
156
  refute value['group'], "#{key}.group makes no sense"
147
157
  refute value['default'], "#{key}.default makes no sense"
148
158
  refute value['private'], "#{key}.private makes no sense"
159
+ refute value['expose'], "#{key}.expose makes no sense"
149
160
  else
150
161
  refute value['version'], "#{key}.version makes no sense"
151
162
  refute value['extensible'], "#{key}.extensible makes no sense"
@@ -5,7 +5,7 @@ class String
5
5
 
6
6
  def indent(offset)
7
7
  return self unless offset > 0
8
- split("\n").indent(offset).join("\n")
8
+ lines.indent(offset).join
9
9
  end
10
10
 
11
11
  def to_underscore
@@ -24,7 +24,7 @@ class String
24
24
  end
25
25
 
26
26
  def lint
27
- gsub(/\s+\n/m, "\n\n").lines.reject { |l| l =~ /^\s*##/ }.join ""
27
+ gsub(/\s+\n/m, "\n\n").lines.reject { |l| l =~ /^\s*##/ }.join
28
28
  end
29
29
 
30
30
  def remove_front_matter
@@ -2,14 +2,13 @@ module Bashly
2
2
  module Script
3
3
  class Command < Base
4
4
  include Completions::Command
5
- include CommandScopes
6
5
 
7
6
  class << self
8
7
  def option_keys
9
8
  @option_keys ||= %i[
10
9
  alias args catch_all commands completions
11
10
  default dependencies environment_variables examples
12
- extensible filename filters flags
11
+ extensible expose filename filters flags
13
12
  footer group help name
14
13
  private version
15
14
  short
@@ -18,6 +17,9 @@ module Bashly
18
17
  end
19
18
  end
20
19
 
20
+ attr_accessor :parent_command
21
+ attr_writer :parents
22
+
21
23
  # Returns the name to be used as an action.
22
24
  # - If it is the root command, the action is "root"
23
25
  # - Else, it is all the parents, except the first one (root) joined
@@ -32,6 +34,16 @@ module Bashly
32
34
  [name] + alt
33
35
  end
34
36
 
37
+ # Returns an array of all full names (including aliases and aliases of
38
+ # parents)
39
+ def all_full_names
40
+ if parent_command
41
+ parent_command.all_full_names.product(aliases).map { |a| a.join ' ' }
42
+ else
43
+ aliases
44
+ end
45
+ end
46
+
35
47
  # Returns an array of alternative aliases if any
36
48
  def alt
37
49
  # DEPRECATION 0.8.0
@@ -57,14 +69,79 @@ module Bashly
57
69
  @catch_all ||= CatchAll.from_config options['catch_all']
58
70
  end
59
71
 
72
+ # Returns a full list of the Command names and aliases combined
73
+ def command_aliases
74
+ commands.map(&:aliases).flatten
75
+ end
76
+
77
+ # Returns a data structure for displaying subcommands help
78
+ def command_help_data
79
+ result = {}
80
+
81
+ public_commands.each do |command|
82
+ result[command.group_string] ||= {}
83
+ result[command.group_string][command.name] = { summary: command.summary_string }
84
+ next unless command.expose
85
+
86
+ command.public_commands.each do |subcommand|
87
+ result[command.group_string]["#{command.name} #{subcommand.name}"] = {
88
+ summary: subcommand.summary_string,
89
+ help_only: command.expose != 'always'
90
+ }
91
+ end
92
+ end
93
+
94
+ result
95
+ end
96
+
97
+ # Returns only the names of the Commands
98
+ def command_names
99
+ commands.map &:name
100
+ end
101
+
60
102
  # Returns an array of the Commands
61
103
  def commands
62
104
  return [] unless options["commands"]
63
105
  options["commands"].map do |options|
64
- options['parents'] = parents + [name]
65
- options['parent_command'] = self
66
- Command.new options
106
+ result = Command.new options
107
+ result.parents = parents + [name]
108
+ result.parent_command = self
109
+ result
110
+ end
111
+ end
112
+
113
+ # Returns a flat array containing all the commands in this tree.
114
+ # This includes self + children + grandchildres + ...
115
+ def deep_commands
116
+ result = []
117
+ commands.each do |command|
118
+ result << command
119
+ if command.commands.any?
120
+ result += command.deep_commands
121
+ end
67
122
  end
123
+ result
124
+ end
125
+
126
+ # If any of this command's subcommands has the default option set to
127
+ # true, this default command will be returned, nil otherwise.
128
+ def default_command
129
+ commands.find { |c| c.default }
130
+ end
131
+
132
+ # Returns an array of all the default Args
133
+ def default_args
134
+ args.select &:default
135
+ end
136
+
137
+ # Returns an array of all the default Environment Variables
138
+ def default_environment_variables
139
+ environment_variables.select &:default
140
+ end
141
+
142
+ # Returns an array of all the default Flags
143
+ def default_flags
144
+ flags.select &:default
68
145
  end
69
146
 
70
147
  # Returns an array of EnvironmentVariables
@@ -100,32 +177,24 @@ module Bashly
100
177
  parents.any? ? (parents + [name]).join(' ') : name
101
178
  end
102
179
 
103
- # Reads a file from the userspace (Settings.source_dir) and returns
104
- # its contents.
105
- # If the file is not found, returns a string with a hint.
106
- def load_user_file(file, placeholder: true)
107
- path = "#{Settings.source_dir}/#{file}"
108
-
109
- content = if File.exist? path
110
- File.read(path).remove_front_matter
111
- elsif placeholder
112
- %q[echo "error: cannot load file"]
180
+ # Returns the string for the group caption
181
+ def group_string
182
+ if group
183
+ strings[:group] % { group: group }
113
184
  else
114
- ''
185
+ strings[:commands]
115
186
  end
116
-
117
- Settings.production? ? content : "#{view_marker path}\n#{content}"
118
- end
119
-
120
- # Returns the Command instance of the direct parent
121
- def parent_command
122
- options['parent_command']
123
187
  end
124
188
 
125
189
  # Returns an array of all parents. For example, the command
126
190
  # "docker container run" will have [docker, container] as its parents
127
191
  def parents
128
- options['parents'] || []
192
+ @parents ||= []
193
+ end
194
+
195
+ # Returns only commands that are not private
196
+ def public_commands
197
+ commands.reject &:private
129
198
  end
130
199
 
131
200
  # Returns true if one of the args is repeatable
@@ -133,6 +202,21 @@ module Bashly
133
202
  args.select(&:repeatable).any?
134
203
  end
135
204
 
205
+ # Returns an array of all the required Arguments
206
+ def required_args
207
+ args.select &:required
208
+ end
209
+
210
+ # Returns an array of all the required EnvironmentVariables
211
+ def required_environment_variables
212
+ environment_variables.select &:required
213
+ end
214
+
215
+ # Returns an array of all the required Flags
216
+ def required_flags
217
+ flags.select &:required
218
+ end
219
+
136
220
  # Returns true if this is the root command (no parents)
137
221
  def root_command?
138
222
  parents.empty?
@@ -143,6 +227,15 @@ module Bashly
143
227
  flags.select { |f| f.short == flag }.any?
144
228
  end
145
229
 
230
+ # Returns the summary string
231
+ def summary_string
232
+ if default
233
+ strings[:default_command_summary] % { summary: summary }
234
+ else
235
+ summary
236
+ end
237
+ end
238
+
146
239
  # Returns a constructed string suitable for Usage pattern
147
240
  def usage_string
148
241
  result = [full_name]
@@ -162,6 +255,15 @@ module Bashly
162
255
  @user_lib ||= Dir["#{Settings.full_lib_dir}/**/*.sh"].sort
163
256
  end
164
257
 
258
+ # Returns an array of all the args with a whitelist
259
+ def whitelisted_args
260
+ args.select &:allowed
261
+ end
262
+
263
+ # Returns an array of all the flags with a whitelist arg
264
+ def whitelisted_flags
265
+ flags.select &:allowed
266
+ end
165
267
  end
166
268
  end
167
269
  end
@@ -26,6 +26,7 @@ version_flag_text: Show version number
26
26
  flag_requires_an_argument: "%{name} requires an argument: %{usage}"
27
27
  invalid_argument: "invalid argument: %s"
28
28
  invalid_flag: "invalid option: %s"
29
+ invalid_command: "invalid command: %s"
29
30
  conflicting_flags: "conflicting options: %s cannot be used with %s"
30
31
  missing_required_argument: "missing required argument: %{arg}\\nusage: %{usage}"
31
32
  missing_required_flag: "missing required flag: %{usage}"
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = "0.8.1"
2
+ VERSION = "0.8.4"
3
3
  end
@@ -0,0 +1,6 @@
1
+ # View Tempaltes
2
+
3
+ These are [GTX](https://github.com/dannyben/gtx) templates.
4
+
5
+ For syntax highlighting, set up your editor to treat `*.gtx` files as Ruby
6
+ source code.
@@ -0,0 +1,15 @@
1
+ = view_marker
2
+
3
+ > echo " {{ label }}"
4
+ > printf "{{ help.wrap(76).indent(4).sanitize_for_print }}\n"
5
+
6
+ if allowed
7
+ > printf " {{ strings[:allowed] % { values: allowed.join(', ') } }}\n"
8
+ end
9
+
10
+ if default
11
+ > printf " {{ strings[:default] % { value: default } }}\n"
12
+ end
13
+
14
+ > echo
15
+ >
@@ -0,0 +1,11 @@
1
+ if validate
2
+
3
+ = view_marker
4
+
5
+ > if [[ -n $(validate_{{ validate }} "$1") ]]; then
6
+ > printf "{{ strings[:validation_error] }}\n" "{{ name.upcase }}" "$(validate_{{ validate }} "$1")"
7
+ > exit 1
8
+ > fi
9
+ >
10
+
11
+ end
@@ -0,0 +1,10 @@
1
+ if catch_all.required?
2
+ = view_marker
3
+
4
+ > if [[ ${#other_args[@]} -eq 0 ]]; then
5
+ > printf "{{ strings[:missing_required_argument] % { arg: catch_all.label, usage: usage_string } }}\n"
6
+ > exit 1
7
+ > fi
8
+ >
9
+
10
+ end
@@ -0,0 +1,42 @@
1
+ = view_marker
2
+
3
+ > "" )
4
+ > {{ function_name }}_usage
5
+ > exit 1
6
+ > ;;
7
+ >
8
+ > * )
9
+
10
+ if default_command
11
+ > action="{{ default_command.name }}"
12
+ > {{ default_command.function_name }}_parse_requirements "$@"
13
+ > shift $#
14
+ > ;;
15
+ >
16
+
17
+ elsif extensible.is_a? String
18
+ > if [[ -x "$(command -v "{{ extensible }}")" ]]; then
19
+ > exec {{ extensible }} "$@"
20
+ > else
21
+ > printf "{{ strings[:invalid_command] }}\n" "$action"
22
+ > exit 1
23
+ > fi
24
+ >
25
+
26
+ elsif extensible
27
+ > if [[ -x "$(command -v "{{ function_name }}-$action")" ]]; then
28
+ > shift
29
+ > exec "{{ function_name }}-$action" "$@"
30
+ > else
31
+ > printf "{{ strings[:invalid_command] }}\n" "$action"
32
+ > exit 1
33
+ > fi
34
+ >
35
+
36
+ else
37
+ > printf "{{ strings[:invalid_command] }}\n" "$action"
38
+ > exit 1
39
+ > ;;
40
+ >
41
+
42
+ end
@@ -0,0 +1,29 @@
1
+ = view_marker
2
+
3
+ if commands.any?
4
+ > action=${1:-}
5
+ >
6
+ > case $action in
7
+ > -* )
8
+ > ;;
9
+ >
10
+
11
+ commands.each do |command|
12
+ > {{ command.aliases.join " | " }} )
13
+ > action="{{ command.name }}"
14
+ > shift
15
+ > {{ command.function_name }}_parse_requirements "$@"
16
+ > shift $#
17
+ > ;;
18
+ >
19
+
20
+ end
21
+
22
+ = render :command_fallback
23
+ > esac
24
+ >
25
+
26
+ else
27
+ > action="{{ action_name }}"
28
+
29
+ end
@@ -0,0 +1,5 @@
1
+ = view_marker
2
+
3
+ deep_commands.each do |command|
4
+ = command.render :function unless command.commands.any?
5
+ end
@@ -0,0 +1,13 @@
1
+ if default_args.any? or default_flags.any?
2
+ = view_marker
3
+
4
+ default_args.each do |arg|
5
+ > [[ -n ${args[{{ arg.name }}]:-} ]] || args[{{ arg.name }}]="{{ arg.default }}"
6
+ end
7
+
8
+ default_flags.each do |flag|
9
+ > [[ -n ${args[{{ flag.long }}]:-} ]] || args[{{ flag.long }}]="{{ flag.default }}"
10
+ end
11
+
12
+ >
13
+ end
@@ -0,0 +1,7 @@
1
+ > ## Code here runs inside the initialize() function
2
+ > ## Use it for anything that you need to run before any other function, like
3
+ > ## setting environment vairables:
4
+ > ## CONFIG_FILE=settings.ini
5
+ > ##
6
+ > ## Feel free to empty (but not delete) this file.
7
+ >
@@ -0,0 +1,4 @@
1
+ > echo "# this file is located in '{{ "#{Settings.source_dir}/#{filename}" }}'"
2
+ > echo "# you can edit it freely and regenerate (it will not be overwritten)"
3
+ > inspect_args
4
+ >
@@ -0,0 +1,5 @@
1
+ > echo "# this file is located in '{{ "#{Settings.source_dir}/#{filename}" }}'"
2
+ > echo "# code for '{{ full_name }}' goes here"
3
+ > echo "# you can edit it freely and regenerate (it will not be overwritten)"
4
+ > inspect_args
5
+ >
@@ -0,0 +1,10 @@
1
+ if dependencies
2
+ = view_marker
3
+
4
+ dependencies.each do |dependency|
5
+ > if ! [[ -x "$(command -v {{ dependency }})" ]]; then
6
+ > printf "{{ strings[:missing_dependency] % { dependency: dependency } }}\n"
7
+ > exit 1
8
+ > fi
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ if default_environment_variables.any? or required_environment_variables.any?
2
+ = view_marker
3
+
4
+ if default_environment_variables.any?
5
+ default_environment_variables.each do |env_var|
6
+ > export {{ env_var.name.upcase }}="${<%= env_var.name.upcase %>:-<%= env_var.default %>}"
7
+ end
8
+ end
9
+
10
+ if required_environment_variables.any?
11
+ required_environment_variables.each do |env_var|
12
+ > if [[ -z "${<%= env_var.name.upcase %>:-}" ]]; then
13
+ > printf "{{ strings[:missing_required_environment_variable] % { var: env_var.name.upcase } }}\n"
14
+ > exit 1
15
+ > fi
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ = view_marker
2
+
3
+ > case "${1:-}" in
4
+
5
+ if root_command?
6
+ = short_flag_exist?("-v") ? "--version )" : "--version | -v )"
7
+ > version_command
8
+ > exit
9
+ > ;;
10
+ >
11
+ end
12
+
13
+ = short_flag_exist?("-h") ? "--help )" : "--help | -h )"
14
+ > long_usage=yes
15
+ > <%= function_name %>_usage
16
+ > exit
17
+ > ;;
18
+ >
19
+ > esac
20
+ >
@@ -0,0 +1,5 @@
1
+ = view_marker
2
+
3
+ > printf "{{ footer.gsub("\n", '\n').gsub('"', '\"') }}\n"
4
+ > echo
5
+ >
@@ -0,0 +1,6 @@
1
+ = view_marker
2
+
3
+ > {{ function_name }}_command() {
4
+ = load_user_file(filename).indent 2
5
+ > }
6
+ >
@@ -0,0 +1,12 @@
1
+ = view_marker
2
+
3
+ > initialize() {
4
+ > version="<%= version %>"
5
+ > long_usage=''
6
+ > {{ Settings.strict ? "set -euo pipefail" : "set -e" }}
7
+ >
8
+
9
+ = load_user_file("initialize.sh", placeholder: false).indent 2
10
+
11
+ > }
12
+ >