choosy 0.1.0 → 0.2.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.
Files changed (45) hide show
  1. data/README.markdown +229 -221
  2. data/Rakefile +21 -3
  3. data/examples/bar.rb +44 -0
  4. data/examples/foo.rb +198 -0
  5. data/examples/superfoo.rb +125 -0
  6. data/lib/VERSION +1 -1
  7. data/lib/choosy/argument.rb +51 -0
  8. data/lib/choosy/base_command.rb +22 -7
  9. data/lib/choosy/command.rb +12 -4
  10. data/lib/choosy/dsl/argument_builder.rb +88 -0
  11. data/lib/choosy/dsl/base_command_builder.rb +71 -56
  12. data/lib/choosy/dsl/command_builder.rb +14 -2
  13. data/lib/choosy/dsl/option_builder.rb +43 -83
  14. data/lib/choosy/dsl/super_command_builder.rb +37 -9
  15. data/lib/choosy/option.rb +13 -11
  16. data/lib/choosy/parse_result.rb +8 -27
  17. data/lib/choosy/parser.rb +20 -16
  18. data/lib/choosy/printing/color.rb +39 -21
  19. data/lib/choosy/printing/erb_printer.rb +12 -3
  20. data/lib/choosy/printing/formatting_element.rb +17 -0
  21. data/lib/choosy/printing/help_printer.rb +204 -117
  22. data/lib/choosy/printing/terminal.rb +53 -0
  23. data/lib/choosy/super_command.rb +6 -6
  24. data/lib/choosy/super_parser.rb +26 -15
  25. data/lib/choosy/verifier.rb +61 -6
  26. data/spec/choosy/base_command_spec.rb +27 -2
  27. data/spec/choosy/command_spec.rb +31 -9
  28. data/spec/choosy/dsl/argument_builder_spec.rb +180 -0
  29. data/spec/choosy/dsl/base_command_builder_spec.rb +87 -44
  30. data/spec/choosy/dsl/commmand_builder_spec.rb +15 -4
  31. data/spec/choosy/dsl/option_builder_spec.rb +101 -191
  32. data/spec/choosy/dsl/super_command_builder_spec.rb +34 -9
  33. data/spec/choosy/parser_spec.rb +30 -8
  34. data/spec/choosy/printing/color_spec.rb +19 -5
  35. data/spec/choosy/printing/help_printer_spec.rb +152 -73
  36. data/spec/choosy/printing/terminal_spec.rb +27 -0
  37. data/spec/choosy/super_command_spec.rb +17 -17
  38. data/spec/choosy/super_parser_spec.rb +20 -10
  39. data/spec/choosy/verifier_spec.rb +137 -47
  40. data/spec/integration/command-A_spec.rb +6 -6
  41. data/spec/integration/command-B_spec.rb +45 -0
  42. data/spec/integration/supercommand-A_spec.rb +33 -27
  43. data/spec/integration/supercommand-B_spec.rb +32 -0
  44. data/spec/spec_helpers.rb +8 -5
  45. metadata +95 -54
@@ -19,154 +19,163 @@ This library should never:
19
19
 
20
20
  # Examples
21
21
 
22
- #!/usr/bin/env ruby
22
+ #!/usr/bin/env ruby -w
23
23
  # foo.rb
24
-
25
- require 'rubygems'
24
+
25
+ $LOAD_PATH.unshift File.join(File.dirname(File.dirname(__FILE__)), 'lib')
26
26
  require 'choosy'
27
-
28
- FOO_VERSION = 1.0.1
29
-
27
+
28
+ FOO_VERSION = '1.0.1'
29
+
30
30
  class FooExecutor
31
- def execute!(options, args)
31
+ def execute!(args, options)
32
32
  puts "BOLDED!!" if options[:bold]
33
33
  options[:count].times do
34
- puts "#{options[:prefix]}#{options[:words].push('foo').join(',')#{options[:suffix}}"
34
+ puts "#{options[:prefix]}#{options[:words].push('foo').join(',')}#{options[:suffix]}"
35
35
  end
36
36
  puts "and #{args.join ' '}"
37
37
  end
38
38
  end
39
-
39
+
40
40
  foo_cmd = Choosy::Command.new :foo do |foo|
41
41
  # Add a class to do the execution when you call foo_cmd.execute!
42
42
  # You can also use a proc that takes the options and the args, like:
