commander 5.0.0 → 6.0.0

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.
@@ -4,13 +4,16 @@ require 'erb'
4
4
 
5
5
  module Commander
6
6
  module HelpFormatter
7
+ ##
8
+ # A condensed variant of HelpFormatter::Terminal, using the ERB
9
+ # templates in the neighboring +terminal_compact/+ directory. Enable
10
+ # it with <tt>program :help_formatter, :compact</tt>.
7
11
  class TerminalCompact < Terminal
12
+ ##
13
+ # Compile the ERB template named _name_ (+:help+ or
14
+ # +:command_help+) from this formatter's template directory.
8
15
  def template(name)
9
- if RUBY_VERSION < '2.6'
10
- ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal_compact', "#{name}.erb")), nil, '-')
11
- else
12
- ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal_compact', "#{name}.erb")), trim_mode: '-')
13
- end
16
+ ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal_compact', "#{name}.erb")), trim_mode: '-')
14
17
  end
15
18
  end
16
19
  end
@@ -1,16 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Commander
4
+ ##
5
+ # = Help Formatter
6
+ #
7
+ # Commander's help formatters control the output when
8
+ # either the help command, or --help switch are called.
9
+ # The default formatter is Commander::HelpFormatter::Terminal.
4
10
  module HelpFormatter
5
11
  autoload :Base, 'commander/help_formatters/base'
6
12
  autoload :Terminal, 'commander/help_formatters/terminal'
7
13
  autoload :TerminalCompact, 'commander/help_formatters/terminal_compact'
8
14
 
15
+ ##
16
+ # Exposes _target_'s binding to an ERB template, letting the template
17
+ # reference _target_'s instance variables and private methods as if
18
+ # they were local variables/bare method calls. Subclasses can inject
19
+ # additional template-local variables by overriding #decorate_binding.
9
20
  class Context
10
21
  def initialize(target)
11
22
  @target = target
12
23
  end
13
24
 
25
+ ##
26
+ # The (possibly decorated) binding of _target_, suitable for
27
+ # passing to ERB#result.
14
28
  def get_binding
15
29
  @target.instance_eval { binding }.tap do |bind|
16
30
  decorate_binding(bind)
@@ -22,20 +36,31 @@ module Commander
22
36
  end
23
37
  end
24
38
 
39
+ ##
40
+ # A Context for rendering the global help template (see
41
+ # HelpFormatter::Terminal#render), decorating the target Runner's
42
+ # binding with +max_command_length+/+max_aliases_length+ locals so
43
+ # the template can align its columns.
25
44
  class ProgramContext < Context
26
45
  def decorate_binding(bind)
27
46
  bind.eval("max_command_length = #{max_command_length(bind)}")
28
47
  bind.eval("max_aliases_length = #{max_aliases_length(bind)}")
29
48
  end
30
49
 
50
+ ##
51
+ # Length, in characters, of the longest registered command name.
31
52
  def max_command_length(bind)
32
53
  max_key_length(bind.eval('@commands'))
33
54
  end
34
55
 
56
+ ##
57
+ # Length, in characters, of the longest registered command alias.
35
58
  def max_aliases_length(bind)
36
59
  max_key_length(bind.eval('@aliases'))
37
60
  end
38
61
 
62
+ ##
63
+ # Length of the longest key in _hash_, or _default_ when _hash_ is empty.
39
64
  def max_key_length(hash, default = 20)
40
65
  longest = hash.keys.max_by(&:size)
41
66
  longest ? longest.size : default
@@ -44,6 +69,9 @@ module Commander
44
69
 
45
70
  module_function
46
71
 
72
+ ##
73
+ # Indent each line of _text_ (after the first) by _amount_ spaces.
74
+ # Used by the help templates to align multi-line descriptions.
47
75
  def indent(amount, text)
48
76
  text.to_s.gsub("\n", "\n#{' ' * amount}")
49
77
  end
