qualitysmith_extensions 0.0.3
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 +72 -0
- data/lib/qualitysmith_extensions/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +42 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +48 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +112 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +64 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +34 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +39 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +94 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.rb +940 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +38 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +29 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +120 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +72 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +32 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +108 -0
- data/lib/qualitysmith_extensions/filter_output.rb +107 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +151 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +32 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +119 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +69 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +113 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +34 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +118 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +16 -0
- data/lib/qualitysmith_extensions/month.rb +62 -0
- data/lib/qualitysmith_extensions/object/singleton.rb +95 -0
- data/lib/qualitysmith_extensions/simulate_input.rb +51 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +25 -0
- data/lib/qualitysmith_extensions/string/md5.rb +27 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +41 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +35 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +64 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +63 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +34 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +34 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +29 -0
- data/test/all.rb +16 -0
- metadata +94 -0
@@ -0,0 +1,749 @@
|
|
1
|
+
# = command.rb
|
2
|
+
#
|
3
|
+
# == Copyright (c) 2005 Thomas Sawyer
|
4
|
+
#
|
5
|
+
# Ruby License
|
6
|
+
#
|
7
|
+
# This module is free software. You may use, modify, and/or
|
8
|
+
# redistribute this software under the same terms as Ruby.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be
|
11
|
+
# useful, but WITHOUT ANY WARRANTY; without even the implied
|
12
|
+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
13
|
+
# PURPOSE.
|
14
|
+
#
|
15
|
+
# == Author(s)
|
16
|
+
#
|
17
|
+
# CREDIT Thomas Sawyer
|
18
|
+
# CREDIT Tyler Rick
|
19
|
+
#
|
20
|
+
# == Developer Notes
|
21
|
+
#
|
22
|
+
# TODO Add help/documentation features.
|
23
|
+
#
|
24
|
+
# TODO Move to console/command.rb, but I'm not sure yet if
|
25
|
+
# adding subdirectories to more/ is a good idea.
|
26
|
+
#
|
27
|
+
|
28
|
+
# Author:: Thomas Sawyer, Tyler Rick
|
29
|
+
# Copyright:: Copyright (c) 2005-2007
|
30
|
+
# License:: Ruby License
|
31
|
+
|
32
|
+
require 'shellwords'
|
33
|
+
|
34
|
+
# = Console
|
35
|
+
#
|
36
|
+
# Console namespace for use by tools specifically designed
|
37
|
+
# for command line interfaces.
|
38
|
+
|
39
|
+
module Console ; end
|
40
|
+
|
41
|
+
# = Console Command
|
42
|
+
#
|
43
|
+
# Console::Command provides a clean and easy way
|
44
|
+
# to create a command line interface for your program.
|
45
|
+
# The unique technique utlizes a Commandline to Object
|
46
|
+
# Mapping (COM) to make it quick and easy.
|
47
|
+
#
|
48
|
+
# == Synopsis
|
49
|
+
#
|
50
|
+
# Let's make an executable called 'mycmd'.
|
51
|
+
#
|
52
|
+
# #!/usr/bin/env ruby
|
53
|
+
#
|
54
|
+
# require 'facets'
|
55
|
+
# require 'command'
|
56
|
+
#
|
57
|
+
# MyCmd << Console::Command
|
58
|
+
#
|
59
|
+
# def _v
|
60
|
+
# $VERBOSE = true
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# def jump
|
64
|
+
# if $VERBOSE
|
65
|
+
# puts "JUMP! JUMP! JUMP!"
|
66
|
+
# else
|
67
|
+
# puts "Jump"
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# MyCmd.execute
|
74
|
+
#
|
75
|
+
# Then on the command line:
|
76
|
+
#
|
77
|
+
# % mycmd jump
|
78
|
+
# Jump
|
79
|
+
#
|
80
|
+
# % mycmd -v jump
|
81
|
+
# JUMP! JUMP! JUMP!
|
82
|
+
#
|
83
|
+
# == Subcommands
|
84
|
+
#
|
85
|
+
# Commands can take subcommand and suboptions. To do this
|
86
|
+
# simply add a module to your class with the same name
|
87
|
+
# as the subcommand, in which the suboption methods are defined.
|
88
|
+
#
|
89
|
+
# MyCmd << Console::Command
|
90
|
+
#
|
91
|
+
# def initialize
|
92
|
+
# @height = 1
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# def _v
|
96
|
+
# $VERBOSE = true
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# def jump
|
100
|
+
# if $VERBOSE
|
101
|
+
# puts "JUMP!" * @height
|
102
|
+
# else
|
103
|
+
# puts "Jump" * @height
|
104
|
+
# end
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# module Jump
|
108
|
+
# def __height(h)
|
109
|
+
# @height = h.to_i
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# MyCmd.start
|
116
|
+
#
|
117
|
+
# Then on the command line:
|
118
|
+
#
|
119
|
+
# % mycmd jump -h 2
|
120
|
+
# Jump Jump
|
121
|
+
#
|
122
|
+
# % mycmd -v jump -h 3
|
123
|
+
# JUMP! JUMP! JUMP!
|
124
|
+
#
|
125
|
+
# Another thing to notice about this example is that #start is an alias
|
126
|
+
# for #execute.
|
127
|
+
#
|
128
|
+
# == Missing Subcommands
|
129
|
+
#
|
130
|
+
# You can use #method_missing to catch missing subcommand calls.
|
131
|
+
#
|
132
|
+
# == Main and Default
|
133
|
+
#
|
134
|
+
# If your command does not take subcommands then simply define
|
135
|
+
# a #main method to dispatch action. All options will be treated globablly
|
136
|
+
# in this case and any remaining comman-line arguments will be passed
|
137
|
+
# to #main.
|
138
|
+
#
|
139
|
+
# If on the other hand your command does take subcommands but none is given,
|
140
|
+
# the #default method will be called, if defined. If not defined
|
141
|
+
# an error will be raised (but only reported if $DEBUG is true).
|
142
|
+
#
|
143
|
+
# == Global Options
|
144
|
+
#
|
145
|
+
# You can define <i>global options</i> which are options that will be
|
146
|
+
# processed no matter where they occur in the command line. In the above
|
147
|
+
# examples only the options occuring before the subcommand are processed
|
148
|
+
# globally. Anything occuring after the subcommand belonds strictly to
|
149
|
+
# the subcommand. For instance, if we had added the following to the above
|
150
|
+
# example:
|
151
|
+
#
|
152
|
+
# global_option :_v
|
153
|
+
#
|
154
|
+
# Then -v could appear anywhere in the command line, even on the end,
|
155
|
+
# and still work as expected.
|
156
|
+
#
|
157
|
+
# % mycmd jump -h 3 -v
|
158
|
+
#
|
159
|
+
# == Missing Options
|
160
|
+
#
|
161
|
+
# You can use #option_missing to catch any options that are not explicility
|
162
|
+
# defined.
|
163
|
+
#
|
164
|
+
# The method signature should look like:
|
165
|
+
#
|
166
|
+
# option_missing(option_name, args)
|
167
|
+
#
|
168
|
+
# Example:
|
169
|
+
# def option_missing(option_name, args)
|
170
|
+
# p args if $debug
|
171
|
+
# case option_name
|
172
|
+
# when 'p'
|
173
|
+
# @a = args[0].to_i
|
174
|
+
# @b = args[1].to_i
|
175
|
+
# 2
|
176
|
+
# else
|
177
|
+
# raise InvalidOptionError(option_name, args)
|
178
|
+
# end
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
# Its return value should be the effective "arity" of that options -- that is,
|
182
|
+
# how many arguments it consumed ("-p a b", for example, would consume 2 args:
|
183
|
+
# "a" and "b"). An arity of 1 is assumed if nil or false is returned.
|
184
|
+
#
|
185
|
+
# Be aware that when using subcommand modules, the same option_missing
|
186
|
+
# method will catch missing options for global options and subcommand
|
187
|
+
# options too unless an option_missing method is also defined in the
|
188
|
+
# subcommand module.
|
189
|
+
#
|
190
|
+
#--
|
191
|
+
#
|
192
|
+
# == Help Documentation
|
193
|
+
#
|
194
|
+
# You can also add help information quite easily. If the following code
|
195
|
+
# is saved as 'foo' for instance.
|
196
|
+
#
|
197
|
+
# MyCmd << Console::Command
|
198
|
+
#
|
199
|
+
# help "Dispays the word JUMP!"
|
200
|
+
#
|
201
|
+
# def jump
|
202
|
+
# if $VERBOSE
|
203
|
+
# puts "JUMP! JUMP! JUMP!"
|
204
|
+
# else
|
205
|
+
# puts "Jump"
|
206
|
+
# end
|
207
|
+
# end
|
208
|
+
#
|
209
|
+
# end
|
210
|
+
#
|
211
|
+
# MyCmd.execute
|
212
|
+
#
|
213
|
+
# then by running 'foo help' on the command line, standard help information
|
214
|
+
# will be displayed.
|
215
|
+
#
|
216
|
+
# foo
|
217
|
+
#
|
218
|
+
# jump Displays the word JUMP!
|
219
|
+
#
|
220
|
+
#++
|
221
|
+
|
222
|
+
class Console::Command
|
223
|
+
|
224
|
+
class << self
|
225
|
+
# Starts the command execution.
|
226
|
+
|
227
|
+
def execute( *args )
|
228
|
+
new(global_options).execute( *args )
|
229
|
+
end
|
230
|
+
|
231
|
+
# Alias for #execute.
|
232
|
+
|
233
|
+
alias_method :start, :execute
|
234
|
+
|
235
|
+
# Change the option mode.
|
236
|
+
|
237
|
+
def global_option( *names )
|
238
|
+
names.each{ |name| global_options << name.to_sym }
|
239
|
+
end
|
240
|
+
|
241
|
+
def global_options
|
242
|
+
@global_options ||= []
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Do not let this pass through to
|
247
|
+
# any included module.
|
248
|
+
|
249
|
+
def initialize(global_options)
|
250
|
+
@global_options = global_options
|
251
|
+
end
|
252
|
+
|
253
|
+
# Execute the command.
|
254
|
+
|
255
|
+
def execute( line=nil )
|
256
|
+
case line
|
257
|
+
when String
|
258
|
+
arguments = Shellwords.shellwords(line)
|
259
|
+
when Array
|
260
|
+
arguments = line
|
261
|
+
else
|
262
|
+
arguments = ARGV
|
263
|
+
end
|
264
|
+
|
265
|
+
# duplicate arguments to work on them in-place.
|
266
|
+
|
267
|
+
argv = arguments.dup
|
268
|
+
|
269
|
+
# Split single letter option groupings into separate options.
|
270
|
+
# ie. -xyz => -x -y -z
|
271
|
+
|
272
|
+
argv = argv.collect { |arg|
|
273
|
+
if md = /^-(\w{2,})/.match( arg )
|
274
|
+
md[1].split(//).collect { |c| "-#{c}" }
|
275
|
+
else
|
276
|
+
arg
|
277
|
+
end
|
278
|
+
}.flatten
|
279
|
+
|
280
|
+
# process global options
|
281
|
+
global_options.each do |name|
|
282
|
+
o = name.to_s.sub('__','--').sub('_','-')
|
283
|
+
m = method(name)
|
284
|
+
c = m.arity
|
285
|
+
while i = argv.index(o)
|
286
|
+
args = argv.slice!(i,c+1)
|
287
|
+
args.shift
|
288
|
+
m.call(*args)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# Does this command take subcommands?
|
293
|
+
subcommand = !respond_to?(:main)
|
294
|
+
|
295
|
+
# process primary options
|
296
|
+
argv = execute_options( argv, subcommand )
|
297
|
+
|
298
|
+
# If this command doesn't take subcommands, then the remaining arguments are arguments for main().
|
299
|
+
return send(:main, *argv) unless subcommand
|
300
|
+
|
301
|
+
# What to do if there is nothing else?
|
302
|
+
if argv.empty?
|
303
|
+
if respond_to?(:default)
|
304
|
+
return __send__(:default)
|
305
|
+
else
|
306
|
+
$stderr << "Nothing to do."
|
307
|
+
return
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# Remaining arguments are subcommand and suboptions.
|
312
|
+
|
313
|
+
subcmd = argv.shift.gsub('-','_')
|
314
|
+
#puts "subcmd = #{subcmd}"
|
315
|
+
|
316
|
+
# Extend subcommand option module
|
317
|
+
subconst = subcmd.gsub(/\W/,'_').capitalize
|
318
|
+
#puts self.class.name
|
319
|
+
if self.class.const_defined?(subconst)
|
320
|
+
puts "Extending self (#{self.class}) with subcommand module #{subconst}" if $debug
|
321
|
+
submod = self.class.const_get(subconst)
|
322
|
+
self.extend submod
|
323
|
+
end
|
324
|
+
|
325
|
+
# process subcommand options
|
326
|
+
#puts "Treating the rest of the args as subcommand options:"
|
327
|
+
#p argv
|
328
|
+
argv = execute_options( argv )
|
329
|
+
|
330
|
+
# This is a little tricky. The method has to be defined by a subclass.
|
331
|
+
if self.respond_to?( subcmd ) and not Console::Command.public_instance_methods.include?( subcmd.to_s )
|
332
|
+
puts "Calling #{subcmd}(#{argv.inspect})" if $debug
|
333
|
+
__send__(subcmd, *argv)
|
334
|
+
else
|
335
|
+
#begin
|
336
|
+
puts "Calling method_missing with #{subcmd}, #{argv.inspect}" if $debug
|
337
|
+
method_missing(subcmd, *argv)
|
338
|
+
#rescue NoMethodError => e
|
339
|
+
#if self.private_methods.include?( "no_command_error" )
|
340
|
+
# no_command_error( *args )
|
341
|
+
#else
|
342
|
+
# $stderr << "Non-applicable command -- #{argv.join(' ')}\n"
|
343
|
+
# exit -1
|
344
|
+
#end
|
345
|
+
#end
|
346
|
+
end
|
347
|
+
|
348
|
+
# rescue => err
|
349
|
+
# if $DEBUG
|
350
|
+
# raise err
|
351
|
+
# else
|
352
|
+
# msg = err.message.chomp('.') + '.'
|
353
|
+
# msg[0,1] = msg[0,1].capitalize
|
354
|
+
# msg << " (#{err.class})" if $VERBOSE
|
355
|
+
# $stderr << msg
|
356
|
+
# end
|
357
|
+
end
|
358
|
+
|
359
|
+
private
|
360
|
+
|
361
|
+
#
|
362
|
+
|
363
|
+
def global_options
|
364
|
+
@global_options
|
365
|
+
end
|
366
|
+
|
367
|
+
#
|
368
|
+
|
369
|
+
def execute_options( argv, subcmd=false )
|
370
|
+
puts "in execute_options:" if $debug
|
371
|
+
argv = argv.dup
|
372
|
+
args_to_return = []
|
373
|
+
until argv.empty?
|
374
|
+
arg = argv.first
|
375
|
+
if arg[0,1] == '-'
|
376
|
+
puts "'#{arg}' -- is an option" if $debug
|
377
|
+
|
378
|
+
name = arg.gsub('-','_')
|
379
|
+
puts " responds_to(#{name})?" if $debug
|
380
|
+
if respond_to?(name)
|
381
|
+
m = method(name)
|
382
|
+
arity = m.arity
|
383
|
+
#puts "{argv before slice: #{argv.inspect}" if $debug
|
384
|
+
args_for_current_option = argv.slice!(0, arity+1)
|
385
|
+
#puts "}argv after slice: #{argv.inspect}" if $debug
|
386
|
+
#puts "{args_for_current_option before shift: #{args_for_current_option.inspect}" if $debug
|
387
|
+
args_for_current_option.shift
|
388
|
+
#puts "}args_for_current_option after shift: #{args_for_current_option.inspect}" if $debug
|
389
|
+
#puts " arity=#{m.arity}" if $debug
|
390
|
+
#puts " calling #{name} with #{args_for_current_option.inspect}" if $debug
|
391
|
+
m.call(*args_for_current_option)
|
392
|
+
elsif respond_to?(:option_missing)
|
393
|
+
puts " option_missing(#{argv.inspect})" if $debug
|
394
|
+
arity = option_missing(arg.gsub(/^[-]+/,''), argv[1..-1]) || 1
|
395
|
+
puts " arity == #{arity}" if $debug
|
396
|
+
argv.slice!(0, arity)
|
397
|
+
argv.shift # Get rid of the *name* of the option
|
398
|
+
else
|
399
|
+
$stderr << "Unknown option '#{arg}'.\n"
|
400
|
+
exit -1
|
401
|
+
end
|
402
|
+
else
|
403
|
+
puts "'#{arg}' -- not an option. Adding to args_to_return..." if $debug
|
404
|
+
if subcmd
|
405
|
+
args_to_return = argv
|
406
|
+
#puts "subcommand. args_to_return=#{args_to_return.inspect}" if $debug
|
407
|
+
break
|
408
|
+
else
|
409
|
+
args_to_return << argv.shift
|
410
|
+
puts "args_to_return=#{args_to_return.inspect}" if $debug
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
puts "Returning #{args_to_return.inspect}" if $debug
|
415
|
+
return args_to_return
|
416
|
+
end
|
417
|
+
|
418
|
+
public
|
419
|
+
|
420
|
+
=begin
|
421
|
+
# We include a module here so you can define your own help
|
422
|
+
# command and call #super to utilize this one.
|
423
|
+
|
424
|
+
module Help
|
425
|
+
|
426
|
+
def help
|
427
|
+
opts = help_options
|
428
|
+
s = ""
|
429
|
+
s << "#{File.basename($0)}\n\n"
|
430
|
+
unless opts.empty?
|
431
|
+
s << "OPTIONS\n"
|
432
|
+
s << help_options
|
433
|
+
s << "\n"
|
434
|
+
end
|
435
|
+
s << "COMMANDS\n"
|
436
|
+
s << help_commands
|
437
|
+
puts s
|
438
|
+
end
|
439
|
+
|
440
|
+
private
|
441
|
+
|
442
|
+
def help_commands
|
443
|
+
help = self.class.help
|
444
|
+
bufs = help.keys.collect{ |a| a.to_s.size }.max + 3
|
445
|
+
lines = []
|
446
|
+
help.each { |cmd, str|
|
447
|
+
cmd = cmd.to_s
|
448
|
+
if cmd !~ /^_/
|
449
|
+
lines << " " + cmd + (" " * (bufs - cmd.size)) + str
|
450
|
+
end
|
451
|
+
}
|
452
|
+
lines.join("\n")
|
453
|
+
end
|
454
|
+
|
455
|
+
def help_options
|
456
|
+
help = self.class.help
|
457
|
+
bufs = help.keys.collect{ |a| a.to_s.size }.max + 3
|
458
|
+
lines = []
|
459
|
+
help.each { |cmd, str|
|
460
|
+
cmd = cmd.to_s
|
461
|
+
if cmd =~ /^_/
|
462
|
+
lines << " " + cmd.gsub(/_/,'-') + (" " * (bufs - cmd.size)) + str
|
463
|
+
end
|
464
|
+
}
|
465
|
+
lines.join("\n")
|
466
|
+
end
|
467
|
+
|
468
|
+
module ClassMethods
|
469
|
+
|
470
|
+
def help( str=nil )
|
471
|
+
return (@help ||= {}) unless str
|
472
|
+
@current_help = str
|
473
|
+
end
|
474
|
+
|
475
|
+
def method_added( meth )
|
476
|
+
if @current_help
|
477
|
+
@help ||= {}
|
478
|
+
@help[meth] = @current_help
|
479
|
+
@current_help = nil
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
|
485
|
+
end
|
486
|
+
|
487
|
+
include Help
|
488
|
+
extend Help::ClassMethods
|
489
|
+
=end
|
490
|
+
|
491
|
+
end
|
492
|
+
|
493
|
+
|
494
|
+
|
495
|
+
# _____ _
|
496
|
+
# |_ _|__ ___| |_
|
497
|
+
# | |/ _ \/ __| __|
|
498
|
+
# | | __/\__ \ |_
|
499
|
+
# |_|\___||___/\__|
|
500
|
+
#
|
501
|
+
|
502
|
+
=begin test
|
503
|
+
|
504
|
+
require 'test/unit'
|
505
|
+
require 'stringio'
|
506
|
+
|
507
|
+
class TestCommand < Test::Unit::TestCase
|
508
|
+
def setup
|
509
|
+
$output = nil
|
510
|
+
$stderr = StringIO.new
|
511
|
+
end
|
512
|
+
|
513
|
+
#
|
514
|
+
|
515
|
+
class SimpleCommand < Console::Command
|
516
|
+
def __here ; @here = true ; end
|
517
|
+
|
518
|
+
def main(*args)
|
519
|
+
$output = [@here] | args
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
def test_SimpleCommand
|
524
|
+
SimpleCommand.execute( '--here file1 file2' )
|
525
|
+
assert_equal( [true, 'file1', 'file2'], $output )
|
526
|
+
end
|
527
|
+
|
528
|
+
#
|
529
|
+
|
530
|
+
class CommandWithMethodMissingSubcommand < Console::Command
|
531
|
+
def __here ; @here = true ; end
|
532
|
+
|
533
|
+
def method_missing(subcommand, *args)
|
534
|
+
$output = [@here, subcommand] | args
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
def test_CommandWithMethodMissingSubcommand
|
539
|
+
CommandWithMethodMissingSubcommand.execute( '--here go file1' )
|
540
|
+
assert_equal( [true, 'go', 'file1'], $output )
|
541
|
+
end
|
542
|
+
|
543
|
+
#
|
544
|
+
|
545
|
+
class CommandWithSimpleSubcommand < Console::Command
|
546
|
+
def __here ; @here = true ; end
|
547
|
+
|
548
|
+
# subcommand
|
549
|
+
|
550
|
+
module Go
|
551
|
+
def _p(n)
|
552
|
+
@p = n.to_i
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
def go ; $output = [@here, @p] ; end
|
557
|
+
end
|
558
|
+
|
559
|
+
def test_CommandWithSimpleSubcommand
|
560
|
+
CommandWithSimpleSubcommand.execute( '--here go -p 1' )
|
561
|
+
assert_equal( [true, 1], $output )
|
562
|
+
end
|
563
|
+
|
564
|
+
#
|
565
|
+
|
566
|
+
# Global options can be anywhere, right? Even after subcommands? Let's find out.
|
567
|
+
class CommandWithGlobalOptionsAfterSubcommand < Console::Command
|
568
|
+
def _x ; @x = true ; end
|
569
|
+
global_option :_x
|
570
|
+
|
571
|
+
def go ; $output = [@x, @p] ; end
|
572
|
+
|
573
|
+
module Go
|
574
|
+
def _p(n)
|
575
|
+
@p = n.to_i
|
576
|
+
end
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
def test_CommandWithGlobalOptionsAfterSubcommand
|
581
|
+
CommandWithGlobalOptionsAfterSubcommand.execute( 'go -x -p 1' )
|
582
|
+
assert_equal( [true, 1], $output )
|
583
|
+
|
584
|
+
CommandWithGlobalOptionsAfterSubcommand.execute( 'go -p 1 -x' )
|
585
|
+
assert_equal( [true, 1], $output )
|
586
|
+
end
|
587
|
+
|
588
|
+
#
|
589
|
+
|
590
|
+
class GivingUnrecognizedOptions < Console::Command
|
591
|
+
def _x ; @x = true ; end
|
592
|
+
def go ; $output = [@x, @p] ; end
|
593
|
+
end
|
594
|
+
|
595
|
+
def test_GivingUnrecognizedOptions
|
596
|
+
assert_raise(SystemExit) do
|
597
|
+
GivingUnrecognizedOptions.execute( '--an-option-that-wont-be-recognized -x go' )
|
598
|
+
end
|
599
|
+
assert_equal "Unknown option '--an-option-that-wont-be-recognized'.\n", $stderr.string
|
600
|
+
assert_equal( nil, $output )
|
601
|
+
end
|
602
|
+
#
|
603
|
+
|
604
|
+
class PassingMultipleSingleCharOptionsAsOneOption < Console::Command
|
605
|
+
def _x ; @x = true ; end
|
606
|
+
def _y ; @y = true ; end
|
607
|
+
def _z(n) ; @z = n ; end
|
608
|
+
|
609
|
+
global_option :_x
|
610
|
+
|
611
|
+
def go ; $output = [@x, @y, @z, @p] ; end
|
612
|
+
|
613
|
+
module Go
|
614
|
+
def _p(n)
|
615
|
+
@p = n.to_i
|
616
|
+
end
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
def test_PassingMultipleSingleCharOptionsAsOneOption
|
621
|
+
PassingMultipleSingleCharOptionsAsOneOption.execute( '-xy -z HERE go -p 1' )
|
622
|
+
assert_equal( [true, true, 'HERE', 1], $output )
|
623
|
+
end
|
624
|
+
|
625
|
+
#
|
626
|
+
|
627
|
+
class CommandWithOptionUsingEquals < Console::Command
|
628
|
+
module Go
|
629
|
+
def __mode(mode) ; @mode = mode ; end
|
630
|
+
end
|
631
|
+
def go ; $output = [@mode] ; end
|
632
|
+
end
|
633
|
+
|
634
|
+
def test_CommandWithOptionUsingEquals
|
635
|
+
CommandWithOptionUsingEquals.execute( 'go --mode smart' )
|
636
|
+
assert_equal( ['smart'], $output )
|
637
|
+
|
638
|
+
# I would expect this to work too, but currently it doesn't.
|
639
|
+
#assert_nothing_raised { CommandWithOptionUsingEquals.execute( 'go --mode=smart' ) }
|
640
|
+
#assert_equal( ['smart'], $output )
|
641
|
+
end
|
642
|
+
|
643
|
+
#
|
644
|
+
|
645
|
+
class CommandWithSubcommandThatTakesArgs < Console::Command
|
646
|
+
def go(arg1, *args) ; $output = [arg1] | args ; end
|
647
|
+
end
|
648
|
+
|
649
|
+
def test_CommandWithSubcommandThatTakesArgs
|
650
|
+
CommandWithSubcommandThatTakesArgs.execute( 'go file1 file2 file3' )
|
651
|
+
assert_equal( ['file1', 'file2', 'file3'], $output )
|
652
|
+
end
|
653
|
+
|
654
|
+
#
|
655
|
+
|
656
|
+
class CommandWith2OptionalArgs < Console::Command
|
657
|
+
def __here ; @here = true ; end
|
658
|
+
|
659
|
+
module Go
|
660
|
+
def _p(n)
|
661
|
+
@p = n.to_i
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
def go(required1 = nil, optional2 = nil) ; $output = [@here, @p, required1, optional2 ] ; end
|
666
|
+
end
|
667
|
+
|
668
|
+
def test_CommandWith2OptionalArgs
|
669
|
+
CommandWith2OptionalArgs.execute( '--here go -p 1 to' )
|
670
|
+
assert_equal( [true, 1, 'to', nil], $output )
|
671
|
+
end
|
672
|
+
|
673
|
+
#
|
674
|
+
|
675
|
+
class CommandWithVariableArgs < Console::Command
|
676
|
+
def __here ; @here = true ; end
|
677
|
+
|
678
|
+
module Go
|
679
|
+
def _p(n)
|
680
|
+
@p = n.to_i
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
684
|
+
def go(*args) ; $output = [@here, @p] | args ; end
|
685
|
+
end
|
686
|
+
|
687
|
+
def test_CommandWithVariableArgs
|
688
|
+
CommandWithVariableArgs.execute( '--here go -p 1 to bed' )
|
689
|
+
assert_equal( [true, 1, 'to', 'bed'], $output )
|
690
|
+
end
|
691
|
+
|
692
|
+
#
|
693
|
+
|
694
|
+
class CommandWithOptionMissing < Console::Command
|
695
|
+
def __here ; @here = true ; end
|
696
|
+
|
697
|
+
module Go
|
698
|
+
def option_missing(option_name, args)
|
699
|
+
p args if $debug
|
700
|
+
case option_name
|
701
|
+
when 'p'
|
702
|
+
@p = args[0].to_i
|
703
|
+
1
|
704
|
+
else
|
705
|
+
raise InvalidOptionError(option_name, args)
|
706
|
+
end
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
def go(*args) ; $output = [@here, @p] | args ; end
|
711
|
+
end
|
712
|
+
|
713
|
+
def test_CommandWithOptionMissing
|
714
|
+
CommandWithOptionMissing.execute( '--here go -p 1 to bed right now' )
|
715
|
+
assert_equal( [true, 1, 'to', 'bed', 'right', 'now'], $output )
|
716
|
+
end
|
717
|
+
|
718
|
+
#
|
719
|
+
|
720
|
+
class CommandWithOptionMissingArityOf2 < Console::Command
|
721
|
+
def __here ; @here = true ; end
|
722
|
+
|
723
|
+
module Go
|
724
|
+
def option_missing(option_name, args)
|
725
|
+
p args if $debug
|
726
|
+
case option_name
|
727
|
+
when 'p'
|
728
|
+
@p1 = args[0].to_i
|
729
|
+
@p2 = args[1].to_i
|
730
|
+
2
|
731
|
+
when 'q'
|
732
|
+
@q = args[0].to_i
|
733
|
+
nil # Test default arity
|
734
|
+
else
|
735
|
+
raise InvalidOptionError(option_name, args)
|
736
|
+
end
|
737
|
+
end
|
738
|
+
end
|
739
|
+
|
740
|
+
def go(*args) ; $output = [@here, @p1, @p2, @q] | args ; end
|
741
|
+
end
|
742
|
+
|
743
|
+
def test_CommandWithOptionMissingArityOf2
|
744
|
+
CommandWithOptionMissingArityOf2.execute( '--here go -p 1 2 -q 3 to bed right now' )
|
745
|
+
assert_equal( [true, 1, 2, 3, 'to', 'bed', 'right', 'now'], $output )
|
746
|
+
end
|
747
|
+
end
|
748
|
+
|
749
|
+
=end
|