43
- # foo.executor { |opts, args| puts 'Hi!' }
44
- foo.executor FooExecutor.new
45
-
43
+ # executor { |args, options| puts 'Hi!' }
44
+ executor FooExecutor.new
45
+
46
+ # When used as a subcommand, you need a summary for the help screen
47
+ summary "This is a nice command named 'foo'"
48
+
46
49
  # You can add your custom printer by giving the
47
50
  # full path to an ERB template file here.
48
51
  # The default printer is :standard, but you can
49
- # also use the builtin printer :compact. The
52
+ # also use the builtin printer :erb, with the :tempates
53
+ # parameter to set the erb template you wish to use. The
50
54
  # output can be colored or uncolored, though the
51
55
  # default is colored.
52
- foo.printer :standard, :colored => true
53
-
54
- foo.summary 'Prints out "foo" to the console"
55
- foo.desc <<HERE
56
- This is a long description about what 'foo' is
57
- and how it works. Don't worry your pretty little head
58
- about the details.
59
- HERE
60
-
61
- foo.separator 'Required Options:'
62
-
56
+ printer :standard, :color => true, :header_styles => [:bold, :green]
57
+
58
+ para 'Prints out "foo" to the console'
59
+ para 'This is a long description of what foo is an how it works. This line will assuredly wrap the console at least once, since it it such a long line, but it will be wrapped automatically by the printer, above. If you want to, you can add write "printer :standard, :max_width => 80" to set the maximum column width that the printer will allow (not respected by ERB templates).'
60
+
61
+ header 'Required Options:' # Formatted according to the header_styles for the printer
62
+
63
63
  # A shorthand for a common option type.
64
64
  # It adds the '-p/--prefix PREFIX' infomation for you.
65
- foo.single :prefix, "A prefix for 'foo'" do |p|
66
- p.default '<'
67
- p.required
65
+ single :prefix, "A prefix for 'foo'" do
66
+ default '<'
67
+ required
68
68
  end
69
-
69
+
70
70
  # The long way to do the same thing as above, except with
71
71
  # explicitly named dependencies
72
- foo.option :suffix => [:prefix] do |o|
73
- o.short '-s'
74
- o.long '--suffix', 'SUFFIX'
75
- o.desc 'A suffix for "foo"'
76
- o.required
77
-
78
- o.validate do |suffix|
79
- if suffix == foo[:prefix]
80
- o.fail "You can't matching prefixes and suffixes, you heathen!"
72
+ option :suffix => [:prefix] do
73
+ short '-s'
74
+ long '--suffix', 'SUFFIX'
75
+ desc 'A suffix for "foo"'
76
+ required
77
+
78
+ validate do |suffix, options|
79
+ if suffix == options[:prefix]
80
+ die "You can't matching prefixes and suffixes, you heathen!"
81
81
  end
82
82
  end
83
83
  end
84
-
84
+
85
85
  # Just like the 'single' method above, except now it automatically
86
86
  # requires/casts the argument to this flag into an integer. These commands
87
87
  # also take an optional hash as the last argument, which can be used instead
88
88
  # of a block.
89
- foo.integer :count, 'The number of times to repeat "foo"', :required => true
90
-
91
- foo.separator
92
- foo.separator 'Options:'
93
-
94
- foo.option :words do |o|
95
- o.short '-w'
96
- o.long '--words', 'WORDS+' # By default, the '+' at the end
89
+ integer :count, 'The number of times to repeat "foo"', :required => true
90
+
91
+ header 'Options:', :bold, :blue # Format this header differently, overrides 'header_styles'
92
+
93
+ option :words do
94
+ short '-w'
95
+ long '--words', 'WORDS+' # By default, the '+' at the end
97
96
  # means that this takes multiple
98
97
  # arguments. You put a '-' at
99
98
  # the end of the argument list
100
99
  # to stop parsing this option
101
100
  # and allow for regular args.
102
- o.desc "Other fun words to put in quotes"
103
- o.default [] # The default anyway on multple arg options
101
+ desc "Other fun words to put in quotes"
104
102
 
105
103
  # Sets the exact count of the number of arguments it accepts.
106
104
  # also allowable are the single selectors :zero and :one.
107
105
  # By default, the option 'WORDS+' sets the range to be
108
106
  # {:at_least => 1, :at_most => 1000 }