@@ -1,6 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Commander
4
+ ##
5
+ # = Methods
6
+ #
7
+ # The primary entry point for adding Commander's DSL to an object.
8
+ # Bundles Commander::UI (terminal output/prompting helpers),
9
+ # Commander::UI::AskForClass (the +ask_for_*+ family of methods), and
10
+ # Commander::Delegates (the +command+/+program+/+run!+ DSL) into a
11
+ # single mixin. <tt>require 'commander/import'</tt> includes this into
12
+ # the top-level Object; embedders typically include it directly instead.
13
+ #
14
+ # When connected to a sufficiently wide terminal, also configures
15
+ # HighLine to wrap output five columns short of the terminal width.
4
16
  module Methods
5
17
  include Commander::UI
6
18
  include Commander::UI::AskForClass
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Commander
4
+ ##
5
+ # = Platform
6
+ #
7
+ # Small helpers for detecting the running Ruby engine.
4
8
  module Platform
9
+ ##
10
+ # Whether the current process is running under JRuby.
5
11
  def self.jruby?
6
12
  defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
7
13
  end
@@ -3,13 +3,23 @@
3
3
  require 'optparse'
4
4
 
5
5
  module Commander
6
+ ##
7
+ # = Runner
8
+ #
9
+ # The engine behind Commander's DSL: holds the registered commands,
10
+ # global options, and program metadata, parses ARGV, and dispatches to
11
+ # the matched Commander::Command. Accessed as a singleton
12
+ # (Runner.instance) by Commander::Delegates so that the top-level
13
+ # +command+/+program+/+run!+ methods all operate on the same runner.
6
14
  class Runner
7
15
  #--
8
16
  # Exceptions
9
17
  #++
10
18
 
19
+ # Raised when required program information (e.g. :version) is missing.
11
20
  class CommandError < StandardError; end
12
21
 
22
+ # Raised when no command matches the given arguments.
13
23
  class InvalidCommandError < CommandError; end
14
24
 
15
25
  attr_reader :commands, :options, :help_formatter_aliases
@@ -17,7 +27,6 @@ module Commander
17
27
  ##
18
28
  # Initialize a new command runner. Optionally
19
29
  # supplying _args_ for mocking, or arbitrary usage.
20
-
21
30
  def initialize(args = ARGV)
22
31
  @args, @commands, @aliases, @options = args, {}, {}, []
23
32
  @help_formatter_aliases = help_formatter_alias_defaults
@@ -29,14 +38,12 @@ module Commander
29
38
 
30
39
  ##
31
40
  # Return singleton Runner instance.
32
-
33
41
  def self.instance
34
42
  @instance ||= new
35
43
  end
36
44
 
37
45
  ##
38
46
  # Run command parsing and execution process.
39
-
40
47
  def run!
41
48
  trace = @always_trace || false
42
49
  require_program :version, :description
@@ -78,14 +85,12 @@ module Commander
78
85
 
79
86
  ##
80
87
  # Return program version.
81
-
82
88
  def version
83
89
  format('%s %s', program(:name), program(:version))
84
90
  end
85
91
 
86
92
  ##
87
93
  # Enable tracing on all executions (bypasses --trace)
88
-
89
94
  def always_trace!
90
95
  @always_trace = true
91
96
  @never_trace = false
@@ -93,7 +98,6 @@ module Commander
93
98
 
94
99
  ##
95
100
  # Hide the trace option from the help menus and don't add it as a global option
96
-
97
101
  def never_trace!
98
102
  @never_trace = true
99
103
  @always_trace = false
@@ -127,7 +131,6 @@ module Commander
127
131
  # :help_paging Flag for toggling help paging
128
132
  # :int_message Message to display when interrupted (CTRL + C)
129
133
  #
130
-
131
134
  def program(key, *args, &block)
132
135
  if key == :help && !args.empty?
133
136
  @program[:help] ||= {}
@@ -138,7 +141,7 @@ module Commander
138
141
  @program[key] = block
139
142
  else
140
143
  unless args.empty?
141
- @program[key] = args.count == 1 ? args[0] : args
144
+ @program[key] = args.length == 1 ? args[0] : args
142
145
  end
