clamp 0.2.3 → 0.3.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.
- data/README.markdown +6 -2
- data/examples/flipflop +4 -2
- data/lib/clamp/attribute_declaration.rb +4 -4
- data/lib/clamp/command.rb +22 -15
- data/lib/clamp/help.rb +6 -2
- data/lib/clamp/option/declaration.rb +1 -1
- data/lib/clamp/parameter/parsing.rb +1 -5
- data/lib/clamp/subcommand/declaration.rb +16 -31
- data/lib/clamp/subcommand/parsing.rb +42 -0
- data/lib/clamp/version.rb +1 -1
- data/spec/clamp/command_group_spec.rb +82 -24
- metadata +26 -36
- data/lib/clamp/subcommand/execution.rb +0 -36
data/README.markdown
CHANGED
@@ -205,11 +205,13 @@ Clamp generates an anonymous subclass of the current class, to represent the sub
|
|
205
205
|
|
206
206
|
### Default subcommand
|
207
207
|
|
208
|
-
You can
|
208
|
+
You can set a default subcommand, at the class level, as follows:
|
209
209
|
|
210
210
|
class MainCommand < Clamp::Command
|
211
211
|
|
212
|
-
default_subcommand
|
212
|
+
self.default_subcommand = "status"
|
213
|
+
|
214
|
+
subcommand "status", "Display current status" do
|
213
215
|
|
214
216
|
def execute
|
215
217
|
# ...
|
@@ -219,6 +221,8 @@ You can mark a subcommand as "default" by using `default_subcommand` to declare
|
|
219
221
|
|
220
222
|
end
|
221
223
|
|
224
|
+
Then, if when no SUBCOMMAND argument is provided, the default will be selected.
|
225
|
+
|
222
226
|
### Subcommand options and parameters
|
223
227
|
|
224
228
|
Options are inheritable, so any options declared for a command are supported for it's sub-classes (e.g. those created using `subcommand`). Parameters, on the other hand, are not inherited - each subcommand must declare it's own parameter list.
|
data/examples/flipflop
CHANGED
@@ -12,7 +12,9 @@ class FlipFlop < Clamp::Command
|
|
12
12
|
exit(0)
|
13
13
|
end
|
14
14
|
|
15
|
-
default_subcommand
|
15
|
+
self.default_subcommand = "flip"
|
16
|
+
|
17
|
+
subcommand "flip", "flip it" do
|
16
18
|
def execute
|
17
19
|
puts "FLIPPED"
|
18
20
|
end
|
@@ -23,7 +25,7 @@ class FlipFlop < Clamp::Command
|
|
23
25
|
puts "FLOPPED"
|
24
26
|
end
|
25
27
|
end
|
26
|
-
|
28
|
+
|
27
29
|
end
|
28
30
|
|
29
31
|
FlipFlop.run
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Clamp
|
2
|
-
|
2
|
+
|
3
3
|
module AttributeDeclaration
|
4
4
|
|
5
5
|
protected
|
6
|
-
|
6
|
+
|
7
7
|
def define_accessors_for(attribute, &block)
|
8
8
|
define_reader_for(attribute)
|
9
9
|
define_default_for(attribute)
|
10
10
|
define_writer_for(attribute, &block)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def define_reader_for(attribute)
|
14
14
|
define_method(attribute.read_method) do
|
15
15
|
if instance_variable_defined?(attribute.ivar_name)
|
@@ -36,5 +36,5 @@ module Clamp
|
|
36
36
|
end
|
37
37
|
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
end
|
data/lib/clamp/command.rb
CHANGED
@@ -5,15 +5,15 @@ require 'clamp/option/parsing'
|
|
5
5
|
require 'clamp/parameter/declaration'
|
6
6
|
require 'clamp/parameter/parsing'
|
7
7
|
require 'clamp/subcommand/declaration'
|
8
|
-
require 'clamp/subcommand/
|
8
|
+
require 'clamp/subcommand/parsing'
|
9
9
|
|
10
10
|
module Clamp
|
11
11
|
|
12
12
|
# {Command} models a shell command. Each command invocation is a new object.
|
13
|
-
# Command options and parameters are represented as attributes
|
13
|
+
# Command options and parameters are represented as attributes
|
14
14
|
# (see {Command::Declaration}).
|
15
15
|
#
|
16
|
-
# The main entry-point is {#run}, which uses {#parse} to populate attributes based
|
16
|
+
# The main entry-point is {#run}, which uses {#parse} to populate attributes based
|
17
17
|
# on an array of command-line arguments, then calls {#execute} (which you provide)
|
18
18
|
# to make it go.
|
19
19
|
#
|
@@ -32,7 +32,7 @@ module Clamp
|
|
32
32
|
# @return [String] the path used to invoke this command
|
33
33
|
#
|
34
34
|
attr_reader :invocation_path
|
35
|
-
|
35
|
+
|
36
36
|
# @return [Array<String>] unconsumed command-line arguments
|
37
37
|
#
|
38
38
|
def remaining_arguments
|
@@ -48,12 +48,13 @@ module Clamp
|
|
48
48
|
@remaining_arguments = arguments.dup
|
49
49
|
parse_options
|
50
50
|
parse_parameters
|
51
|
-
|
51
|
+
parse_subcommand
|
52
|
+
handle_remaining_arguments
|
52
53
|
end
|
53
54
|
|
54
55
|
# Run the command, with the specified arguments.
|
55
56
|
#
|
56
|
-
# This calls {#parse} to process the command-line arguments,
|
57
|
+
# This calls {#parse} to process the command-line arguments,
|
57
58
|
# then delegates to {#execute}.
|
58
59
|
#
|
59
60
|
# @param [Array<String>] arguments command-line arguments
|
@@ -64,12 +65,12 @@ module Clamp
|
|
64
65
|
end
|
65
66
|
|
66
67
|
# Execute the command (assuming that all options/parameters have been set).
|
67
|
-
#
|
68
|
+
#
|
68
69
|
# This method is designed to be overridden in sub-classes.
|
69
70
|
#
|
70
71
|
def execute
|
71
|
-
if
|
72
|
-
|
72
|
+
if @subcommand
|
73
|
+
@subcommand.execute
|
73
74
|
else
|
74
75
|
raise "you need to define #execute"
|
75
76
|
end
|
@@ -83,12 +84,18 @@ module Clamp
|
|
83
84
|
|
84
85
|
include Clamp::Option::Parsing
|
85
86
|
include Clamp::Parameter::Parsing
|
86
|
-
include Clamp::Subcommand::
|
87
|
+
include Clamp::Subcommand::Parsing
|
87
88
|
|
88
89
|
protected
|
89
|
-
|
90
|
+
|
90
91
|
attr_accessor :context
|
91
92
|
|
93
|
+
def handle_remaining_arguments
|
94
|
+
unless remaining_arguments.empty?
|
95
|
+
signal_usage_error "too many arguments"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
92
99
|
private
|
93
100
|
|
94
101
|
def signal_usage_error(message)
|
@@ -97,8 +104,8 @@ module Clamp
|
|
97
104
|
raise e
|
98
105
|
end
|
99
106
|
|
100
|
-
def
|
101
|
-
raise
|
107
|
+
def request_help
|
108
|
+
raise HelpWanted, self
|
102
109
|
end
|
103
110
|
|
104
111
|
class << self
|
@@ -113,9 +120,9 @@ module Clamp
|
|
113
120
|
# @param [String] invocation_path the path used to invoke the command
|
114
121
|
# @param [Array<String>] arguments command-line arguments
|
115
122
|
# @param [Hash] context additional data the command may need
|
116
|
-
#
|
123
|
+
#
|
117
124
|
def run(invocation_path = File.basename($0), arguments = ARGV, context = {})
|
118
|
-
begin
|
125
|
+
begin
|
119
126
|
new(invocation_path, context).run(arguments)
|
120
127
|
rescue Clamp::UsageError => e
|
121
128
|
$stderr.puts "ERROR: #{e.message}"
|
data/lib/clamp/help.rb
CHANGED
@@ -23,8 +23,12 @@ module Clamp
|
|
23
23
|
attr_reader :description
|
24
24
|
|
25
25
|
def derived_usage_description
|
26
|
-
parts =
|
27
|
-
parts.
|
26
|
+
parts = ["[OPTIONS]"]
|
27
|
+
parts += parameters.map { |a| a.name }
|
28
|
+
if has_subcommands?
|
29
|
+
parts << "SUBCOMMAND"
|
30
|
+
parts << "[ARGS] ..."
|
31
|
+
end
|
28
32
|
parts.join(" ")
|
29
33
|
end
|
30
34
|
|
@@ -35,7 +35,7 @@ module Clamp
|
|
35
35
|
help_switches = ["--help"]
|
36
36
|
help_switches.unshift("-h") unless effective_options.find { |o| o.handles?("-h") }
|
37
37
|
option help_switches, :flag, "print help" do
|
38
|
-
|
38
|
+
request_help
|
39
39
|
end
|
40
40
|
end
|
41
41
|
@implicit_options_declared = true
|
@@ -4,7 +4,7 @@ module Clamp
|
|
4
4
|
module Parsing
|
5
5
|
|
6
6
|
protected
|
7
|
-
|
7
|
+
|
8
8
|
def parse_parameters
|
9
9
|
|
10
10
|
self.class.parameters.each do |parameter|
|
@@ -16,10 +16,6 @@ module Clamp
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
unless remaining_arguments.empty?
|
20
|
-
signal_usage_error "too many arguments"
|
21
|
-
end
|
22
|
-
|
23
19
|
end
|
24
20
|
|
25
21
|
end
|
@@ -10,48 +10,33 @@ module Clamp
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def subcommand(name, description, subcommand_class = self, &block)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
has_subcommands!(name)
|
19
|
-
declare_subcommand(name, description, subcommand_class, &block)
|
13
|
+
if block
|
14
|
+
# generate a anonymous sub-class
|
15
|
+
subcommand_class = Class.new(subcommand_class, &block)
|
16
|
+
end
|
17
|
+
recognised_subcommands << Subcommand.new(name, description, subcommand_class)
|
20
18
|
end
|
21
19
|
|
22
20
|
def has_subcommands?
|
23
|
-
|
21
|
+
!recognised_subcommands.empty?
|
24
22
|
end
|
25
23
|
|
26
24
|
def find_subcommand(name)
|
27
25
|
recognised_subcommands.find { |sc| sc.is_called?(name) }
|
28
26
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
|
28
|
+
attr_writer :default_subcommand
|
29
|
+
|
30
|
+
def default_subcommand(*args, &block)
|
31
|
+
if args.empty?
|
32
|
+
@default_subcommand
|
35
33
|
else
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
parameter "[ARGS] ...", "subcommand arguments", :attribute_name => :subcommand_arguments
|
42
|
-
@has_subcommands = true
|
34
|
+
$stderr.puts "WARNING: Clamp default_subcommand syntax has changed; check the README."
|
35
|
+
$stderr.puts " (from #{caller.first})"
|
36
|
+
subcommand(*args, &block)
|
37
|
+
self.default_subcommand = args.first
|
43
38
|
end
|
44
39
|
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def declare_subcommand(name, description, subcommand_class = self, &block)
|
49
|
-
if block
|
50
|
-
# generate a anonymous sub-class
|
51
|
-
subcommand_class = Class.new(subcommand_class, &block)
|
52
|
-
end
|
53
|
-
recognised_subcommands << Subcommand.new(name, description, subcommand_class)
|
54
|
-
end
|
55
40
|
|
56
41
|
end
|
57
42
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Clamp
|
2
|
+
class Subcommand
|
3
|
+
|
4
|
+
module Parsing
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def parse_subcommand
|
9
|
+
return false unless self.class.has_subcommands?
|
10
|
+
subcommand_name = parse_subcommand_name
|
11
|
+
@subcommand = instatiate_subcommand(subcommand_name)
|
12
|
+
@subcommand.parse(remaining_arguments)
|
13
|
+
remaining_arguments.clear
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def parse_subcommand_name
|
19
|
+
remaining_arguments.shift || self.class.default_subcommand || request_help
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_subcommand(name)
|
23
|
+
self.class.find_subcommand(name) ||
|
24
|
+
signal_usage_error("No such sub-command '#{name}'")
|
25
|
+
end
|
26
|
+
|
27
|
+
def instatiate_subcommand(name)
|
28
|
+
subcommand_class = find_subcommand(name).subcommand_class
|
29
|
+
subcommand = subcommand_class.new("#{invocation_path} #{name}", context)
|
30
|
+
self.class.recognised_options.each do |option|
|
31
|
+
option_set = instance_variable_defined?(option.ivar_name)
|
32
|
+
if option_set && subcommand.respond_to?(option.write_method)
|
33
|
+
subcommand.send(option.write_method, self.send(option.read_method))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
subcommand
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
data/lib/clamp/version.rb
CHANGED
@@ -33,40 +33,67 @@ describe Clamp::Command do
|
|
33
33
|
|
34
34
|
end
|
35
35
|
|
36
|
+
context "executed with no subcommand" do
|
37
|
+
|
38
|
+
it "triggers help" do
|
39
|
+
lambda do
|
40
|
+
@command.run([])
|
41
|
+
end.should raise_error(Clamp::HelpWanted)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#parse" do
|
47
|
+
|
48
|
+
describe "with too many arguments" do
|
49
|
+
|
50
|
+
it "raises a UsageError" do
|
51
|
+
lambda do
|
52
|
+
@command.parse(["flip", "extra", "args"])
|
53
|
+
end.should raise_error(Clamp::UsageError, "too many arguments")
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
36
60
|
describe "#help" do
|
37
|
-
|
61
|
+
|
62
|
+
it "shows subcommand parameters in usage" do
|
63
|
+
@command.help.should include("flipflop [OPTIONS] SUBCOMMAND [ARGS] ...")
|
64
|
+
end
|
65
|
+
|
38
66
|
it "lists subcommands" do
|
39
67
|
@help = @command.help
|
40
68
|
@help.should =~ /Subcommands:/
|
41
69
|
@help.should =~ /flip +flip it/
|
42
70
|
@help.should =~ /flop +flop it/
|
43
71
|
end
|
44
|
-
|
72
|
+
|
45
73
|
it "handles new lines in subcommand descriptions" do
|
46
|
-
@help
|
47
|
-
@help.should =~ /flop +flop it\n +for extra flop/
|
74
|
+
@command.help.should =~ /flop +flop it\n +for extra flop/
|
48
75
|
end
|
49
|
-
|
76
|
+
|
50
77
|
end
|
51
|
-
|
78
|
+
|
52
79
|
end
|
53
80
|
|
54
81
|
describe "with an aliased subcommand" do
|
55
|
-
|
82
|
+
|
56
83
|
given_command "blah" do
|
57
84
|
|
58
85
|
subcommand ["say", "talk"], "Say something" do
|
59
|
-
|
86
|
+
|
60
87
|
parameter "WORD ...", "stuff to say"
|
61
|
-
|
88
|
+
|
62
89
|
def execute
|
63
90
|
puts word_list
|
64
91
|
end
|
65
|
-
|
92
|
+
|
66
93
|
end
|
67
|
-
|
94
|
+
|
68
95
|
end
|
69
|
-
|
96
|
+
|
70
97
|
it "responds to both aliases" do
|
71
98
|
|
72
99
|
@command.run(["say", "boo"])
|
@@ -76,8 +103,8 @@ describe Clamp::Command do
|
|
76
103
|
stdout.should =~ /jive/
|
77
104
|
|
78
105
|
end
|
79
|
-
|
80
|
-
describe "#help" do
|
106
|
+
|
107
|
+
describe "#help" do
|
81
108
|
|
82
109
|
it "lists all aliases" do
|
83
110
|
@help = @command.help
|
@@ -85,9 +112,9 @@ describe Clamp::Command do
|
|
85
112
|
end
|
86
113
|
|
87
114
|
end
|
88
|
-
|
115
|
+
|
89
116
|
end
|
90
|
-
|
117
|
+
|
91
118
|
describe "with nested subcommands" do
|
92
119
|
|
93
120
|
given_command "fubar" do
|
@@ -110,9 +137,36 @@ describe Clamp::Command do
|
|
110
137
|
end
|
111
138
|
|
112
139
|
end
|
113
|
-
|
140
|
+
|
114
141
|
describe "with a default subcommand" do
|
115
|
-
|
142
|
+
|
143
|
+
given_command "admin" do
|
144
|
+
|
145
|
+
subcommand "status", "Show status" do
|
146
|
+
|
147
|
+
def execute
|
148
|
+
puts "All good!"
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
self.default_subcommand = "status"
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
context "executed with no subcommand" do
|
158
|
+
|
159
|
+
it "invokes the default subcommand" do
|
160
|
+
@command.run([])
|
161
|
+
stdout.should =~ /All good/
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "with a default subcommand, declared the old way" do
|
169
|
+
|
116
170
|
given_command "admin" do
|
117
171
|
|
118
172
|
default_subcommand "status", "Show status" do
|
@@ -125,13 +179,17 @@ describe Clamp::Command do
|
|
125
179
|
|
126
180
|
end
|
127
181
|
|
128
|
-
|
129
|
-
|
130
|
-
|
182
|
+
context "executed with no subcommand" do
|
183
|
+
|
184
|
+
it "invokes the default subcommand" do
|
185
|
+
@command.run([])
|
186
|
+
stdout.should =~ /All good/
|
187
|
+
end
|
188
|
+
|
131
189
|
end
|
132
|
-
|
190
|
+
|
133
191
|
end
|
134
|
-
|
192
|
+
|
135
193
|
describe "each subcommand" do
|
136
194
|
|
137
195
|
before do
|
@@ -146,7 +204,7 @@ describe Clamp::Command do
|
|
146
204
|
option "--direction", "DIR", "which way", :default => "home"
|
147
205
|
|
148
206
|
include speed_options
|
149
|
-
|
207
|
+
|
150
208
|
subcommand "move", "move in the appointed direction" do
|
151
209
|
|
152
210
|
def execute
|
metadata
CHANGED
@@ -1,30 +1,23 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: clamp
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.3
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Mike Williams
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2011-07-31 00:00:00 Z
|
12
|
+
date: 2011-10-30 00:00:00.000000000Z
|
14
13
|
dependencies: []
|
15
|
-
|
16
|
-
|
17
|
-
Clamp provides an object-model for command-line utilities.
|
18
|
-
It handles parsing of command-line options, and generation of usage help.
|
19
|
-
|
14
|
+
description: ! "Clamp provides an object-model for command-line utilities. \nIt handles
|
15
|
+
parsing of command-line options, and generation of usage help.\n"
|
20
16
|
email: mdub@dogbiscuit.org
|
21
17
|
executables: []
|
22
|
-
|
23
18
|
extensions: []
|
24
|
-
|
25
19
|
extra_rdoc_files: []
|
26
|
-
|
27
|
-
files:
|
20
|
+
files:
|
28
21
|
- .gitignore
|
29
22
|
- Gemfile
|
30
23
|
- README.markdown
|
@@ -48,7 +41,7 @@ files:
|
|
48
41
|
- lib/clamp/parameter/parsing.rb
|
49
42
|
- lib/clamp/subcommand.rb
|
50
43
|
- lib/clamp/subcommand/declaration.rb
|
51
|
-
- lib/clamp/subcommand/
|
44
|
+
- lib/clamp/subcommand/parsing.rb
|
52
45
|
- lib/clamp/version.rb
|
53
46
|
- spec/clamp/command_group_spec.rb
|
54
47
|
- spec/clamp/command_spec.rb
|
@@ -58,38 +51,35 @@ files:
|
|
58
51
|
- spec/spec_helper.rb
|
59
52
|
homepage: http://github.com/mdub/clamp
|
60
53
|
licenses: []
|
61
|
-
|
62
54
|
post_install_message:
|
63
55
|
rdoc_options: []
|
64
|
-
|
65
|
-
require_paths:
|
56
|
+
require_paths:
|
66
57
|
- lib
|
67
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
59
|
none: false
|
69
|
-
requirements:
|
70
|
-
- -
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
|
73
|
-
segments:
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
segments:
|
74
65
|
- 0
|
75
|
-
|
76
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
hash: 2140542804318955849
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
68
|
none: false
|
78
|
-
requirements:
|
79
|
-
- -
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
|
82
|
-
segments:
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
segments:
|
83
74
|
- 0
|
84
|
-
|
75
|
+
hash: 2140542804318955849
|
85
76
|
requirements: []
|
86
|
-
|
87
77
|
rubyforge_project:
|
88
|
-
rubygems_version: 1.
|
78
|
+
rubygems_version: 1.8.10
|
89
79
|
signing_key:
|
90
80
|
specification_version: 3
|
91
81
|
summary: a minimal framework for command-line utilities
|
92
|
-
test_files:
|
82
|
+
test_files:
|
93
83
|
- spec/clamp/command_group_spec.rb
|
94
84
|
- spec/clamp/command_spec.rb
|
95
85
|
- spec/clamp/option_module_spec.rb
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module Clamp
|
2
|
-
class Subcommand
|
3
|
-
|
4
|
-
module Execution
|
5
|
-
|
6
|
-
protected
|
7
|
-
|
8
|
-
def execute_subcommand
|
9
|
-
signal_usage_error "no subcommand specified" unless subcommand_name
|
10
|
-
subcommand_class = find_subcommand_class(subcommand_name)
|
11
|
-
subcommand = subcommand_class.new("#{invocation_path} #{subcommand_name}", context)
|
12
|
-
self.class.recognised_options.each do |option|
|
13
|
-
option_set = instance_variable_defined?(option.ivar_name)
|
14
|
-
if option_set && subcommand.respond_to?(option.write_method)
|
15
|
-
subcommand.send(option.write_method, self.send(option.read_method))
|
16
|
-
end
|
17
|
-
end
|
18
|
-
subcommand.run(subcommand_arguments)
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def find_subcommand(name)
|
24
|
-
self.class.find_subcommand(name) ||
|
25
|
-
signal_usage_error("No such sub-command '#{name}'")
|
26
|
-
end
|
27
|
-
|
28
|
-
def find_subcommand_class(name)
|
29
|
-
subcommand = find_subcommand(name)
|
30
|
-
subcommand.subcommand_class if subcommand
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|