109
- o.count {:at_least => 2, :at_most => 10 }
110
-
111
- o.validate do |words|
107
+ count :at_least => 2, :at_most => 10
108
+
109
+ validate do |words, options|
112
110
  words.each do |word|
113
111
  if word !~ /\w+/
114
- o.fail "I can't print that: #{word}"
112
+ die "I can't print that: #{word}"
115
113
  end
116
114
  end
117
115
  end
118
116
  end
119
-
117
+
120
118
  # Alternatively, we could have done the following:
121
- foo.strings :words, "Other fun words to put in quotes" do |w|
122
- w.count {:at_least => 2, :at_most => 10 }
123
- w.validate do |words|
119
+ strings :words, "Other fun words to put in quotes" do
120
+ count 2..10
121
+ default []
122
+ validate do |words, options|
124
123
  words.each do |word|
125
124
  if word !~ /\w+/
126
- w.fail "I can't print that: #{word}"
125
+ die "I can't print that: #{word}"
127
126
  end
128
127
  end
129
128
  end
130
129
  end
131
-
130
+
132
131
  # Yet another shorthand notation for options, since they
133
- # are boolean by default
134
- foo.option :bold => {:long => '--bold', :default => false}
135
-
136
- options.separator
132
+ # are boolean by default. Here, we add a negation to the
133
+ # long flag of the option, creating [-b|--bold|--un-bold] flags.
134
+ # By default, calling 'negate' in a block without an argument
135
+ # uses the '--no-' prefix instead.
136
+ boolean :bold, "Bold this option", :default => false, :negate => 'un'
137
+
137
138
  # Tail options
138
-
139
+
139
140
  # When any of the simpler notations are suffixed with a '_'
140
141
  # character, the short option is always suppressed.
141
- foo.boolean_ :debug, "Prints out extra debugging output."
142
-
142
+ boolean_ :debug, "Prints out extra debugging output."
143
+
143
144
  # The '_' characters are replaced with '-' in flags, so the
144
- # following creates a '--no-color' flag.
145
- foo.boolean_ :no_color, "Turns off coloring in the output" do |o|
146
- o.validate do
147
- foo.printer :standard, :colored => false
145
+ # following creates a '--[no-]color' flag.
146
+ boolean_ :color, "Turns on/off coloring in the output. Defalt is on." do
147
+ negate
148
+ default true
149
+ validate do
150
+ foo.command.alter do
151
+ printer :standard, :colored => false
152
+ end
148
153
  end
149
154
  end
150
-
155
+
151
156
  # Adds the standard -h/--help option.
152
157
  # Should skip the '-h' flag if already set.
153
- foo.help
154
-
158
+ help # Automatically adds the description if not passed an argument. You can supply your own
159
+
155
160
  # Adds the --version option.
156
- foo.version "Foo: #{FOO_VERSION}"
157
-
161
+ version "Foo: #{FOO_VERSION}"
162
+
158
163
  # Now, add some validation for any addtional arguments
159
- # that are left over after the parsing.
160
- foo.arguments do |args|
161
- if args.empty?
162
- a.fail "You have to pass in empty arguments that do nothing!"
163
- end
164
- if args.count >= 3
165
- a.fail "Whoa there! You're going argument crazy!"
164
+ # that are left over after the parsing the options.
165
+ arguments do
166
+ metaname 'ARGS'
167
+ count 1..10
168
+ validate do |args, options|
169
+ if args.empty?
170
+ die "You have to pass in empty arguments that do nothing!"
171
+ end
172
+ if args.count == 10
173
+ die "Whoa there! You're going argument crazy!"
174
+ end
166
175
  end
167
176
  end
168
177
  end
169
-
178
+
170
179
  if __FILE__ == $0
171
180
  # Parses and validates the options.
172
181
  args = ['--prefix', '{',
@@ -175,7 +184,7 @@ This library should never:
175
184
  # The '-' stops parsing this option, so that:
176
185
  'handsom', 'devil',
177
186
  'http://not.posting.here', # will be regular arguments
178
- '-c, '3', # Count
187
+ '-c', '3', # Count
179
188
  '--', # Stops parsing all arguments
180
189
  '-h', '--help', '-v', '--version' # Ignored
181
190
  ]
@@ -184,16 +193,17 @@ This library should never:
184
193
  require 'pp'
