OptionParser 0.5.0 → 0.5.1
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/LICENSE +31 -0
- data/README +36 -43
- data/docs/index.html +521 -362
- data/lib/commandline.rb +14 -0
- metadata +10 -10
- data/test/tc_option.rb +0 -121
- data/test/testall.rb +0 -16
data/LICENSE
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
OPTIONPARSER LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2005, Jim Freeze
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files
|
8
|
+
(the "Software"), to deal in the Software without restriction,
|
9
|
+
including without limitation the rights to use, copy, modify,
|
10
|
+
merge, publish, distribute, sublicense, and/or sell copies of the
|
11
|
+
Software, and to permit persons to whom the Software is furnished
|
12
|
+
to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
18
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
19
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
20
|
+
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
21
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
22
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
23
|
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
24
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
25
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
26
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
|
29
|
+
http://www.opensource.org/licenses/mit-license.php
|
30
|
+
http://www.opensource.org/licenses/bsd-license.php
|
31
|
+
|
data/README
CHANGED
@@ -1,32 +1,22 @@
|
|
1
|
-
LICENSE
|
2
|
-
|
3
|
-
This release is licensed under the RLL - Ruby Lovers License. If you don't
|
4
|
-
love Ruby, then you don't have permission to even think about using/reading/
|
5
|
-
opening any file in this project.
|
6
|
-
|
7
|
-
If you a lover of Ruby, then you may use this freely and pay for your use
|
8
|
-
by giving feedback to the author, Jim Freeze.
|
9
|
-
|
10
|
-
|
11
1
|
CommandLine::OptionParser
|
12
2
|
=========================
|
13
|
-
|
3
|
+
Author: Jim Freeze
|
4
|
+
Copyright 2005 Jim Freeze
|
14
5
|
|
15
6
|
ABOUT
|
16
7
|
=====
|
17
|
-
|
18
8
|
CommandLine::OptionParser is part of the CommandLine suite of
|
19
|
-
tools and is used for command line parsing. The
|
20
|
-
|
21
|
-
CommandLine::Application.
|
9
|
+
tools and is used for command line parsing. The command line
|
10
|
+
parser suite consists of classes CommandLine::Option,
|
11
|
+
CommandLine::OptionData and CommandLine::Application.
|
22
12
|
|
23
13
|
The parser supports POSIX, Gnu and XTools style parsing options.
|
24
|
-
It also
|
14
|
+
It also provides flexibility to support <em>non standard</em>
|
25
15
|
options. For example:
|
26
16
|
|
27
17
|
POSIX
|
28
18
|
=====
|
29
|
-
OptionParser.new Option.new(:names => "-f")
|
19
|
+
OptionParser.new Option.new(:posix, :names => "-f")
|
30
20
|
|
31
21
|
Gnu
|
32
22
|
===
|
@@ -43,50 +33,44 @@ OptionParser.new(Option.new(
|
|
43
33
|
:arg_arity => [1,-1],
|
44
34
|
:arg_description => "file1 [file2, ...]"))
|
45
35
|
|
46
|
-
This
|
36
|
+
This last option prints:
|
47
37
|
|
48
38
|
OPTIONS
|
49
39
|
|
50
40
|
--file,-file,--files,-files,-f file1 [file2, ...]
|
51
41
|
|
52
42
|
|
53
|
-
|
54
|
-
|
55
|
-
|
43
|
+
HISTORY
|
44
|
+
=======
|
56
45
|
After poking around in a few corporations, it was evident that
|
57
|
-
option parsing was not understood.
|
58
|
-
were built that did not conform to any of the POSIX, Gnu or XTools
|
46
|
+
option parsing was not well understood. Therefore, many inhouse
|
47
|
+
tools were built that did not conform to any of the POSIX, Gnu or XTools
|
59
48
|
option styles. CommandLine::OptionParser was developed so that
|
60
|
-
new
|
49
|
+
new applications could be written that conformed to accepted standards,
|
61
50
|
but non-standard option configurations could be handled as well
|
62
51
|
to support legacy interfaces.
|
63
52
|
|
64
|
-
More information on OptionParser can be found
|
65
|
-
http://
|
66
|
-
|
67
|
-
|
68
|
-
Major Features - 06/07/2005
|
69
|
-
=============
|
70
|
-
* First public release 0.5.0
|
71
|
-
|
72
|
-
|
73
|
-
Thanks for all the feedback!
|
74
|
-
|
53
|
+
More information and usage scenarios on OptionParser can be found at:
|
54
|
+
http://rubyforge.org/projects/optionparser/
|
75
55
|
|
76
56
|
Download & Installation
|
77
57
|
=======================
|
78
58
|
|
79
|
-
Homepage: http://
|
80
|
-
Download: http://rubyforge.org/frs/?group_id=
|
59
|
+
Homepage: http://rubyforge.org/projects/optionparser/
|
60
|
+
Download: http://rubyforge.org/frs/?group_id=632&release_id=2345
|
81
61
|
|
82
62
|
Dependencies:
|
83
63
|
* None
|
84
64
|
|
85
|
-
|
65
|
+
Currently optionparser is only available as a rubygem.
|
86
66
|
|
87
67
|
Via RubyGems
|
88
68
|
$ gem install optionparser
|
89
69
|
|
70
|
+
All feedback is appreciated!
|
71
|
+
|
72
|
+
Installations not available yet
|
73
|
+
===============================
|
90
74
|
# not in RPA yet
|
91
75
|
Via RPA
|
92
76
|
$ rpa install optionparser
|
@@ -102,9 +86,18 @@ The simplified do-it-yourself way
|
|
102
86
|
$ rake install
|
103
87
|
|
104
88
|
|
105
|
-
|
106
|
-
|
89
|
+
RELEASE NOTES
|
90
|
+
=============
|
91
|
+
|
92
|
+
---------------------------------------------------------------------
|
93
|
+
0.5.1 06/17/2005
|
94
|
+
* Contains all planned features except CVS like command handling
|
95
|
+
* Fixed loading path using gems. Is now loaded by:
|
96
|
+
require 'rubygems'
|
97
|
+
require 'commandline/optionparser'
|
98
|
+
* Updated documentation
|
99
|
+
|
100
|
+
---------------------------------------------------------------------
|
101
|
+
0.5.0 06/07/2005
|
102
|
+
* First public release
|
107
103
|
|
108
|
-
class MyApp << CommandLine::Application
|
109
|
-
|
110
|
-
end
|
data/docs/index.html
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
4
4
|
<head>
|
5
5
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
|
6
|
-
<title>
|
7
|
-
<link rel="alternate" type="text/xml" title="RSS"
|
8
|
-
href="http://localhost:8808/index.cgi/index.rss" />
|
6
|
+
<title>CommandLine::OptionParser</title>
|
9
7
|
|
10
8
|
<style type="text/css">
|
11
9
|
body,td {
|
@@ -26,7 +24,10 @@ h1, h2, h3, h4, h5, h6 {
|
|
26
24
|
}
|
27
25
|
|
28
26
|
pre {
|
29
|
-
border-left: 7px solid #e8d8d8;
|
27
|
+
#border-left: 7px solid #e8d8d8;
|
28
|
+
background: #ffeeff;
|
29
|
+
border-top: 2px solid #aaaaaa;
|
30
|
+
border-left: 2px solid #aaaaaa;
|
30
31
|
}
|
31
32
|
|
32
33
|
.sidebar {
|
@@ -207,30 +208,522 @@ pre {
|
|
207
208
|
</head>
|
208
209
|
<body>
|
209
210
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
211
|
+
<tr valign="bottom">
|
212
|
+
<td class="pagetitle">CommandLine::OptionParser</a></td>
|
213
|
+
</tr>
|
214
|
+
</table>
|
215
|
+
<hr />
|
216
|
+
<table>
|
217
|
+
<tr valign="top"><td>
|
218
|
+
|
219
|
+
<table class="entry" border="0" cellspacing="0" width="100%">
|
210
220
|
<tr class="entrybody"><td colspan="3" class="entrybody">
|
211
|
-
<h1>Welcome to
|
212
|
-
<
|
213
|
-
|
221
|
+
<h1>Welcome to OptionParser</h1>
|
222
|
+
<ul>
|
223
|
+
<li>Copyright © 2005 Jim Freeze
|
224
|
+
|
225
|
+
</li>
|
226
|
+
<li>Author: Jim Freeze
|
227
|
+
|
228
|
+
</li>
|
229
|
+
<li><a href="http://www.freeze.org/ruby/optionparser/license.txt">License</a>
|
230
|
+
</li>
|
231
|
+
<li><a href="http://rubyforge.org/projects/optionparser/">Project Page</a>
|
232
|
+
</li>
|
233
|
+
<li><a href="http://rubyforge.org/frs/?group_id=632&release_id=2345">Download</a>
|
234
|
+
</li>
|
235
|
+
</ul>
|
236
|
+
<tt>OptionParser</tt> is
|
214
237
|
designed to be a flexible command line parser with a Ruby look and feel to
|
215
|
-
it. <
|
216
|
-
|
217
|
-
|
218
|
-
<tt>
|
238
|
+
it. <tt>OptionParser</tt> got
|
239
|
+
its birth from the need for a parser that is standards compliant, yet
|
240
|
+
flexible. <tt>OptionParser</tt>
|
241
|
+
supports the standard command line styles of <tt>Unix</tt>, <tt>Gnu</tt>
|
242
|
+
and <tt>X Toolkit</tt>, but also lets you break those rules.
|
243
|
+
|
244
|
+
<p>
|
245
|
+
<tt>OptionParser</tt> is
|
246
|
+
not a port of a traditional command line parser, but it is written to meet
|
247
|
+
the feature requirements of traditional command line parsers. When using it
|
248
|
+
as a library, you should notice that it is expressive, supports
|
249
|
+
Ruby’s blocks and lambda’s, and is sprinkled with a little bit
|
250
|
+
of magic.
|
251
|
+
</p>
|
252
|
+
<p>
|
253
|
+
While the library can be used by itself, it is also designed to work with
|
254
|
+
the <tt>CommandLine::Application</tt> class. These tools work together to
|
255
|
+
facilitate the generation of a sophisticated (batch oriented) application
|
256
|
+
user interface in a matter of minutes.
|
257
|
+
</p>
|
258
|
+
<p>
|
259
|
+
If you need a refresher on the traditional option parsing schemes, see
|
260
|
+
"Traditional Option Parsing Schemes" below.
|
261
|
+
</p>
|
262
|
+
<h1>Jumping Right In</h1>
|
263
|
+
<h1>OptionParser Usage</h1>
|
264
|
+
<p>
|
265
|
+
The OptionParser
|
266
|
+
library consists of three classes, <tt>Option</tt>, <tt>OptionParser</tt> and
|
267
|
+
<tt>OptionData</tt>. For each option an <tt>Option</tt> object is created.
|
268
|
+
When you are ready to prepare for command line parsing, these options are
|
269
|
+
collected into an array and fed to <tt>OptionParser</tt>.
|
270
|
+
This <tt>OptionParser</tt>
|
271
|
+
object controls the type of option scheme that is implemented. When it
|
272
|
+
comes time to parse a command line, call the method <tt>Option#parse</tt>.
|
273
|
+
This will parse any array, but parses ARGV by default. The result is an
|
274
|
+
<tt>OptionData</tt> object. This object can be used from which to extract
|
275
|
+
values or it can be passed to another class as a fully encapsulated data
|
276
|
+
object.
|
277
|
+
</p>
|
278
|
+
<h2>Getting Started</h2>
|
279
|
+
<h3>Installing</h3>
|
280
|
+
<pre>
|
281
|
+
gem install -r OptionParser
|
282
|
+
</pre>
|
283
|
+
<h3>Loading the library</h3>
|
284
|
+
<pre>
|
285
|
+
require 'rubygems'
|
286
|
+
require 'commandline/optionparser'
|
287
|
+
include CommandLine
|
288
|
+
</pre>
|
289
|
+
<h3>Using Option Parser</h3>
|
290
|
+
<p>
|
291
|
+
An option is created with the following syntax:
|
292
|
+
</p>
|
293
|
+
<pre>
|
294
|
+
opt = Option.new([options], <properties>)
|
295
|
+
</pre>
|
296
|
+
<p>
|
297
|
+
The options can be <tt>:flag</tt> or <tt>:posix</tt>. <tt>:flag</tt> means
|
298
|
+
that the option is a mode flag and does not take any arguments.
|
299
|
+
<tt>:posix</tt> means that <tt>Option</tt> will validate the properties to
|
300
|
+
ensure they are posix compliant.
|
301
|
+
</p>
|
302
|
+
<p>
|
303
|
+
An option object has six properties. Four of these properties define
|
304
|
+
attributes of the object. The last two define <em>actions</em> that are
|
305
|
+
taken when a command line is parsed.
|
306
|
+
</p>
|
307
|
+
<ol>
|
308
|
+
<li>:names
|
309
|
+
|
310
|
+
</li>
|
311
|
+
<li>:arg_arity
|
312
|
+
|
313
|
+
</li>
|
314
|
+
<li>:opt_description
|
315
|
+
|
316
|
+
</li>
|
317
|
+
<li>:arg_description
|
318
|
+
|
319
|
+
</li>
|
320
|
+
<li>:opt_found
|
321
|
+
|
322
|
+
</li>
|
323
|
+
<li>:opt_not_found
|
324
|
+
|
325
|
+
</li>
|
326
|
+
</ol>
|
327
|
+
<p>
|
328
|
+
It is not necessary to set values for all of these properties. Some are set
|
329
|
+
automatically, as we’ll see below.
|
330
|
+
</p>
|
331
|
+
<h3>Posix</h3>
|
332
|
+
<p>
|
333
|
+
The default <tt>Option</tt> object is non-posix.
|
334
|
+
</p>
|
335
|
+
<pre>
|
336
|
+
op1 = OptionParser.new(:posix, opts)
|
337
|
+
op2 = OptionParser.new(opts)
|
338
|
+
op1.posix #=> true
|
339
|
+
op2.posix #=> false
|
340
|
+
</pre>
|
341
|
+
<h3>Mode-Flag</h3>
|
342
|
+
<p>
|
343
|
+
To create a mode flag, that is, an option that is either true or false
|
344
|
+
depending if it is seen on the command line or not, we could write:
|
345
|
+
</p>
|
346
|
+
<pre>
|
347
|
+
opt_debug = Option.new(
|
348
|
+
:names => %w(--debug -d), # the flag has two names
|
349
|
+
:arg_arity => [0,0], # this says take no arugments
|
350
|
+
:opt_description => "Sets debug to true",
|
351
|
+
:arg_description => "",
|
352
|
+
:opt_found => true, # true if seen on command line
|
353
|
+
:opt_not_found => false # false if not seen on command line
|
354
|
+
)
|
355
|
+
</pre>
|
356
|
+
<p>
|
357
|
+
Now, this is a lot of work just for a common mode-flag. However, there is a
|
358
|
+
shorter way:
|
359
|
+
</p>
|
360
|
+
<pre>
|
361
|
+
opt = Option.new(:flag, :names => %w(--debug -d))
|
362
|
+
</pre>
|
363
|
+
<p>
|
364
|
+
When <tt>Option</tt> sees the :flag option, it makes some assignments
|
365
|
+
behind the scenes and what you are left with is:
|
366
|
+
</p>
|
367
|
+
<pre>
|
368
|
+
:names => ["--debug", "-d"]
|
369
|
+
:arg_arity => [0, 0]
|
370
|
+
:opt_description => "Sets debug to true." # debug is taken from the first name
|
371
|
+
:arg_description => ""
|
372
|
+
:opt_found => true
|
373
|
+
:opt_not_found => false
|
374
|
+
</pre>
|
375
|
+
<p>
|
376
|
+
For a common option like a mode-flag, <tt>Option</tt> will use the first
|
377
|
+
option ‘word’ it finds in the :names list and use that in the
|
378
|
+
automatic option text. Of course, if you don’t want any text, just
|
379
|
+
set the option description to an empty string:
|
380
|
+
</p>
|
381
|
+
<pre>
|
382
|
+
:opt_description => "".
|
383
|
+
</pre>
|
384
|
+
<h3>Option Arguments</h3>
|
385
|
+
<p>
|
386
|
+
If an option is not a mode flag, then it takes arguments. Most option
|
387
|
+
parsers only permit a single argument per option flag. If your application
|
388
|
+
needs multiple arguments, the standard method is just to repeat the option
|
389
|
+
multiple times, once for each required argument. For example, if I need to
|
390
|
+
pass two files to an application I would need something like:
|
391
|
+
</p>
|
392
|
+
<pre>
|
393
|
+
myapp -f file1 -f file2
|
394
|
+
</pre>
|
395
|
+
<p>
|
396
|
+
But, it would be cleaner if the command line could be expressed as:
|
397
|
+
</p>
|
398
|
+
<pre>
|
399
|
+
myapp -f file1 file2
|
400
|
+
</pre>
|
401
|
+
<p>
|
402
|
+
Well, no longer do you have to suffer with thirty-year old option parser
|
403
|
+
technology. <tt>OptionParser</tt>
|
404
|
+
permits multiple arguments per option flag and the number of arguments can
|
405
|
+
be defined to be variable.
|
406
|
+
</p>
|
407
|
+
<p>
|
408
|
+
To define an option that takes 1 or more arguments, the following can be
|
409
|
+
done:
|
410
|
+
</p>
|
411
|
+
<pre>
|
412
|
+
opt = Option.new(:names => "--file", :arg_arity => [1,-1])
|
413
|
+
</pre>
|
414
|
+
<p>
|
415
|
+
Let’s say the option required at least two arguments, but not more
|
416
|
+
than five. This is defined with:
|
417
|
+
</p>
|
418
|
+
<pre>
|
419
|
+
opt = Option.new(:names => "--file", :arg_arity => [2,5])
|
420
|
+
OptionParser.new(opt).parse
|
421
|
+
|
422
|
+
% myapp --file file1 # exception raised
|
423
|
+
% myapp --file file1 file2 # ok
|
424
|
+
% myapp --file file1 file2 file3 # ok
|
425
|
+
% myapp --file f1 f2 f3 f4 f5 f6 # f6 remains on the command line
|
426
|
+
</pre>
|
427
|
+
<p>
|
428
|
+
This ability is handy on occassions where an option argument is
|
429
|
+
‘optional’.
|
430
|
+
</p>
|
431
|
+
<pre>
|
432
|
+
myapp --custom # no args, uses $HOME/.myapprc
|
433
|
+
myapp --custom my_custom_file # uses my_custom_file
|
434
|
+
</pre>
|
435
|
+
<p>
|
436
|
+
This type of option is defined by:
|
437
|
+
</p>
|
438
|
+
<pre>
|
439
|
+
opt = Option.new(:names => "--custom", :arg_arity => [0,1])
|
440
|
+
</pre>
|
441
|
+
<p>
|
442
|
+
If the <tt>:arg_arity</tt> is not satisfied, an exception is raised.
|
443
|
+
</p>
|
444
|
+
<h3>Actions</h3>
|
445
|
+
<p>
|
446
|
+
The option properties <tt>:opt_found</tt> and <tt>:opt_not_found</tt> are
|
447
|
+
the source of the value returned for an option when it is parsed. These
|
448
|
+
properties can be either an object or a proc/lambda. If they are an object,
|
449
|
+
then the stored object is simply returned. If they are lambdas, then the
|
450
|
+
stored value is the return value of the proc/lambda. So, the following will
|
451
|
+
have the same result:
|
452
|
+
</p>
|
453
|
+
<pre>
|
454
|
+
opt_debug = Option.new(:flag
|
455
|
+
:names => %w(--debug -d),
|
456
|
+
:opt_found => true,
|
457
|
+
:opt_not_found => false
|
458
|
+
)
|
219
459
|
|
460
|
+
opt_debug = Option.new(:flag
|
461
|
+
:names => %w(--debug -d),
|
462
|
+
:opt_found => lambda { true },
|
463
|
+
:opt_not_found => lambda { false }
|
464
|
+
)
|
465
|
+
</pre>
|
466
|
+
<p>
|
467
|
+
Notice that there is no need to set an instance variable to a default
|
468
|
+
value. Normally one does:
|
469
|
+
</p>
|
470
|
+
<pre>
|
471
|
+
@debug = false
|
472
|
+
# option setup
|
473
|
+
... parse the commandline
|
474
|
+
@debug = true if parse_results["--debug"]
|
475
|
+
</pre>
|
476
|
+
<p>
|
477
|
+
But with <tt>OptionParser</tt>, one
|
478
|
+
has the capability of doing the following:
|
479
|
+
</p>
|
480
|
+
<pre>
|
481
|
+
opt_debug = Option.new(:flag, :names => %w(--debug -d))
|
482
|
+
... parse the commandline
|
483
|
+
@debug = option_data[:debug] # value is set without need for default
|
484
|
+
|
485
|
+
# or
|
486
|
+
|
487
|
+
opt_debug = Option.new(:flag
|
488
|
+
:names => %w(--debug -d),
|
489
|
+
:opt_found => lambda { @debug = true },
|
490
|
+
:opt_not_found => lambda { @debug = false }
|
491
|
+
)
|
492
|
+
# do nothing, variable already set.
|
493
|
+
</pre>
|
494
|
+
<p>
|
495
|
+
I find this much easier to manage than having to worry about setting
|
496
|
+
default behaviour. Now that we know how to create options, let’s move
|
497
|
+
on to the commandline parser.
|
498
|
+
</p>
|
499
|
+
<h2>OptionParser</h2>
|
500
|
+
<p>
|
501
|
+
Once the options are defined, we load them into an <tt>OptionParser</tt> and
|
502
|
+
parse the command line. The syntax for creating an <tt>OptionParser</tt>
|
503
|
+
object is:
|
504
|
+
</p>
|
505
|
+
<pre>
|
506
|
+
OptionParser.new(prop_flags, option)
|
507
|
+
OptionParser.new(prop_flags, [options])
|
508
|
+
OptionParser.new(option)
|
509
|
+
OptionParser.new([options])
|
510
|
+
</pre>
|
511
|
+
<p>
|
512
|
+
where the possible property flags are:
|
513
|
+
</p>
|
514
|
+
<pre>
|
515
|
+
:posix
|
516
|
+
:unknown_options_action => :collect | :ignore | :raise
|
517
|
+
</pre>
|
518
|
+
<p>
|
519
|
+
If you want to parse posix, you must specify so. <tt>OptionParser</tt> will
|
520
|
+
not assume posix mode just because all of the options are posix options.
|
521
|
+
This allows you to use posix only options but not require the strict
|
522
|
+
parsing rules.
|
523
|
+
</p>
|
524
|
+
<p>
|
525
|
+
Below are a few examples of creating an <tt>OptionParser</tt>
|
526
|
+
object:
|
527
|
+
</p>
|
528
|
+
<pre>
|
529
|
+
opt = Option.new(:flag, :names => %w(-h))
|
530
|
+
op1 = OptionParser.new(:posix, opt)
|
531
|
+
op2 = OptionParser.new(opt)
|
532
|
+
</pre>
|
533
|
+
<p>
|
534
|
+
or
|
535
|
+
</p>
|
536
|
+
<pre>
|
537
|
+
opts = []
|
538
|
+
opts << Option.new(:flag, :names => %w(--help h))
|
539
|
+
opts << Option.new(:flag, :names => %w(--debug d))
|
540
|
+
</pre>
|
541
|
+
<p>
|
542
|
+
Options may be added to an <tt>OptionParser</tt> by
|
543
|
+
three different methods:
|
544
|
+
</p>
|
545
|
+
<pre>
|
546
|
+
# Options added as arguments during OptionParser construction
|
547
|
+
op = OptionParser.new(opt1, opt2)
|
548
|
+
op = OptionParser.new([opt1, opt2])
|
549
|
+
</pre>
|
550
|
+
<p>
|
551
|
+
or
|
552
|
+
</p>
|
553
|
+
<pre>
|
554
|
+
# Options added in a block constructor
|
555
|
+
op = OptionParser.new { |o| o << opts }
|
556
|
+
</pre>
|
557
|
+
<p>
|
558
|
+
or
|
559
|
+
</p>
|
560
|
+
<pre>
|
561
|
+
# Options added to an existing OptionParser object
|
562
|
+
op = OptionParser.new
|
563
|
+
op << opts
|
564
|
+
</pre>
|
565
|
+
<h3>Parsing the Command Line</h3>
|
566
|
+
<p>
|
567
|
+
Parsing the command line is as simple as calling <tt>#parse</tt>:
|
568
|
+
</p>
|
569
|
+
<pre>
|
570
|
+
option_data = op.parse
|
571
|
+
</pre>
|
572
|
+
<h3>Printing an Option Summary</h3>
|
573
|
+
<p>
|
574
|
+
A <tt>OptionParser</tt> with
|
575
|
+
a complete set of options added to it defines the human interface that your
|
576
|
+
application presents to a user. Therefore, the parser should be able to
|
577
|
+
provide a nicely formatted summary for the user.
|
578
|
+
</p>
|
579
|
+
<p>
|
580
|
+
An example is shown below with its corresponding output:
|
581
|
+
</p>
|
582
|
+
<pre>
|
583
|
+
require 'rubygems'
|
584
|
+
require 'commandline/optionparser'
|
585
|
+
include CommandLine
|
586
|
+
puts OptionParser.new { |o|
|
587
|
+
o << Option.new(:flag, :names => %w[--debug -d])
|
588
|
+
o << Option.new(:flag, :names => %w[--help -h],
|
589
|
+
:opt_description => "Prints this page.")
|
590
|
+
o << Option.new(:names => %w[--ouput -o],
|
591
|
+
:opt_description => "Defines the output file.",
|
592
|
+
:arg_description => "output_file")
|
593
|
+
o << Option.new(:names => %w[--a-long-opt --with-many-names -a -A],
|
594
|
+
:arg_arity => [2,-1],
|
595
|
+
:opt_description => "Your really long description here.",
|
596
|
+
:arg_description => "file1 file2 [file3 ...]")
|
597
|
+
}.to_s
|
598
|
+
</pre>
|
599
|
+
<p>
|
600
|
+
Generates the output:
|
601
|
+
</p>
|
602
|
+
<pre>
|
603
|
+
OPTIONS
|
604
|
+
|
605
|
+
--debug,-d
|
606
|
+
Sets debug to true.
|
607
|
+
|
608
|
+
--help,-h
|
609
|
+
Prints this page.
|
610
|
+
|
611
|
+
--ouput,-o output_file
|
612
|
+
Defines the output file.
|
613
|
+
|
614
|
+
--a-long-opt,--with-many-names,-a,-A file1 file2 [file3 ...]
|
615
|
+
Your really long description here.
|
616
|
+
</pre>
|
617
|
+
<h2>Option Data</h2>
|
618
|
+
<p>
|
619
|
+
The <tt>OptionData</tt> is the return value of <tt>OptionParser#parse</tt>.
|
620
|
+
The parsing results for each option are accessed with the bracket notation
|
621
|
+
#[].
|
622
|
+
</p>
|
623
|
+
<pre>
|
624
|
+
opt = Option.new(:posix,
|
625
|
+
:names => %w(-r),
|
626
|
+
:opt_found => OptionParser::GET_ARGS)
|
627
|
+
od = OptionParser.new(:posix, opt).parse(["-rubygems"])
|
628
|
+
od["-r"] #=> "ubygems"
|
629
|
+
|
630
|
+
od = OptionParser.new(:posix, opt).parse(["-r", "ubygems"])
|
631
|
+
od["-r"] #=> "ubygems"
|
632
|
+
</pre>
|
633
|
+
<p>
|
634
|
+
<tt>OptionData</tt> behaves similar to a hash object in that the parsed
|
635
|
+
option data is accessed with #[] where the key is the first item in the
|
636
|
+
:names array of each option. An option cannot access its parsed values
|
637
|
+
using just any of its names.
|
638
|
+
</p>
|
639
|
+
<pre>
|
640
|
+
od = OptionParser.new { |o|
|
641
|
+
o << Option.new(:flag, :names => %w(--valid --notvalid))
|
642
|
+
o << Option.new(:flag, :names => %w(--first --second))
|
643
|
+
}.parse(%w(--notvalid --second))
|
644
|
+
od["--valid"] #=> true
|
645
|
+
od["--first"] #=> true
|
646
|
+
od["--notvalid"] #=> CommandLine::OptionData::UnknownOptionError
|
647
|
+
od["--second"] #=> CommandLine::OptionData::UnknownOptionError
|
648
|
+
</pre>
|
649
|
+
<h3>Built-in Data Handlers</h3>
|
650
|
+
<p>
|
651
|
+
OptionParser has
|
652
|
+
built-in data handlers for handling common scenarios. These lambdas can
|
653
|
+
save a lot of typing.
|
654
|
+
</p>
|
655
|
+
<h3>GET_ARG_ARRAY</h3>
|
656
|
+
<p>
|
657
|
+
This is useful for options that take a variable number of arguments. It
|
658
|
+
returns all the arguments in an array.
|
659
|
+
</p>
|
660
|
+
<pre>
|
661
|
+
# GET_ARG_ARRAY returns all arguments in an array, even if no
|
662
|
+
# arguments are present. This is not to be confused with the option
|
663
|
+
# occuring multiple times on the command line.
|
664
|
+
opt = Option.new(:names => %w(--file),
|
665
|
+
:argument_arity => [0,-1],
|
666
|
+
:opt_found => OptionParser::GET_ARG_ARRAY)
|
667
|
+
#:opt_found => :collect) # would this be better?
|
668
|
+
od = OptionParser.new(opt).parse(%w(--file))
|
669
|
+
od["--file"] #=> []
|
670
|
+
od = OptionParser.new(opt).parse(%w(--file=file))
|
671
|
+
od["--file"] #=> ["file"]
|
672
|
+
od = OptionParser.new(opt).parse(%w(--file=file1 --file file2))
|
673
|
+
od["--file"] #=> ["file2"]
|
674
|
+
od = OptionParser.new(opt).parse(%w(--file=file1 file2))
|
675
|
+
od["--file"] #=> ["file1", "file2"]
|
676
|
+
od = OptionParser.new(opt).parse(%w(--file file1 file2))
|
677
|
+
od["--file"] #=> ["file1", "file2"]
|
678
|
+
</pre>
|
679
|
+
<h3>GET_ARGS</h3>
|
680
|
+
<p>
|
681
|
+
This is a ‘smart’ option getter. If no arguments are found, it
|
682
|
+
returns true. If a single argument is found, it returns that argument. If
|
683
|
+
more than one argument is found, it returns an array of those arguments.
|
684
|
+
</p>
|
685
|
+
<pre>
|
686
|
+
opt = Option.new(:names => %w(--file),
|
687
|
+
:argument_arity => [0,-1],
|
688
|
+
:opt_found => OptionParser::GET_ARGS)
|
689
|
+
#:opt_found => :smart_collect) # would this be better?
|
690
|
+
od = OptionParser.new(opt).parse(%w(--file))
|
691
|
+
od["--file"] #=> true
|
692
|
+
od = OptionParser.new(opt).parse(%w(--file=file))
|
693
|
+
od["--file"] #=> "file"
|
694
|
+
od = OptionParser.new(opt).parse(%w(--file=file1 --file file2))
|
695
|
+
od["--file"] #=> "file2"
|
696
|
+
od = OptionParser.new(opt).parse(%w(--file=file1 file2))
|
697
|
+
od["--file"] #=> ["file1", "file2"]
|
698
|
+
od = OptionParser.new(opt).parse(%w(--file file1 file2))
|
699
|
+
od["--file"] #=> ["file1", "file2"]
|
700
|
+
</pre>
|
220
701
|
<p>
|
221
|
-
|
222
|
-
a port of a traditional command line parser, but it is written to meet the
|
223
|
-
feature requirements of traditional command line parsers. When using it as
|
224
|
-
a library, you should notice that it is expressive, supports Ruby’s
|
225
|
-
blocks and lambda’s, and is sprinkled with a little bit of magic.
|
702
|
+
And, for those oxymoronic non-optional options:
|
226
703
|
</p>
|
704
|
+
<pre>
|
705
|
+
opt = Option.new(:names => %w(--not-really-an-option),
|
706
|
+
:opt_not_found => OptionParser::OPT_NOT_FOUND_BUT_REQUIRED
|
707
|
+
)
|
708
|
+
OptionParser.new(opt).parse([]) #=> OptionParser::MissingRequiredOptionError
|
709
|
+
</pre>
|
710
|
+
<h3><tt>OptionData</tt></h3>
|
227
711
|
<p>
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
712
|
+
We have just shown that after parsing a command line, the result of each
|
713
|
+
option is found from OptionData. The values that remain on the command line
|
714
|
+
are assigned to <tt>args</tt>. Other attributes of <tt>OptionData</tt> are:
|
715
|
+
</p>
|
716
|
+
<pre>
|
717
|
+
od.argv # the original command line
|
718
|
+
od.unknown_options # If OptionParser was told to :collect unknown options
|
719
|
+
od.args # arguments not claimed by any option
|
720
|
+
od.not_parsed # arguments following a '--' on the command line
|
721
|
+
od.cmd # not yet implemented - but a cvs like command
|
722
|
+
</pre>
|
723
|
+
<hr size="2"></hr><h1>Traditional Option Parsing Schemes</h1>
|
724
|
+
<p>
|
725
|
+
This section is a brief overview of traditional command line parsing.
|
232
726
|
</p>
|
233
|
-
<h1>Traditional Option Parsing Schemes</h1>
|
234
727
|
<p>
|
235
728
|
Command line options traditionally occur in three flavors:
|
236
729
|
</p>
|
@@ -371,11 +864,6 @@ The options in this style are sometimes referred to as
|
|
371
864
|
The compatibility is maintained by preceding the <em>long_options</em> with
|
372
865
|
two dashes. The option word must be two or more characters.
|
373
866
|
</p>
|
374
|
-
<pre>
|
375
|
-
:test
|
376
|
-
if gnu_style is slected, ensure only two options and that one
|
377
|
-
is Unix and one is Gnu style.
|
378
|
-
</pre>
|
379
867
|
<h3>Separation Between the Option Flag and Its Argument</h3>
|
380
868
|
<p>
|
381
869
|
Gnu style options cannot be grouped. For options that have an argument, the
|
@@ -419,18 +907,16 @@ filtered from the command line before passing them to an application.
|
|
419
907
|
<p>
|
420
908
|
It is convention that a bare hypen indicates to read from stdin.
|
421
909
|
</p>
|
422
|
-
<h2>The
|
910
|
+
<h2>The OptionParser Style</h2>
|
423
911
|
<p>
|
424
|
-
The CommandLine
|
425
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> does not
|
912
|
+
The CommandLine::OptionParser does not
|
426
913
|
care what style you use. It is designed for maximum flexiblity so it may be
|
427
914
|
used within any organiziation to meet their standards.
|
428
915
|
</p>
|
429
916
|
<h3>Multiple Option Names</h3>
|
430
|
-
<p>
|
431
|
-
<a href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> does
|
917
|
+
<p> OptionParser does
|
432
918
|
not place restrictions on the number of options. The only restriction is
|
433
|
-
that an option name begin with a hyphen ’-’.
|
919
|
+
that an option name begin with a hyphen ’-’. A definitely
|
434
920
|
conjured example of this freedom is:
|
435
921
|
</p>
|
436
922
|
<pre>
|
@@ -438,7 +924,6 @@ conjured example of this freedom is:
|
|
438
924
|
--file --File --f --F -file -File -f -F
|
439
925
|
)
|
440
926
|
</pre>
|
441
|
-
<h2>Miscellaneous Option Styles</h2>
|
442
927
|
<h3>Prefix Matching</h3>
|
443
928
|
<p>
|
444
929
|
Although not encouraged, some prefer the ability to truncate option words
|
@@ -474,8 +959,7 @@ should happen when the following is given:
|
|
474
959
|
<p>
|
475
960
|
Should the parser flag this as an error or should it accept both arguments.
|
476
961
|
</p>
|
477
|
-
<p>
|
478
|
-
<a href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> gives
|
962
|
+
<p> OptionParser gives
|
479
963
|
you the choice of whether it raises an exception when an option is seen
|
480
964
|
more than once, or it just passes the data onto the user.
|
481
965
|
</p>
|
@@ -510,337 +994,12 @@ on how this is handled in the usage section.
|
|
510
994
|
A conflict can occur where a grouping of single letter Unix options has the
|
511
995
|
value as a word option preceded by a single dash. For this reason, it is
|
512
996
|
customary to use the double-dash notation for word options. Unless
|
513
|
-
double-dashes are enforced for word options,
|
514
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> will
|
997
|
+
double-dashes are enforced for word options, OptionParser will
|
515
998
|
check for possible name conflicts and raise an exception if it finds one.
|
516
999
|
</p>
|
517
|
-
<p>
|
518
|
-
An individual Option. Why isnt’ a hash good enough? I think it is. An
|
519
|
-
option, is a hash. But, it can’t validate itself. <a
|
520
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> should
|
521
|
-
worry about parsing using a collection of options
|
522
|
-
</p>
|
523
|
-
<h1><a href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> Usage</h1>
|
524
|
-
<p>
|
525
|
-
The <a href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a>
|
526
|
-
library consists of three classes, <tt>Option</tt>, <tt><a
|
527
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a></tt> and
|
528
|
-
<tt>OptionData</tt>. For each option an <tt>Option</tt> object is created.
|
529
|
-
When you are ready to prepare for command line parsing, these options are
|
530
|
-
collected into an <tt><a
|
531
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a></tt>
|
532
|
-
object. This object controls the type of option scheme that is to be
|
533
|
-
implemented. When it comes time to parse a command line, call the method
|
534
|
-
+Option#parse+. This will parse any array, but parses ARGV by default. The
|
535
|
-
result is an <tt>OptionData</tt> object. This object can be used from which
|
536
|
-
to extract values or it can be passed to another class as a fully
|
537
|
-
encapsulated data object.
|
538
|
-
</p>
|
539
|
-
<h2>Getting Started</h2>
|
540
|
-
<p>
|
541
|
-
An option is created with the following syntax:
|
542
|
-
</p>
|
543
|
-
<pre>
|
544
|
-
opt = Option.new([type], [options], <properties>)
|
545
|
-
</pre>
|
546
|
-
<p>
|
547
|
-
The optional type can be <tt>:flag</tt> or <tt>:default</tt>, with
|
548
|
-
<tt>:default</tt> naturally being the default.
|
549
|
-
</p>
|
550
|
-
<p>
|
551
|
-
The options supported are
|
552
|
-
</p>
|
553
|
-
<pre>
|
554
|
-
:posix => true | false
|
555
|
-
</pre>
|
556
|
-
<p>
|
557
|
-
with <tt>:posix => false</tt> being the default.
|
558
|
-
</p>
|
559
|
-
<p>
|
560
|
-
An option object has six properties. Four of these properties define
|
561
|
-
attributes of the object. The last two define <em>actions</em> that are
|
562
|
-
taken when a command line is parsed.
|
563
|
-
</p>
|
564
|
-
<ol>
|
565
|
-
<li>:names
|
566
|
-
|
567
|
-
</li>
|
568
|
-
<li>:arg_arity
|
569
|
-
|
570
|
-
</li>
|
571
|
-
<li>:opt_description
|
572
|
-
|
573
|
-
</li>
|
574
|
-
<li>:arg_description
|
575
|
-
|
576
|
-
</li>
|
577
|
-
<li>:opt_found
|
578
|
-
|
579
|
-
</li>
|
580
|
-
<li>:opt_not_found
|
581
|
-
|
582
|
-
</li>
|
583
|
-
</ol>
|
584
|
-
<h3>Mode-Flag</h3>
|
585
|
-
<p>
|
586
|
-
To create a mode flag, that is an option that is either true or false
|
587
|
-
depending if it is seen on the command line, we write:
|
588
|
-
</p>
|
589
|
-
<pre>
|
590
|
-
opt_debug = Option.new(
|
591
|
-
:names => %w(--debug -d),
|
592
|
-
:arg_arity => [0,0],
|
593
|
-
:opt_description => "Sets debug to true",
|
594
|
-
:arg_description => "",
|
595
|
-
:opt_found => true,
|
596
|
-
:opt_not_found => false
|
597
|
-
)
|
598
|
-
</pre>
|
599
|
-
<p>
|
600
|
-
Now, this is a lot of work just for a common mode-flag. However, there is a
|
601
|
-
shorter way:
|
602
|
-
</p>
|
603
|
-
<pre>
|
604
|
-
opt = Option.new(:flag,
|
605
|
-
:names => %w(--debug -d),
|
606
|
-
:opt_description => "Sets debug to true.")
|
607
|
-
</pre>
|
608
|
-
<p>
|
609
|
-
Or, even simpler yet,
|
610
|
-
</p>
|
611
|
-
<pre>
|
612
|
-
opt = Option.new(:flag, :names => %w(--debug -d))
|
613
|
-
</pre>
|
614
|
-
<p>
|
615
|
-
For a common option like a mode-flag, <tt>Option</tt> will use the first
|
616
|
-
option ‘word’ it finds in the :names list and use that in the
|
617
|
-
automatic option text. Of course, if you don’t want any text, just
|
618
|
-
set the option description to an empty string:
|
619
|
-
</p>
|
620
|
-
<pre>
|
621
|
-
:opt_description => "".
|
622
|
-
</pre>
|
623
|
-
<h3>POSIX</h3>
|
624
|
-
<p>
|
625
|
-
The default for is false, so the following are equivalent:
|
626
|
-
</p>
|
627
|
-
<pre>
|
628
|
-
op1 = OptionParser.new(opts, :posix => false)
|
629
|
-
op2 = OptionParser.new(opts)
|
630
|
-
op1.posix) #=> false
|
631
|
-
op2.posix) #=> false
|
632
|
-
</pre>
|
633
|
-
<h3>Actions</h3>
|
634
|
-
<p>
|
635
|
-
The option properties <tt>:opt_found</tt> and <tt>:opt_not_found</tt> are
|
636
|
-
the source of the value returned for an option when it is parsed. These
|
637
|
-
properties can be either an object or a proc/lambda. If they are an object,
|
638
|
-
then the stored object is simply returned. If they are lambdas, then the
|
639
|
-
stored value is the result of executing the lambda. So, the following will
|
640
|
-
have the same result:
|
641
|
-
</p>
|
642
|
-
<p>
|
643
|
-
object is the Options can perform actions
|
644
|
-
</p>
|
645
|
-
<pre>
|
646
|
-
opt_debug = Option.new(:flag
|
647
|
-
:names => %w(--debug -d),
|
648
|
-
:opt_found => true,
|
649
|
-
:opt_not_found => false
|
650
|
-
)
|
651
|
-
|
652
|
-
opt_debug = Option.new(:flag
|
653
|
-
:names => %w(--debug -d),
|
654
|
-
:opt_found => lambda { true },
|
655
|
-
:opt_not_found => lambda { false }
|
656
|
-
)
|
657
|
-
</pre>
|
658
|
-
<p>
|
659
|
-
The key to notice here is that there is never a need to set an instance
|
660
|
-
variable to a default value. Normally one does:
|
661
|
-
</p>
|
662
|
-
<pre>
|
663
|
-
@debug = false
|
664
|
-
# option setup
|
665
|
-
... parse the commandline
|
666
|
-
@debug = true if parse_results[:debug]
|
667
|
-
</pre>
|
668
|
-
<p>
|
669
|
-
Here, one has the option of doing the following:
|
670
|
-
</p>
|
671
|
-
<pre>
|
672
|
-
opt_debug = Option.new(:flag :names => %w(--debug -d),)
|
673
|
-
... parse the commandline
|
674
|
-
@debug = option_data[:debug]
|
675
|
-
|
676
|
-
# or
|
677
|
-
|
678
|
-
opt_debug = Option.new(:flag
|
679
|
-
:names => %w(--debug -d),
|
680
|
-
:opt_found => lambda { @debug = true },
|
681
|
-
:opt_not_found => lambda { @debug = false }
|
682
|
-
)
|
683
|
-
# do nothing, variable already set.
|
684
|
-
</pre>
|
685
|
-
<p>
|
686
|
-
I find this much easier to manage that having to worry about setting
|
687
|
-
default behaviour.
|
688
|
-
</p>
|
689
|
-
<h2><a href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a></h2>
|
690
|
-
<p>
|
691
|
-
Once the options are defined, we load them into and <a
|
692
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> and parse
|
693
|
-
the command line. The syntax for creating an <a
|
694
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> object
|
695
|
-
is:
|
696
|
-
</p>
|
697
|
-
<pre>
|
698
|
-
OptionParser.new(opt_or_array_of_opts[, options])
|
699
|
-
</pre>
|
700
|
-
<p>
|
701
|
-
where the only option is for parsing posix:
|
702
|
-
</p>
|
703
|
-
<pre>
|
704
|
-
:posix => true | false (default is false)
|
705
|
-
</pre>
|
706
|
-
<p>
|
707
|
-
If you want to parse posix, you must specify so. <a
|
708
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> will not
|
709
|
-
assume posix mode just because all of the options are posix options. This
|
710
|
-
allows you to use posix only options but not require the strict parsing
|
711
|
-
rules.
|
712
|
-
</p>
|
713
|
-
<p>
|
714
|
-
Some examples of creating an <a
|
715
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> object:
|
716
|
-
</p>
|
717
|
-
<pre>
|
718
|
-
opt = Option.new(:flag, :names => %w(-h))
|
719
|
-
|
720
|
-
op = OptionParser.new(opt, :posix => false)
|
721
|
-
op = OptionParser.new(opt)
|
722
|
-
|
723
|
-
opts = []
|
724
|
-
opts << Option.new(:flag, :names => %w(--help h))
|
725
|
-
opts << Option.new(:flag, :names => %w(--debug d))
|
726
|
-
op = OptionParser.new(opts)
|
727
|
-
|
728
|
-
op = OptionParser.new
|
729
|
-
op << opt
|
730
|
-
op << opts
|
731
|
-
|
732
|
-
# block constructor
|
733
|
-
op = OptionParser.new { |o|
|
734
|
-
o << Option.new(:flag, :names => %w(--debug d))
|
735
|
-
}
|
736
|
-
</pre>
|
737
|
-
<h2>Parsing the Command Line</h2>
|
738
|
-
<p>
|
739
|
-
Parsing the command line is as simple as calling #parse:
|
740
|
-
</p>
|
741
|
-
<pre>
|
742
|
-
opt = Option.new(:flag, :names => %w(-h))
|
743
|
-
op = OptionParser.new(opt)
|
744
|
-
option_data = op.parse
|
745
|
-
</pre>
|
746
|
-
<h2>Option Data</h2>
|
747
|
-
<p>
|
748
|
-
The OptionData is the return value of <a
|
749
|
-
href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a>#parse.
|
750
|
-
The parsing results for each option are accessed with the bracket notation
|
751
|
-
#[].
|
752
|
-
</p>
|
753
|
-
<pre>
|
754
|
-
opt = Option.new(:posix => true,
|
755
|
-
:names => %w(-r),
|
756
|
-
:opt_found => OptionParser::GET_ARGS)
|
757
|
-
od = OptionParser.new(opt, :posix => true).parse(["-rubygems"])
|
758
|
-
od["-r"] #=> "ubygems"
|
759
|
-
|
760
|
-
od = OptionParser.new(opt, :posix => true).parse(["-r", "ubygems"])
|
761
|
-
od["-r"] #=> "ubygems"
|
762
|
-
</pre>
|
763
|
-
<p>
|
764
|
-
But, OptionData is not liberal in that it only stores a reference to an
|
765
|
-
options first name. An option cannot access its parsed values using just
|
766
|
-
any of its names.
|
767
|
-
</p>
|
768
|
-
<pre>
|
769
|
-
od = OptionParser.new { |o|
|
770
|
-
o << Option.new(:flag, :names => %w(--valid --notvalid))
|
771
|
-
o << Option.new(:flag, :names => %w(--first --second))
|
772
|
-
}.parse(%w(--notvalid --second))
|
773
|
-
od["--valid"] #=> true
|
774
|
-
od["--first"] #=> true
|
775
|
-
od["--notvalid"] #=> CommandLine::OptionData::UnknownOptionError
|
776
|
-
od["--second"] #=> CommandLine::OptionData::UnknownOptionError
|
777
|
-
</pre>
|
778
|
-
<h3>Built-in Data Handlers</h3>
|
779
|
-
<p>
|
780
|
-
<a href="/index.cgi/OptionParser/OptionParser.rdoc">OptionParser</a> has
|
781
|
-
built-in data handlers for handling common scenarios. These lambas can save
|
782
|
-
a lot of typing.
|
783
|
-
</p>
|
784
|
-
<p>
|
785
|
-
The first is GET_ARG_ARRAY. This is useful for options that take a variable
|
786
|
-
number of arguments. It returns all the arguments in an array.
|
787
|
-
</p>
|
788
|
-
<pre>
|
789
|
-
# GET_ARG_ARRAY returns all arguments in an array, even if no
|
790
|
-
# arguments are present. This is not to be confused with the option
|
791
|
-
# occuring multiple times on the command line.
|
792
|
-
opt = Option.new(:names => %w(--file),
|
793
|
-
:argument_arity => [0-1],
|
794
|
-
:opt_found => OptionParser::GET_ARG_ARRAY)
|
795
|
-
od = OptionParser.new(opt).parse(%w(--file))
|
796
|
-
od["--file"] #=> []
|
797
|
-
od = OptionParser.new(opt).parse(%w(--file=file))
|
798
|
-
od["--file"] #=> ["file"]
|
799
|
-
od = OptionParser.new(opt).parse(%w(--file=file1 --file file2))
|
800
|
-
od["--file"] #=> ["file2"]
|
801
|
-
od = OptionParser.new(opt).parse(%w(--file=file1 file2))
|
802
|
-
od["--file"] #=> ["file1", "file2"]
|
803
|
-
od = OptionParser.new(opt).parse(%w(--file file1 file2))
|
804
|
-
od["--file"] #=> ["file1", "file2"]
|
805
|
-
</pre>
|
806
|
-
<p>
|
807
|
-
The next is GET_ARGS. This is a ‘smart’ option getter. If no
|
808
|
-
arguments are found, it returns true. If a single argument is found, it
|
809
|
-
returns that argument. If more than one argument is found, it returns an
|
810
|
-
array of those arguments.
|
811
|
-
</p>
|
812
|
-
<pre>
|
813
|
-
opt = Option.new(:names => %w(--file),
|
814
|
-
:argument_arity => [0-1],
|
815
|
-
:opt_found => OptionParser::GET_ARGS)
|
816
|
-
od = OptionParser.new(opt).parse(%w(--file))
|
817
|
-
od["--file"] #=> true
|
818
|
-
od = OptionParser.new(opt).parse(%w(--file=file))
|
819
|
-
od["--file"] #=> "file"
|
820
|
-
od = OptionParser.new(opt).parse(%w(--file=file1 --file file2))
|
821
|
-
od["--file"] #=> "file2"
|
822
|
-
od = OptionParser.new(opt).parse(%w(--file=file1 file2))
|
823
|
-
od["--file"] #=> ["file1", "file2"]
|
824
|
-
od = OptionParser.new(opt).parse(%w(--file file1 file2))
|
825
|
-
od["--file"] #=> ["file1", "file2"]
|
826
|
-
</pre>
|
827
|
-
<p>
|
828
|
-
And, for those oxymoronic non-optional options:
|
829
|
-
</p>
|
830
|
-
<pre>
|
831
|
-
opt = Option.new(:names => %w(--not-really-an-option),
|
832
|
-
:opt_not_found => OptionParser::OPT_NOT_FOUND_BUT_REQUIRED
|
833
|
-
)
|
834
|
-
OptionParser.new(opt).parse([]) #=> OptionParser::MissingRequiredOptionError
|
835
|
-
</pre>
|
836
|
-
<h3>OptionData</h3>
|
837
|
-
<p>
|
838
|
-
We have just shown that after parsing a command line, the result of each
|
839
|
-
option is found from OptionData. The vaues that are left are assigned to
|
840
|
-
<tt>args</tt>. And, the first argument can be a command if so desired.
|
841
|
-
</p>
|
842
1000
|
|
843
1001
|
</td></tr>
|
844
1002
|
</table>
|
1003
|
+
</table>
|
845
1004
|
</body>
|
846
1005
|
</html>
|
data/lib/commandline.rb
ADDED
metadata
CHANGED
@@ -3,16 +3,16 @@ rubygems_version: 0.8.10
|
|
3
3
|
specification_version: 1
|
4
4
|
name: OptionParser
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.5.
|
7
|
-
date: 2005-06-
|
6
|
+
version: 0.5.1
|
7
|
+
date: 2005-06-17
|
8
8
|
summary: A flexible command line option parser.
|
9
9
|
require_paths:
|
10
|
-
- lib
|
11
|
-
email:
|
12
|
-
homepage: http://
|
10
|
+
- lib
|
11
|
+
email: optionparser@freeze.org
|
12
|
+
homepage: http://rubyforge.org/projects/optionparser/
|
13
13
|
rubyforge_project:
|
14
14
|
description:
|
15
|
-
autorequire: optionparser
|
15
|
+
autorequire: commandline/optionparser
|
16
16
|
default_executable:
|
17
17
|
bindir: bin
|
18
18
|
has_rdoc: true
|
@@ -27,9 +27,9 @@ platform: ruby
|
|
27
27
|
authors:
|
28
28
|
- Jim Freeze
|
29
29
|
files:
|
30
|
-
- docs/api
|
31
30
|
- docs/index.html
|
32
31
|
- lib/commandline
|
32
|
+
- lib/commandline.rb
|
33
33
|
- lib/commandline/optionparser
|
34
34
|
- lib/commandline/optionparser.rb
|
35
35
|
- lib/commandline/text
|
@@ -38,12 +38,12 @@ files:
|
|
38
38
|
- lib/commandline/optionparser/optionparser.rb
|
39
39
|
- lib/commandline/text/format.rb
|
40
40
|
- README
|
41
|
-
|
42
|
-
|
43
|
-
- test/tc_option.rb
|
41
|
+
- LICENSE
|
42
|
+
test_files: []
|
44
43
|
rdoc_options: []
|
45
44
|
extra_rdoc_files:
|
46
45
|
- README
|
46
|
+
- LICENSE
|
47
47
|
executables: []
|
48
48
|
extensions: []
|
49
49
|
requirements: []
|
data/test/tc_option.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
# $Id$
|
2
|
-
# $Source$
|
3
|
-
#
|
4
|
-
# Author: Jim Freeze
|
5
|
-
# Copyright (c) 2005
|
6
|
-
#
|
7
|
-
# =DESCRIPTION
|
8
|
-
# Test cases for Option Class
|
9
|
-
#
|
10
|
-
# =Revision History
|
11
|
-
# Jim.Freeze 2005/04/02 Birthday
|
12
|
-
#
|
13
|
-
|
14
|
-
require 'test/unit'
|
15
|
-
require 'commandline/optionparser'
|
16
|
-
|
17
|
-
class TC_Option < Test::Unit::TestCase
|
18
|
-
include CommandLine
|
19
|
-
|
20
|
-
def test_flag_parameters
|
21
|
-
opt = Option.new(:flag, :names => "-h")
|
22
|
-
assert_equal(%w(-h), opt.names)
|
23
|
-
assert_equal([0,0], opt.arg_arity)
|
24
|
-
assert_equal("", opt.opt_description)
|
25
|
-
assert_equal("", opt.arg_description)
|
26
|
-
assert_equal(true, opt.opt_found)
|
27
|
-
assert_equal(false, opt.opt_not_found)
|
28
|
-
assert_equal(false, opt.posix)
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_posix
|
32
|
-
op = Option.new(:flag, :posix, :names => %w(-))
|
33
|
-
assert_equal(true, op.posix)
|
34
|
-
op = Option.new(:flag, :names => %w(-))
|
35
|
-
assert_equal(false, op.posix)
|
36
|
-
|
37
|
-
assert_raises(CommandLine::Option::InvalidOptionNameError) {
|
38
|
-
Option.new(:flag, :posix, :names => %w(--help))
|
39
|
-
}
|
40
|
-
assert_raises(CommandLine::Option::InvalidOptionNameError) {
|
41
|
-
Option.new(:flag, :posix, :names => %w(-help))
|
42
|
-
}
|
43
|
-
assert_nothing_raised {
|
44
|
-
Option.new(:flag, :posix, :names => %w(-h))
|
45
|
-
}
|
46
|
-
assert_nothing_raised {
|
47
|
-
Option.new(:flag, :posix, :names => %w(-H))
|
48
|
-
}
|
49
|
-
assert_nothing_raised {
|
50
|
-
Option.new(:flag, :posix, :names => %w(-))
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_no_dash_name
|
55
|
-
assert_raises(CommandLine::Option::InvalidOptionNameError) {
|
56
|
-
Option.new(:flag, :names => ["fred"])
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_flag_constructor
|
61
|
-
opt = nil
|
62
|
-
assert_nothing_raised { opt = Option.new(:flag, :names => %w(--debug -d) ) }
|
63
|
-
assert_equal("Sets debug to true.", opt.opt_description)
|
64
|
-
|
65
|
-
opt = Option.new(:flag,
|
66
|
-
:names => %w(--debug -d),
|
67
|
-
:opt_description => ""
|
68
|
-
)
|
69
|
-
assert_equal("", opt.opt_description)
|
70
|
-
|
71
|
-
opt = Option.new(:flag,
|
72
|
-
:names => %w(--debug -d),
|
73
|
-
:opt_description => "Custom description"
|
74
|
-
)
|
75
|
-
assert_equal("Custom description", opt.opt_description)
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_block_constructor
|
79
|
-
assert_raises(CommandLine::Option::MissingPropertyError) {
|
80
|
-
opt = Option.new { |opp| opp.names = %w(--fred -f) }
|
81
|
-
}
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_no_arity
|
85
|
-
opt = nil
|
86
|
-
assert_nothing_raised { opt = Option.new(:flag, :names => %w(--debug -d) ) }
|
87
|
-
assert_equal([0,0], opt.arg_arity)
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_arity_is_number
|
91
|
-
opt = nil
|
92
|
-
assert_nothing_raised { opt =
|
93
|
-
Option.new(:names => %w(--debug -d),
|
94
|
-
:arg_arity => 1) }
|
95
|
-
assert_equal([1,1], opt.arg_arity)
|
96
|
-
|
97
|
-
opt = nil
|
98
|
-
assert_nothing_raised { opt =
|
99
|
-
Option.new(:names => %w(--debug -d),
|
100
|
-
:arg_arity => 2) }
|
101
|
-
assert_equal([2,2], opt.arg_arity)
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_names_not_array
|
105
|
-
op = nil
|
106
|
-
assert_nothing_raised { op = Option.new(:flag, :names => "-fred") }
|
107
|
-
assert_equal(["-fred"], op.names)
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_incompatible_properties
|
111
|
-
assert_raises(CommandLine::Option::InvalidArgumentArityError) {
|
112
|
-
opt = Option.new(:flag, :names => "-a", :arg_arity => 1) }
|
113
|
-
assert_raises(CommandLine::Option::InvalidArgumentArityError) {
|
114
|
-
Option.new(:flag, :names => "-b", :arg_arity => 1) }
|
115
|
-
|
116
|
-
assert_raises(CommandLine::Option::InvalidOptionNameError) {
|
117
|
-
Option.new(:posix, :names => "--fred") }
|
118
|
-
end
|
119
|
-
|
120
|
-
|
121
|
-
end#class TC_Option
|
data/test/testall.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
|
4
|
-
|
5
|
-
require 'commandline/optionparser'
|
6
|
-
|
7
|
-
#tc = %w( tc_option.rb tc_optionparser.rb tc_optiondata.rb )
|
8
|
-
tc = Dir["tc_*rb"]
|
9
|
-
|
10
|
-
tc.each { |lib|
|
11
|
-
fork {
|
12
|
-
require lib
|
13
|
-
#puts "===> Testing #{lib}"
|
14
|
-
}
|
15
|
-
}
|
16
|
-
|