143
146
  @program[key]
144
147
  end
@@ -157,7 +160,6 @@ module Commander
157
160
  # end
158
161
  # end
159
162
  #
160
-
161
163
  def command(name, &block)
162
164
  yield add_command(Commander::Command.new(name)) if block
163
165
  @commands[name.to_s]
@@ -166,7 +168,6 @@ module Commander
166
168
  ##
167
169
  # Add a global option; follows the same syntax as Command#option
168
170
  # This would be used for switches such as --version, --trace, etc.
169
-
170
171
  def global_option(*args, &block)
171
172
  switches, description = Runner.separate_switches_from_description(*args)
172
173
  @options << {
@@ -180,7 +181,6 @@ module Commander
180
181
  ##
181
182
  # Alias command _name_ with _alias_name_. Optionally _args_ may be passed
182
183
  # as if they were being passed straight to the original command via the command-line.
183
-
184
184
  def alias_command(alias_name, name, *args)
185
185
  @commands[alias_name.to_s] = command name
186
186
  @aliases[alias_name.to_s] = args
@@ -189,37 +189,32 @@ module Commander
189
189
  ##
190
190
  # Default command _name_ to be used when no other
191
191
  # command is found in the arguments.
192
-
193
192
  def default_command(name)
194
193
  @default_command = name
195
194
  end
196
195
 
197
196
  ##
198
197
  # Add a command object to this runner.
199
-
200
198
  def add_command(command)
201
199
  @commands[command.name] = command
202
200
  end
203
201
 
204
202
  ##
205
203
  # Check if command _name_ is an alias.
206
-
207
204
  def alias?(name)
208
205
  @aliases.include? name.to_s
209
206
  end
210
207
 
211
208
  ##
212
209
  # Check if a command _name_ exists.
213
-
214
210
  def command_exists?(name)
215
211
  @commands[name.to_s]
216
212
  end
217
213
 
218
- #:stopdoc:
214
+ # :stopdoc:
219
215
 
220
216
  ##
221
217
  # Get active command within arguments passed to this runner.
222
-
223
218
  def active_command
224
219
  @active_command ||= command(command_name_from_args)
225
220
  end
@@ -228,14 +223,12 @@ module Commander
228
223
  # Attempts to locate a command name from within the arguments.
229
224
  # Supports multi-word commands, using the largest possible match.
230
225
  # Returns the default command, if no valid commands found in the args.
231
-
232
226
  def command_name_from_args
233
- @command_name_from_args ||= (longest_valid_command_name_from(@args) || @default_command)
227
+ @command_name_from_args ||= longest_valid_command_name_from(@args) || @default_command
234
228
  end
235
229
 
236
230
  ##
237
231
  # Returns array of valid command names found within _args_.
238
-
239
232
  def valid_command_names_from(*args)
240
233
  remove_global_options options, args
241
234
  arg_string = args.delete_if { |value| value =~ /^-/ }.join ' '
@@ -244,14 +237,12 @@ module Commander
244
237
 
245
238
  ##
246
239
  # Help formatter instance.
247
-
248
240
  def help_formatter
249
241
  @help_formatter ||= program(:help_formatter).new self
250
242
  end
251
243
 
252
244
  ##
253
245
  # Return arguments without the command name.
254
-
255
246
  def args_without_command_name
256
247
  removed = []
257
248
  parts = command_name_from_args.split rescue []
@@ -262,7 +253,6 @@ module Commander
262
253
 
263
254
  ##
264
255
  # Returns hash of help formatter alias defaults.
265
-
266
256
  def help_formatter_alias_defaults
267
257
  {
268
258
  compact: HelpFormatter::TerminalCompact,
@@ -271,7 +261,6 @@ module Commander
271
261
 
272
262
  ##
273
263
  # Returns hash of program defaults.
274
-
275
264
  def program_defaults
276
265
  {
277
266
  help_formatter: HelpFormatter::Terminal,
@@ -283,7 +272,6 @@ module Commander
283
272
  ##
284
273
  # Creates default commands such as 'help' which is
285
274
  # essentially the same as using the --help switch.
286
-
287
275
  def create_default_commands
288
276
  command :help do |c|
289
277
  c.syntax = 'commander help [command]'
@@ -309,7 +297,6 @@ module Commander
309
297
 
310
298
  ##
311
299
  # Raises InvalidCommandError when a _command_ is not found.
312
-
313
300
  def require_valid_command(command = active_command)
314
301
  fail InvalidCommandError, 'invalid command', caller if command.nil?
315
302
  end
@@ -318,7 +305,6 @@ module Commander
318
305
  # Removes global _options_ from _args_. This prevents an invalid
319
306
  # option error from occurring when options are parsed
320
307
  # again for the command.
321
-
322
308
  def remove_global_options(options, args)
323
309
  options.each do |option|
324
310
  switches = option[:switches]
@@ -358,8 +344,8 @@ module Commander
358
344
  def expand_optionally_negative_switches(switches)
359
345
  switches.reduce([]) do |memo, val|
360
346
  if val =~ /\[no-\]/
361
- memo << val.gsub(/\[no-\]/, '')
362
- memo << val.gsub(/\[no-\]/, 'no-')
347
+ memo << val.gsub('[no-]', '')
348
+ memo << val.gsub('[no-]', 'no-')
363
349
  else
364
350
  memo << val
365
351
  end
@@ -368,7 +354,6 @@ module Commander
368
354
 
369
355
  ##
370
356
  # Parse global command options.
371
-
372
357
  def parse_global_options
373
358
  parser = options.inject(OptionParser.new) do |options, option|
374
359
  options.on(*option[:args], &global_option_proc(option[:switches], &option[:proc]))
@@ -389,7 +374,6 @@ module Commander
389
374
  # This functionality works whether a block is present for the global
390
375
  # option or not, so simple switches such as --verbose can be used
391
376
  # without a block, and used throughout all commands.
392
-
393
377
  def global_option_proc(switches, &block)
394
378
  lambda do |value|
395
379
  unless active_command.nil?
@@ -401,7 +385,6 @@ module Commander
401
385
 
402
386
  ##
403
387
  # Raises a CommandError when the program any of the _keys_ are not present, or empty.
404
-
405
388
  def require_program(*keys)
406
389
  keys.each do |key|
407
390
  fail CommandError, "program #{key} required" if program(key).nil? || program(key).empty?
@@ -410,7 +393,6 @@ module Commander
410
393
 
411
394
  ##
412
395
  # Return switches and description separated from the _args_ passed.
413
-
414
396
  def self.separate_switches_from_description(*args)
415
397
  switches = args.find_all { |arg| arg.to_s =~ /^-/ }
416
398
  description = args.last if args.last.is_a?(String) && !args.last.match(/^-/)
@@ -428,14 +410,12 @@ module Commander
428
410
  # --file FILE # => :file
429
411
  # --list of,things # => :list
430
412
  #
431
-
432
413
  def self.switch_to_sym(switch)
433
- switch.scan(/[\-\]](\w+)/).join('_').to_sym rescue nil
414
+ switch.scan(/[-\]](\w+)/).join('_').to_sym rescue nil
434
415
  end
435
416
 
436
417
  ##
437
418
  # Run the active command.
438
-
439
419
  def run_active_command
440
420
  require_valid_command
441
421
  if alias? command_name_from_args
@@ -445,7 +425,7 @@ module Commander
445
425
  end
446
426
  end
447
427
 
448
- def say(*args) #:nodoc:
428
+ def say(*args) # :nodoc:
449
429
  HighLine.default_instance.say(*args)
450
430
  end
451
431
 
@@ -454,7 +434,6 @@ module Commander
454
434
  ##
455
435
  # Attempts to locate a command name from within the provided arguments.
456
436
  # Supports multi-word commands, using the largest possible match.
457
-
458
437
  def longest_valid_command_name_from(args)
459
438
  valid_command_names_from(*args.dup).max
460
439
  end