185
194
  pp result[:prefix] # => '{'
186
195
  pp result[:suffix] # => '}'
187
- pp reuslt[:count] # => 3
196
+ pp result[:count] # => 3
188
197
  pp result[:bold] # => false
189
- pp reuslt[:words] # => ['high', 'there', 'you']
190
- pp reuslt.args # => ['handsom', 'devil',
198
+ pp result[:words] # => ['high', 'there', 'you']
199
+ pp result.args # => ['handsom', 'devil',
191
200
  # 'http://not.posting.here',
192
201
  # '-h', '--help', '-v', '--version']
193
202
  pp result.options # => {:prefix => '{', :suffix => '}'
194
203
  # :count => 3, :bold => false,
195
- # :words => ['high', 'there', 'you']}
196
-
204
+ # :words => ['high', 'there', 'you'],
205
+ # :debug => false, :color => true}
206
+
197
207
  # Now, call the command that does the actual work.
198
208
  # This passes the foo_cmd.options and the foo_cmd.args
199
209
  # as arguments to the executors 'execute!' method.
@@ -205,7 +215,7 @@ This library should never:
205
215
  # {high,there,you,foo}
206
216
  # {high,there,you,foo}
207
217
  # and handsom devil http://not.posting.here -h --help -v --verbose
208
-
218
+
209
219
  end
210
220
 
211
221
  ### Super Commands
@@ -214,180 +224,178 @@ You can also combine multiple choices into an uber-choice, creating
214
224
  commands that look a lot like git or subversion.
215
225
 
216
226
  First, we create another command.
217
-
218
- #!/usr/bin/env ruby
219
- # bar.rb
220
227
 
221
- require 'rubygems'
228
+ #!/usr/bin/env ruby -w
229
+ # bar.rb
230
+
231
+ $LOAD_PATH.unshift File.join(File.dirname(File.dirname(__FILE__)), 'lib')
222
232
  require 'choosy'
223
-
224
- class BarExecutor
225
- def execute!(options, args)
233
+
234
+ # Create a new command
235
+ bar_cmd = Choosy::Command.new :bar do
236
+ executor do |args, options|
226
237
  if options[:bold]
227
- puts "BOLDED BAR"
238
+ puts "BOLD!!!"
228
239
  else
229
- puts "bar"
240
+ puts "plain"
230
241
  end
231
242
  end
232
- end
233
243
 
234
- # Create a new command
235
- bar_cmd = Choosy::Command.new :bar do |bar|
236
- bar.executor BarExecutor.new
237
- bar.summary "Just prints 'bar'"
238
- bar.desc "A truly unremarkable command"
239
-
240
- bar.boolean :bold, "Bolds something"
241
-
244
+ summary "Displays when this is a subcommand"
245
+ para "Just prints 'bar'"
246
+ para "A truly unremarkable command"
247
+
248
+ header 'Option:'
249
+ boolean :bold, "Bolds something" do
250
+ negate 'un'
251
+ end
252
+
242
253
  # Because there is no bar.arguments call,
243
254
  # it is now an error if there are extra
244
255
  # command line arguments to this command.
245
256
  end
246
257
 
258
+ if __FILE__ == $0
259
+ args = ['--un-bold']
260
+
261
+ result = bar_cmd.parse!(args)
262
+
263
+ require 'pp'
264
+ pp result.options[:bold] # => false
265
+ pp result.args # => []
266
+
267
+ bar_cmd.execute!(args) # => 'plain'
268
+
269
+ args << 'should-throw-error'
270
+ bar_cmd.execute!(args)
271
+ end
272
+
247
273
  We can now create our super command.
248
274
 
249
- #!/usr/bin/env ruby
275
+ #!/usr/bin/env ruby -w
250
276
  # superfoo.rb
251
-
252
- require 'rubygems'
277
+
278
+ $LOAD_PATH.unshift File.join(File.dirname(File.dirname(__FILE__)), 'lib')
279
+ $LOAD_PATH.unshift File.join(File.dirname(File.dirname(__FILE__)), 'examples')
253
280
  require 'choosy'
254
- require 'foo.rb'
255
- require 'bar.rb'
281
+ require "foo"
282
+ require "bar"
256
283
 
257
284
  SUPERFOO_VERSION = "1.0.1"
258
285
 
