commander-openflighthpc 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|