commander-openflighthpc 2.0.2 → 2.1.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.
- checksums.yaml +4 -4
- data/README.md +7 -87
- data/commander-openflighthpc.gemspec +1 -0
- data/lib/commander.rb +3 -4
- data/lib/commander/cli.rb +15 -76
- data/lib/commander/command.rb +89 -175
- data/lib/commander/error_handler.rb +72 -0
- data/lib/commander/help_formatters.rb +0 -4
- data/lib/commander/help_formatters/terminal.rb +0 -5
- data/lib/commander/help_formatters/terminal/command_help.erb +12 -6
- data/lib/commander/help_formatters/terminal/help.erb +10 -4
- data/lib/commander/runner.rb +98 -129
- data/lib/commander/version.rb +1 -1
- metadata +19 -44
- data/bin/commander +0 -104
- data/lib/commander/blank.rb +0 -7
- data/lib/commander/core_ext.rb +0 -2
- data/lib/commander/core_ext/array.rb +0 -24
- data/lib/commander/core_ext/object.rb +0 -8
- data/lib/commander/help_formatters/terminal/subcommand_help.erb +0 -23
- data/lib/commander/help_formatters/terminal_compact.rb +0 -11
- data/lib/commander/help_formatters/terminal_compact/command_help.erb +0 -26
- data/lib/commander/help_formatters/terminal_compact/help.erb +0 -29
- data/lib/commander/help_formatters/terminal_compact/subcommand_help.erb +0 -15
- data/lib/commander/import.rb +0 -5
- data/lib/commander/patches/decimal-integer.rb +0 -17
- data/lib/commander/patches/help_formatter_binding.rb +0 -15
- data/lib/commander/patches/implicit-short-tags.rb +0 -75
- data/lib/commander/patches/priority_sort.rb +0 -21
- data/lib/commander/patches/validate_inputs.rb +0 -79
- data/lib/commander/platform.rb +0 -7
- data/spec/command_spec.rb +0 -157
- data/spec/configure_spec.rb +0 -37
- data/spec/core_ext/array_spec.rb +0 -18
- data/spec/core_ext/object_spec.rb +0 -19
- data/spec/help_formatters/terminal_compact_spec.rb +0 -69
- data/spec/help_formatters/terminal_spec.rb +0 -67
- data/spec/methods_spec.rb +0 -61
- data/spec/patches/validate_inputs_spec.rb +0 -84
- data/spec/runner_spec.rb +0 -672
- data/spec/spec_helper.rb +0 -79
- data/spec/ui_spec.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2de2c466191b2e6eec17147fa3f65c84910946e26986eac3b2b0542dc339ae6f
|
4
|
+
data.tar.gz: b4e6443b1c09467439509b0661d4c43c6c7c324d62d900ed111a41431d8cc742
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5c5216978964ac2a4e100cd37d89835ca432372ee57f760f1f9d940d4319c2d3579f980d0adf6bbd9ef77c8de1c6b9476f1c4ac2f0e504a89e84f53d98c1086
|
7
|
+
data.tar.gz: 8b2650058b67db6b92d9ec19d924e171004019a6ddc730ed34f35144613bfd101509e45461b882e7213bcfcbd9899295cc10d32f5a2a76e24ac79b522d007ea8
|
data/README.md
CHANGED
@@ -12,8 +12,6 @@ project that support the OpenFlightHPC tools.
|
|
12
12
|
To ship a new release, do the following:
|
13
13
|
|
14
14
|
* Increment the version number in `version.rb`
|
15
|
-
* Run `rake build`
|
16
|
-
* Run `rake release`
|
17
15
|
|
18
16
|
Documentation from the upstream project follows.
|
19
17
|
|
@@ -23,42 +21,26 @@ Documentation from the upstream project follows.
|
|
23
21
|
|
24
22
|
The complete solution for Ruby command-line executables.
|
25
23
|
Commander bridges the gap between other terminal related libraries
|
26
|
-
you know and love (
|
24
|
+
you know and love (Slop, HighLine), while providing many new
|
27
25
|
features, and an elegant API.
|
28
26
|
|
29
27
|
## Features
|
30
28
|
|
31
|
-
* Easier than baking cookies
|
32
|
-
* Parses options using OptionParser
|
33
|
-
* Auto-populates struct with options ( no more `{ |v| options[:recursive] = v }` )
|
34
29
|
* Auto-generates help documentation via pluggable help formatters
|
35
30
|
* Optional default command when none is present
|
36
31
|
* Global / Command level options
|
37
|
-
* Packaged with
|
32
|
+
* Packaged with one help formatters (Terminal)
|
38
33
|
* Imports the highline gem for interacting with the terminal
|
39
34
|
* Adds additional user interaction functionality
|
40
35
|
* Highly customizable progress bar with intuitive, simple usage
|
41
|
-
* Multi-word command name support such as `drupal module install MOD`, rather than `drupal module_install MOD`
|
42
36
|
* Sexy paging for long bodies of text
|
43
|
-
* Support for MacOS text-to-speech
|
44
37
|
* Command aliasing (very powerful, as both switches and arguments can be used)
|
45
|
-
* Growl notification support for MacOS
|
46
38
|
* Use the `commander` executable to initialize a commander driven program
|
47
39
|
|
48
40
|
## Installation
|
49
41
|
|
50
42
|
$ gem install commander
|
51
43
|
|
52
|
-
## Quick Start
|
53
|
-
|
54
|
-
To generate a quick template for a commander app, run:
|
55
|
-
|
56
|
-
$ commander init yourfile.rb
|
57
|
-
|
58
|
-
To generate a quick modular style template for a commander app, run:
|
59
|
-
|
60
|
-
$ commander init --modular yourfile.rb
|
61
|
-
|
62
44
|
## Example
|
63
45
|
|
64
46
|
For more option examples view the `Commander::Command#option` method. Also
|
@@ -87,8 +69,8 @@ end
|
|
87
69
|
command :bar do |c|
|
88
70
|
c.syntax = 'foobar bar [options]'
|
89
71
|
c.description = 'Display bar with optional prefix and suffix'
|
90
|
-
c.option '--prefix STRING',
|
91
|
-
c.option '--suffix STRING',
|
72
|
+
c.option '--prefix STRING', 'Adds a prefix to bar'
|
73
|
+
c.option '--suffix STRING', 'Adds a suffix to bar'
|
92
74
|
c.action do |args, options|
|
93
75
|
options.default :prefix => '(', :suffix => ')'
|
94
76
|
say "#{options.prefix}bar#{options.suffix}"
|
@@ -142,8 +124,8 @@ to set defaults in a clean manner for options which have not been set.
|
|
142
124
|
|
143
125
|
```ruby
|
144
126
|
command :foo do |c|
|
145
|
-
c.option '--interval SECONDS',
|
146
|
-
c.option '--timeout SECONDS',
|
127
|
+
c.option '--interval SECONDS', 'Interval in seconds'
|
128
|
+
c.option '--timeout SECONDS', 'Timeout in seconds'
|
147
129
|
c.action do |args, options|
|
148
130
|
options.default \
|
149
131
|
:interval => 2,
|
@@ -239,74 +221,12 @@ Which will output the rest of the help doc, along with:
|
|
239
221
|
|
240
222
|
### Global Options
|
241
223
|
|
242
|
-
|
243
|
-
default at the global level, such as `--version`, and `--help`. Using
|
244
|
-
`#global_option` you can add additional global options:
|
245
|
-
|
246
|
-
```ruby
|
247
|
-
global_option('-c', '--config FILE', 'Load config data for your commands to use') { |file| ... }
|
248
|
-
```
|
249
|
-
|
250
|
-
This method accepts the same syntax as `Commander::Command#option` so check it out for documentation.
|
251
|
-
|
252
|
-
All global options regardless of providing a block are accessable at the command level. This
|
253
|
-
means that instead of the following:
|
254
|
-
|
255
|
-
```ruby
|
256
|
-
global_option('--verbose') { $verbose = true }
|
257
|
-
...
|
258
|
-
c.action do |args, options|
|
259
|
-
say 'foo' if $verbose
|
260
|
-
...
|
261
|
-
```
|
262
|
-
|
263
|
-
You may:
|
264
|
-
|
265
|
-
```ruby
|
266
|
-
global_option '--verbose'
|
267
|
-
...
|
268
|
-
c.action do |args, options|
|
269
|
-
say 'foo' if options.verbose
|
270
|
-
...
|
271
|
-
```
|
272
|
-
|
273
|
-
### Formatters
|
274
|
-
|
275
|
-
Two core formatters are currently available, the default `Terminal` formatter
|
276
|
-
as well as `TerminalCompact`. To utilize a different formatter simply use
|
277
|
-
`:help_formatter` like below:
|
278
|
-
|
279
|
-
```ruby
|
280
|
-
program :help_formatter, Commander::HelpFormatter::TerminalCompact
|
281
|
-
```
|
282
|
-
|
283
|
-
Or utilize the help formatter aliases:
|
284
|
-
|
285
|
-
```ruby
|
286
|
-
program :help_formatter, :compact
|
287
|
-
```
|
288
|
-
|
289
|
-
This abstraction could be utilized to generate HTML documentation for your executable.
|
224
|
+
WIP: Update globals behaviour
|
290
225
|
|
291
226
|
### Tracing
|
292
227
|
|
293
228
|
WIP: Update OpenFlight --trace behaviour
|
294
229
|
|
295
|
-
## Tips
|
296
|
-
|
297
|
-
When adding a global or command option, `OptionParser` no longer implicitly adds a small
|
298
|
-
switch unless explicitly stated.
|
299
|
-
|
300
|
-
## ASCII Tables
|
301
|
-
|
302
|
-
For feature rich ASCII tables for your terminal app check out the terminal-table gem at http://github.com/tj/terminal-table
|
303
|
-
|
304
|
-
+----------+-------+----+--------+-----------------------+
|
305
|
-
| Terminal | Table | Is | Wicked | Awesome |
|
306
|
-
+----------+-------+----+--------+-----------------------+
|
307
|
-
| | | | | get it while its hot! |
|
308
|
-
+----------+-------+----+--------+-----------------------+
|
309
|
-
|
310
230
|
## Running Specifications
|
311
231
|
|
312
232
|
$ rake spec
|
data/lib/commander.rb
CHANGED
@@ -23,11 +23,10 @@
|
|
23
23
|
|
24
24
|
require 'highline'
|
25
25
|
$terminal = HighLine.new
|
26
|
+
|
27
|
+
require 'commander/error_handler'
|
26
28
|
require 'commander/version'
|
27
|
-
require 'commander/blank'
|
28
|
-
require 'commander/core_ext'
|
29
|
-
require 'commander/runner'
|
30
29
|
require 'commander/command'
|
30
|
+
require 'commander/runner'
|
31
31
|
require 'commander/help_formatters'
|
32
|
-
require 'commander/platform'
|
33
32
|
require 'commander/cli'
|
data/lib/commander/cli.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
|
+
require 'slop'
|
2
|
+
|
1
3
|
module Commander
|
2
4
|
module CLI
|
3
5
|
##
|
4
6
|
# Wrapper run command with error handling
|
5
7
|
def run!(*args)
|
8
|
+
Commander.traceable_error_handler(*args) do |new_args|
|
9
|
+
run(*new_args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(*args)
|
6
14
|
instance = Runner.new(
|
7
15
|
@program, commands, default_command,
|
8
|
-
|
16
|
+
global_slop, aliases, args
|
9
17
|
)
|
10
18
|
instance.run
|
11
|
-
rescue StandardError, Interrupt => e
|
12
|
-
$stderr.puts e.backtrace.reverse if args.include?('--trace')
|
13
|
-
error_handler(instance, e)
|
14
19
|
end
|
15
20
|
|
16
21
|
##
|
@@ -24,8 +29,6 @@ module Commander
|
|
24
29
|
# program :description, 'Commander utility program.'
|
25
30
|
# program :help, 'Copyright', '2008 TJ Holowaychuk'
|
26
31
|
# program :help, 'Anything', 'You want'
|
27
|
-
# program :help_formatter, :compact
|
28
|
-
# program :help_formatter, Commander::HelpFormatter::TerminalCompact
|
29
32
|
#
|
30
33
|
# # Get data
|
31
34
|
# program :name # => 'Commander'
|
@@ -35,6 +38,7 @@ module Commander
|
|
35
38
|
# :version (required) Program version triple, ex: '0.0.1'
|
36
39
|
# :description (required) Program description
|
37
40
|
# :name Program name, defaults to basename of executable
|
41
|
+
# :config An optional argument to be passed into the action
|
38
42
|
# :help_formatter Defaults to Commander::HelpFormatter::Terminal
|
39
43
|
# :help Allows addition of arbitrary global help blocks
|
40
44
|
# :help_paging Flag for toggling help paging
|
@@ -80,37 +84,14 @@ module Commander
|
|
80
84
|
|
81
85
|
##
|
82
86
|
# Hash of Global Options
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
command(:help).run(*args)
|
89
|
-
exit 0
|
90
|
-
end
|
91
|
-
global_option('--version', 'Display version information') do
|
92
|
-
say version
|
93
|
-
exit 0
|
94
|
-
end
|
87
|
+
#
|
88
|
+
def global_slop
|
89
|
+
@global_slop ||= Slop::Options.new.tap do |slop|
|
90
|
+
slop.bool '-h', '--help', 'Display help documentation'
|
91
|
+
slop.bool '--version', 'Display version information'
|
95
92
|
end
|
96
93
|
end
|
97
94
|
|
98
|
-
##
|
99
|
-
# Add a global option; follows the same syntax as Command#option
|
100
|
-
# This would be used for switches such as --version
|
101
|
-
# NOTE: --trace is special and does not appear in the help
|
102
|
-
# It is intended for debugging purposes
|
103
|
-
|
104
|
-
def global_option(*args, &block)
|
105
|
-
switches, description = Runner.separate_switches_from_description(*args)
|
106
|
-
global_options << {
|
107
|
-
args: args,
|
108
|
-
proc: block,
|
109
|
-
switches: switches,
|
110
|
-
description: description,
|
111
|
-
}
|
112
|
-
end
|
113
|
-
|
114
95
|
##
|
115
96
|
# Define and get a command by name
|
116
97
|
#
|
@@ -134,47 +115,5 @@ module Commander
|
|
134
115
|
commands[alias_name.to_s] = command name
|
135
116
|
aliases[alias_name.to_s] = args
|
136
117
|
end
|
137
|
-
|
138
|
-
def error_handler(runner, e)
|
139
|
-
error_msg = "#{Paint[runner.program(:name), '#2794d8']}: #{Paint[e.to_s, :red, :bright]}"
|
140
|
-
exit_code = e.respond_to?(:exit_code) ? e.exit_code.to_i : 1
|
141
|
-
case e
|
142
|
-
when OptionParser::InvalidOption,
|
143
|
-
Commander::Runner::InvalidCommandError,
|
144
|
-
Commander::Patches::CommandUsageError
|
145
|
-
# Display the error message for a specific command. Most likely due to
|
146
|
-
# invalid command syntax
|
147
|
-
if cmd = runner.active_command
|
148
|
-
$stderr.puts error_msg
|
149
|
-
$stderr.puts "\nUsage:\n\n"
|
150
|
-
runner.command('help').run(cmd.name)
|
151
|
-
# Display the main app help text when called without `--help`
|
152
|
-
elsif runner.args_without_command_name.empty?
|
153
|
-
$stderr.puts "Usage:\n\n"
|
154
|
-
runner.command('help').run(:error)
|
155
|
-
# Display the main app help text when called with arguments. Mostly
|
156
|
-
# likely an invalid syntax error
|
157
|
-
else
|
158
|
-
$stderr.puts error_msg
|
159
|
-
$stderr.puts "\nUsage:\n\n"
|
160
|
-
runner.command('help').run(:error)
|
161
|
-
end
|
162
|
-
exit_code = 254
|
163
|
-
# Display the help text for sub command groups when called without `--help`
|
164
|
-
when SubCommandGroupError
|
165
|
-
if cmd = runner.active_command
|
166
|
-
$stderr.puts "Usage:\n\n"
|
167
|
-
runner.command('help').run(cmd.name)
|
168
|
-
end
|
169
|
-
exit_code = 254
|
170
|
-
when Interrupt
|
171
|
-
$stderr.puts 'Received Interrupt!'
|
172
|
-
exit_code = 255
|
173
|
-
# Catch all error message for all other issues
|
174
|
-
else
|
175
|
-
$stderr.puts error_msg
|
176
|
-
end
|
177
|
-
exit(exit_code)
|
178
|
-
end
|
179
118
|
end
|
180
119
|
end
|
data/lib/commander/command.rb
CHANGED
@@ -1,60 +1,37 @@
|
|
1
|
-
require '
|
2
|
-
require 'commander/patches/implicit-short-tags'
|
3
|
-
require 'commander/patches/decimal-integer'
|
4
|
-
require 'commander/patches/validate_inputs'
|
5
|
-
require 'commander/patches/help_formatter_binding'
|
6
|
-
require 'commander/patches/priority_sort'
|
7
|
-
|
8
|
-
OptionParser.prepend Commander::Patches::ImplicitShortTags
|
9
|
-
OptionParser.prepend Commander::Patches::DecimalInteger
|
1
|
+
require 'slop'
|
10
2
|
|
11
3
|
module Commander
|
12
|
-
class SubCommandGroupError < StandardError; end
|
13
|
-
|
14
4
|
class Command
|
15
|
-
|
16
|
-
prepend Patches::PrioritySort
|
17
|
-
|
18
|
-
attr_accessor :name, :examples, :syntax, :description
|
19
|
-
attr_accessor :summary, :proxy_options, :options, :hidden
|
20
|
-
attr_reader :sub_command_group
|
5
|
+
class CommandUsageError < StandardError; end
|
21
6
|
|
22
|
-
|
23
|
-
|
7
|
+
attr_accessor :name, :examples, :syntax, :description, :priority
|
8
|
+
attr_accessor :summary, :options
|
24
9
|
|
25
10
|
##
|
26
|
-
#
|
27
|
-
|
28
|
-
class Options
|
29
|
-
include Blank
|
30
|
-
|
31
|
-
def initialize
|
32
|
-
@table = {}
|
33
|
-
end
|
11
|
+
# Initialize new command with specified _name_.
|
34
12
|
|
35
|
-
|
36
|
-
|
37
|
-
|
13
|
+
def initialize(name)
|
14
|
+
@name, @examples, @when_called = name.to_s, [], []
|
15
|
+
@options = []
|
16
|
+
end
|
38
17
|
|
39
|
-
|
40
|
-
|
41
|
-
|
18
|
+
# Allows the commands to be sorted via priority
|
19
|
+
def <=>(other)
|
20
|
+
# Different classes can not be compared and thus are considered
|
21
|
+
# equal in priority
|
22
|
+
return 0 unless self.class == other.class
|
42
23
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
24
|
+
# Sort firstly based on the commands priority
|
25
|
+
comp = (self.priority || 0) <=> (other.priority || 0)
|
46
26
|
|
47
|
-
|
48
|
-
|
49
|
-
end
|
27
|
+
# Fall back on name comparison if priority is equal
|
28
|
+
comp == 0 ? self.name <=> other.name : comp
|
50
29
|
end
|
51
30
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
@name, @examples, @when_called = name.to_s, [], []
|
57
|
-
@options, @proxy_options = [], []
|
31
|
+
def run!(args, opts, config)
|
32
|
+
assert_correct_number_of_args!(args)
|
33
|
+
callee = @when_called.dup
|
34
|
+
callee.shift&.send(callee.shift || :call, args, opts, config)
|
58
35
|
end
|
59
36
|
|
60
37
|
##
|
@@ -77,59 +54,32 @@ module Commander
|
|
77
54
|
##
|
78
55
|
# Add an option.
|
79
56
|
#
|
80
|
-
#
|
81
|
-
# for additional usage documentation. A block may optionally be
|
82
|
-
# passed to handle the option, otherwise the _options_ struct seen below
|
83
|
-
# contains the results of this option. This handles common formats such as:
|
84
|
-
#
|
85
|
-
# -h, --help options.help # => bool
|
86
|
-
# --[no-]feature options.feature # => bool
|
87
|
-
# --large-switch options.large_switch # => bool
|
88
|
-
# --file FILE options.file # => file passed
|
89
|
-
# --list WORDS options.list # => array
|
90
|
-
# --date [DATE] options.date # => date or nil when optional argument not set
|
91
|
-
#
|
92
|
-
# === Examples
|
93
|
-
#
|
94
|
-
# command :something do |c|
|
95
|
-
# c.option '--recursive', 'Do something recursively'
|
96
|
-
# c.option '--file FILE', 'Specify a file'
|
97
|
-
# c.option('--info', 'Display info') { puts "handle with block" }
|
98
|
-
# c.option '--[no-]feature', 'With or without feature'
|
99
|
-
# c.option '--list FILES', Array, 'List the files specified'
|
100
|
-
#
|
101
|
-
# c.when_called do |args, options|
|
102
|
-
# do_something_recursively if options.recursive
|
103
|
-
# do_something_with_file options.file if options.file
|
104
|
-
# end
|
105
|
-
# end
|
106
|
-
#
|
107
|
-
# === Help Formatters
|
108
|
-
#
|
109
|
-
# This method also parses the arguments passed in order to determine
|
110
|
-
# which were switches, and which were descriptions for the
|
111
|
-
# option which can later be used within help formatters
|
112
|
-
# using option[:switches] and option[:description].
|
113
|
-
#
|
114
|
-
# === Input Parsing
|
115
|
-
#
|
116
|
-
# Since Commander utilizes OptionParser you can pre-parse and evaluate
|
117
|
-
# option arguments. Simply require 'optparse/time', or 'optparse/date', as these
|
118
|
-
# objects must respond to #parse.
|
119
|
-
#
|
120
|
-
# c.option '--time TIME', Time
|
121
|
-
# c.option '--date [DATE]', Date
|
57
|
+
# This is the legacy `option` method which now wraps `slop`
|
122
58
|
#
|
123
59
|
|
124
60
|
def option(*args, default: nil, &block)
|
61
|
+
# Split the description from the switchers
|
125
62
|
switches, description = Runner.separate_switches_from_description(*args)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
63
|
+
|
64
|
+
# Other switches are normally short tags and something like below
|
65
|
+
# In this case the VALUE needs to be ignored
|
66
|
+
# -k VALUE
|
67
|
+
other_switches = switches.dup.tap(&:pop).map do |string|
|
68
|
+
string.split(' ').first
|
69
|
+
end
|
70
|
+
|
71
|
+
long_switch, meta = switches.last.split(' ', 2)
|
72
|
+
|
73
|
+
# The meta flag is the VALUE from denotes if its a boolean or
|
74
|
+
# string method
|
75
|
+
method = meta.nil? ? :bool : :string
|
76
|
+
|
77
|
+
# Adds the option to Slop
|
78
|
+
slop.send(method, *other_switches, long_switch, description, default: default)
|
79
|
+
end
|
80
|
+
|
81
|
+
def slop
|
82
|
+
@slop ||= Slop::Options.new
|
133
83
|
end
|
134
84
|
|
135
85
|
##
|
@@ -139,16 +89,10 @@ module Commander
|
|
139
89
|
# === Examples
|
140
90
|
#
|
141
91
|
# # Simple block handling
|
142
|
-
# c.when_called do |args, options|
|
92
|
+
# c.when_called do |args, options, config|
|
143
93
|
# # do something
|
144
94
|
# end
|
145
95
|
#
|
146
|
-
# # Create inst of Something and pass args / options
|
147
|
-
# c.when_called MyLib::Command::Something
|
148
|
-
#
|
149
|
-
# # Create inst of Something and use arbitrary method
|
150
|
-
# c.when_called MyLib::Command::Something, :some_method
|
151
|
-
#
|
152
96
|
# # Pass an object to handle callback (requires method symbol)
|
153
97
|
# c.when_called SomeObject, :some_method
|
154
98
|
#
|
@@ -160,102 +104,72 @@ module Commander
|
|
160
104
|
alias action when_called
|
161
105
|
|
162
106
|
##
|
163
|
-
#
|
164
|
-
#
|
165
|
-
|
166
|
-
def sub_command_group?
|
167
|
-
!!@sub_command_group
|
168
|
-
end
|
169
|
-
|
170
|
-
def sub_command_group=(value)
|
171
|
-
@sub_command_group = value
|
172
|
-
self.action { raise SubCommandGroupError } if value
|
173
|
-
end
|
107
|
+
# Causes the option parsing to be skipped. The flags will be passed
|
108
|
+
# down within the args instead
|
109
|
+
#
|
174
110
|
|
175
|
-
def
|
176
|
-
@
|
177
|
-
if @when_called.empty?
|
178
|
-
action do |args, opts|
|
179
|
-
unless args.empty?
|
180
|
-
raise Commander::Runner::InvalidCommandError,
|
181
|
-
"unrecognized subcommand '#{args[0]}'"
|
182
|
-
end
|
183
|
-
runner.command('help').run(ARGV[0])
|
184
|
-
end
|
185
|
-
end
|
111
|
+
def skip_option_parsing(set = true)
|
112
|
+
@skip_option_parsing ||= set
|
186
113
|
end
|
187
114
|
|
188
115
|
##
|
189
|
-
#
|
190
|
-
#
|
191
|
-
# * parses options, call option blocks
|
192
|
-
# * invokes when_called proc
|
116
|
+
# Flags the command not to appear in general help text
|
193
117
|
#
|
194
118
|
|
195
|
-
def
|
196
|
-
|
119
|
+
def hidden(set = true)
|
120
|
+
@hidden ||= set
|
197
121
|
end
|
198
122
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
# Parses options and calls associated procs,
|
203
|
-
# returning the arguments remaining.
|
123
|
+
def inspect
|
124
|
+
"<Commander::Command:#{name}>"
|
125
|
+
end
|
204
126
|
|
205
|
-
def
|
206
|
-
|
207
|
-
|
208
|
-
|
127
|
+
def assert_correct_number_of_args!(args)
|
128
|
+
return if primary_command_word == 'help'
|
129
|
+
too_many = too_many_args?(args)
|
130
|
+
if too_many
|
131
|
+
raise CommandUsageError, "excess arguments for command '#{primary_command_word}'"
|
132
|
+
elsif too_few_args?(args)
|
133
|
+
raise CommandUsageError, "insufficient arguments for command '#{primary_command_word}'"
|
209
134
|
end
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
135
|
+
end
|
136
|
+
|
137
|
+
def syntax_parts
|
138
|
+
@syntax_parts ||= syntax.split.tap do |parts|
|
139
|
+
while part = parts.shift do
|
140
|
+
break if part == primary_command_word || parts.length == 0
|
214
141
|
end
|
215
142
|
end
|
216
|
-
opt.parse! default_opt
|
217
|
-
opt.parse! args
|
218
143
|
end
|
219
144
|
|
220
|
-
|
221
|
-
|
145
|
+
def primary_command_word
|
146
|
+
name.split.last
|
147
|
+
end
|
222
148
|
|
223
|
-
def
|
224
|
-
|
225
|
-
object = callee.shift
|
226
|
-
meth = callee.shift || :call
|
227
|
-
options = proxy_option_struct
|
228
|
-
case object
|
229
|
-
when Proc then object.call(args, options)
|
230
|
-
when Class then meth != :call ? object.new.send(meth, args, options) : object.new(args, options)
|
231
|
-
else object.send(meth, args, options) if object
|
232
|
-
end
|
149
|
+
def total_argument_count
|
150
|
+
syntax_parts.length
|
233
151
|
end
|
234
152
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
def proxy_option_struct
|
240
|
-
proxy_options.each_with_object(Options.new) do |(option, value), options|
|
241
|
-
# options that are present will evaluate to true
|
242
|
-
value = true if value.nil?
|
243
|
-
options.__send__ :"#{option}=", value
|
244
|
-
options
|
245
|
-
end
|
153
|
+
def optional_argument_count
|
154
|
+
syntax_parts.select do |part|
|
155
|
+
part[0] == '[' && part[-1] == ']'
|
156
|
+
end.length
|
246
157
|
end
|
247
158
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
# and work with option values.
|
159
|
+
def variable_arg?
|
160
|
+
syntax_parts.any? {|part| part[-4..-1] == '...]' || part[-3..-1] == '...'}
|
161
|
+
end
|
252
162
|
|
253
|
-
def
|
254
|
-
|
163
|
+
def required_argument_count
|
164
|
+
total_argument_count - optional_argument_count
|
255
165
|
end
|
256
166
|
|
257
|
-
def
|
258
|
-
|
167
|
+
def too_many_args?(args)
|
168
|
+
!variable_arg? && args.length > total_argument_count
|
169
|
+
end
|
170
|
+
|
171
|
+
def too_few_args?(args)
|
172
|
+
args.length < required_argument_count
|
259
173
|
end
|
260
174
|
end
|
261
175
|
end
|