259
- superfoo = Choosy::SuperCommand.new :superfoo do |superfoo|
260
- superfoo.summary "This is a superfoo command."
261
- superfoo.desc "Say something, dammit!"
262
-
286
+ superfoo = Choosy::SuperCommand.new :superfoo do
287
+ summary "This is a superfoo command"
288
+ para "Say something, dammit!"
289
+
263
290
  # You can also add commands after instantiation.
264
291
  # Note that, when added, these commands have their
265
292
  # -h/--help/--version flags suppressed, so you'll
266
293
  # need to add those flags here.
267
- superfoo.commands bar_cmd
268
-
269
- # Creates a 'help' command
270
- superfoo.help do |help|
271
- help.summary "Prints this help message"
272
- end
273
-
274
- # Create some global options that are parsed
275
- # defore subcommand options
294
+ command bar_cmd
295
+ command foo_cmd
276
296
 
277
- superfoo.option :config do |o|
278
- o.long '--config', 'FILE'
279
- o.desc "Configure your superfoo with a configuration file."
297
+ # Creates a 'help' command, message optional
298
+ help "Prints this help message"
280
299
 
281
- o.validate do |config|
282
- if !File.exist? config
283
- o.fail "Unable to find configuration file!"
284
- end
285
- end
300
+ # Create some global options that are parsed
301
+ # defore result options
302
+
303
+ # Here, check that a YAML file exists, and attempt
304
+ # to load it's parsed contents into this option.
305
+ # There is also a 'file' type that checks to see
306
+ # if the file exists. With both 'file' and 'yaml',
307
+ # if the file is missing, the option fails with an
308
+ # error.
309
+ yaml :Config, "Configure your superfoo with a YAML configuration file." do
310
+ default File.join(ENV['HOME'], '.superfoo.yml')
286
311
  end
287
312
 
288
313
  # Adds a global --version flag.
289
- superfoo.version do
290
- puts "#{SUPERFOO_VERSION}"
291
- end
314
+ version "#{SUPERFOO_VERSION}"
292
315
  end
293
316
 
294
- # Add a command after the fact.
295
- superfoo.commands foo_cmd
296
-
297
317
  if __FILE__ == $0
298
- superfoo.parse! ['-c', '5',
299
- 'foo',
300
- '--config', '~/.superfoo',
301
- '--prefix', '{',
302
- '--suffix', '}',
303
- 'cruft',
304
- 'bar',
305
- '--bold']
306
-
318
+ args = ['foo',
319
+ '-c', '5',
320
+ '--config', '~/.superfoo',
321
+ '--prefix', '{',
322
+ '--suffix', '}',
323
+ 'cruft',
324
+ 'bar',
325
+ '--bold']
326
+
327
+ result = superfoo.parse!(args)
328
+
307
329
  require 'pp'
308
- pp superfoo[:config] # => '~/.superfoo'
309
- pp superfoo.subcommand.name # => :foo
310
- pp superfoo.subcommand[:prefix] # => '{'
311
- pp superfoo.subcommand[:suffix] # => '}'
312
- pp superfoo.subcommand[:count] # => 2
313
- pp superfoo.subcommand[:bold] # => true
314
- pp superfoo.subcommand.options # => {:prefix => '{', :suffix => '}'
315
- # :count => 2,
316
- # :bold => true,
317
- # :words => [],
318
- # :config => '~/.superfoo' }
319
- pp superfoo.subcommand.args # => ['cruft', 'bar']
330
+ pp result[:config] # => '~/.superfoo'
331
+ pp result.name # => :foo
332
+ pp result[:prefix] # => '{'
333
+ pp result[:suffix] # => '}'
334
+ pp result[:count] # => 2
335
+ pp result[:bold] # => true
336
+ pp result.options # => {:prefix => '{', :suffix => '}'
337
+ # :count => 2,
338
+ # :bold => true,
339
+ # :words => [],
340
+ # :config => '~/.superfoo' }
341
+ pp result.args # => ['cruft', 'bar']
342
+
343
+ # Now, we can call the result
344
+ superfoo.execute!(args) ## Calls superfoo.result.execute!
345
+ ## Prints:
346
+ # BOLDED!!
347
+ # {foo}
348
+ # {foo}
349
+ # and cruft bar
320
350
 
321
- pp superfoo.options # => {:prefix => '{', :suffix => '}'
322
- # :count => 2,
323
- # :bold => true,
324
- # :words => [],
325
- # :config => '~/.superfoo' }
326
- pp superfoo.args # => ['cruft', 'bar']
327
-
328
- # Now, we can call the subcommand
329
- superfoo.execute! ## Calls superfoo.subcommand.execute!
330
- ## Prints:
331
- # BOLDED!!
332
- # {foo}
333
- # {foo}
334
- # and cruft bar
335
-
336
- # We got what we wanted, so reset the parser.
337
- superfoo.reset!
338
-
339
351
  # Instead of parsing the 'bar' parameter as an argument to
340
352
  # the foo command, so that when the first argument that matches
341
353
  # another command name is encountered, it stops parsing the
342
354
  # current command and passes the rest of the arguments to the
343
355
  # next command.
344
356
  #
345
- # You can also set this inside a SuperChoosy.new {|s| ... }
357
+ # In this case, we call the 'alter' method to use the DSL
358
+ # syntax again to alter this command.
359
+ #
360
+ # You can also set this inside a SuperChoosy.new {...}
346
361
  # block.
347
- superfoo.parsimonious
348
-
349
- superfoo.parse! ['-c', '5',
350
- 'foo',
351
- '--config', '~/.superfoo',
352
- '--prefix', '{',
353
- '--suffix', '}',
354
- 'cruft',
355
- 'bar',
356
- '--bold']
362
+ superfoo.alter do
363
+ parsimonious
364
+ end
365
+
366
+ result = superfoo.parse!(args)
357
367
 
358
- pp superfoo[:config] # => '~/.superfoo'
359
- pp superfoo.subcommand.name # => :foo
360
- pp superfoo.subcommands[0].name # => :foo
361
- pp superfoo.subcommands[0][:prefix] # => '{'
362
- pp superfoo.subcommands[0][:suffix] # => '}'
363
- pp superfoo.subcommands[0][:count] # => 2
364
- pp superfoo.subcommands[0][:bold] # => true
365
- pp superfoo.subcommands[0].options # => {:prefix => '{', :suffix => '}'
366
- # :count => 2,
367
- # :bold => false,
368
- # :words => [],
369
- # :config => '~/.superfoo' }
370
- pp superfoo.subcommands[0].args # => ['cruft']
371
-
372
- pp superfoo.subcommands[1].name # => :bar
373
- pp superfoo.subcommands[1][:bold] # => true
374
- pp superfoo.subcommands[1].options # => {:bold => true,
375
- # :config => '~/.superfoo'}
376
- pp superfoo.subcommands[1].args # => []
368
+ pp result.name # => :superfoo
369
+ pp result[:config] # => '~/.superfoo'
370
+ pp result.subresults[0].name # => :foo
371
+ pp result.subresults[0][:prefix] # => '{'
372
+ pp result.subresults[0][:suffix] # => '}'
373
+ pp result.subresults[0][:count] # => 2
374
+ pp result.subresults[0][:bold] # => true
375
+ pp result.subresults[0].options # => {:prefix => '{', :suffix => '}'
376
+ # :count => 2,
377
+ # :bold => false,
378
+ # :words => [],
379
+ # :config => '~/.superfoo' }
380
+ pp result.subresults[0].args # => ['cruft']
381
+
382
+ pp result.subresults[1].name # => :bar
383
+ pp result.subresults[1][:bold] # => true
384
+ pp result.subresults[1].options # => {:bold => true,
385
+ # :config => '~/.superfoo'}
386
+ pp result.subresults[1].args # => []
377
387
 
378
- pp superfoo.options # => {:config => '~/.superfoo'}
379
- pp superfoo.args # => []
380
-
381
- # Now, execute the subcommands in order
382
- superfoo.execute! ## Same as:
383
- # superfoo.subcommands.each do |subcommand|
384
- # command.execute!
385
- # end
386
- ## Prints:
387
- # {foo}
388
- # {foo}
389
- # and cruft
390
- # BOLDED BAR
388
+ # Now, execute the results in order
389
+ superfoo.execute!(args) ## Same as:
390
+ # results.each do |subcommand|
391
+ # command.execute!
392
+ # end
393
+ ## Prints:
394
+ # {foo}
395
+ # {foo}
396
+ # and cruft
397
+ # BOLDED BAR
391
398
  end
399
+
392
400
 
393
401
  ### TODO: Output Printing