trollop 2.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +5 -0
- data/FAQ.txt +0 -3
- data/Gemfile +4 -0
- data/History.txt +15 -0
- data/README.md +57 -0
- data/Rakefile +12 -0
- data/lib/trollop.rb +90 -32
- data/test/test_helper.rb +23 -0
- data/test/test_trollop.rb +190 -18
- data/trollop.gemspec +33 -0
- metadata +128 -25
- data/README.txt +0 -50
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: be70256e210067fa6547103ba32b51a4242a6382
|
4
|
+
data.tar.gz: 958ed3d139b74b319cf793208d7482c634663fbc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 36ba799aa516cf9160cfce8809c45939bdfef580dac0f30f8c8bac85f6e1e1a13bd0f786eb7b8da79006a4f4677bd2e8bb036262a917db9ab5714c2910f5789c
|
7
|
+
data.tar.gz: 6ffcdcf7434e5182eb8aca04cf1fbcdfd63d65e5af5a9b360e80a72c7a18ff39f45a7afe4fa429796ba6d1f297d28b1abbc32caf360f8a7a73643c06b7d84fb5
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/FAQ.txt
CHANGED
data/Gemfile
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
== 2.1.0 / 2014-12-23
|
2
|
+
* Integer parser now supports underscore separator.
|
3
|
+
* Add Parser#usage and Parser#synopsis commands for creating a standard banner
|
4
|
+
message. Using Parser#banner directly will override both of those.
|
5
|
+
* Add Parser#ignore_invalid_options to prevent erroring on unknown options.
|
6
|
+
* Allow flags to act as switches if they have defaults set and no value is
|
7
|
+
passed on the commandline
|
8
|
+
* Parser#opt learned to accept a block or a :callback option which it will call
|
9
|
+
after parsing the option.
|
10
|
+
* Add Trollop::educate which displays the help message and dies.
|
11
|
+
* Reformat help message to be more GNUish.
|
12
|
+
* Fix command name in help message when script has no extension.
|
13
|
+
* Fix handling of newlines inside descriptions
|
14
|
+
* Documentation and other fixes.
|
15
|
+
|
1
16
|
== 2.0 / 2012-08-11
|
2
17
|
* Change flag logic: --no-X will always be false, and --X will always be true,
|
3
18
|
regardless of default.
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# trollop
|
2
|
+
|
3
|
+
http://manageiq.github.io/trollop/
|
4
|
+
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/trollop.svg)](http://badge.fury.io/rb/trollop)
|
6
|
+
[![Build Status](https://travis-ci.org/ManageIQ/trollop.svg)](https://travis-ci.org/ManageIQ/trollop)
|
7
|
+
[![Code Climate](https://codeclimate.com/github/ManageIQ/trollop/badges/gpa.svg)](https://codeclimate.com/github/ManageIQ/trollop)
|
8
|
+
[![Coverage Status](http://img.shields.io/coveralls/ManageIQ/trollop.svg)](https://coveralls.io/r/ManageIQ/trollop)
|
9
|
+
[![Dependency Status](https://gemnasium.com/ManageIQ/trollop.svg)](https://gemnasium.com/ManageIQ/trollop)
|
10
|
+
|
11
|
+
Documentation quickstart: See Trollop.options and then Trollop::Parser#opt.
|
12
|
+
Also see the examples at http://manageiq.github.io/trollop/.
|
13
|
+
|
14
|
+
## Description
|
15
|
+
|
16
|
+
Trollop is a commandline option parser for Ruby that just gets out of your way.
|
17
|
+
One line of code per option is all you need to write. For that, you get a nice
|
18
|
+
automatically-generated help page, robust option parsing, and sensible defaults
|
19
|
+
for everything you don't specify.
|
20
|
+
|
21
|
+
## Features
|
22
|
+
|
23
|
+
- Dirt-simple usage.
|
24
|
+
- Single file. Throw it in lib/ if you don't want to make it a Rubygem dependency.
|
25
|
+
- Sensible defaults. No tweaking necessary, much tweaking possible.
|
26
|
+
- Support for long options, short options, subcommands, and automatic type validation and
|
27
|
+
conversion.
|
28
|
+
- Automatic help message generation, wrapped to current screen width.
|
29
|
+
|
30
|
+
## Requirements
|
31
|
+
|
32
|
+
* A burning desire to write less code.
|
33
|
+
|
34
|
+
## Install
|
35
|
+
|
36
|
+
* gem install trollop
|
37
|
+
|
38
|
+
## Synopsis
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
require 'trollop'
|
42
|
+
opts = Trollop::options do
|
43
|
+
opt :monkey, "Use monkey mode" # flag --monkey, default false
|
44
|
+
opt :name, "Monkey name", :type => :string # string --name <s>, default nil
|
45
|
+
opt :num_limbs, "Number of limbs", :default => 4 # integer --num-limbs <i>, default to 4
|
46
|
+
end
|
47
|
+
|
48
|
+
p opts # a hash: { :monkey=>false, :name=>nil, :num_limbs=>4, :help=>false }
|
49
|
+
```
|
50
|
+
|
51
|
+
## License
|
52
|
+
|
53
|
+
Copyright © 2008-2014 [William Morgan](http://masanjin.net/).
|
54
|
+
|
55
|
+
Copyright © 2014 Red Hat, Inc.
|
56
|
+
|
57
|
+
Trollop is licensed under the same terms as Ruby.
|
data/Rakefile
ADDED
data/lib/trollop.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# lib/trollop.rb -- trollop command-line processing library
|
2
|
+
# Copyright (c) 2008-2014 William Morgan.
|
3
|
+
# Copyright (c) 2014 Red Hat, Inc.
|
4
|
+
# trollop is licensed under the same terms as Ruby.
|
5
5
|
|
6
6
|
require 'date'
|
7
7
|
|
8
8
|
module Trollop
|
9
|
-
|
10
|
-
VERSION = "2.0"
|
9
|
+
VERSION = "2.1.0"
|
11
10
|
|
12
11
|
## Thrown by Parser in the event of a commandline error. Not needed if
|
13
12
|
## you're using the Trollop::options entry.
|
@@ -17,7 +16,7 @@ class CommandlineError < StandardError; end
|
|
17
16
|
## automatically by Trollop#options.
|
18
17
|
class HelpNeeded < StandardError; end
|
19
18
|
|
20
|
-
## Thrown by Parser if the user passes in '-
|
19
|
+
## Thrown by Parser if the user passes in '-v' or '--version'. Handled
|
21
20
|
## automatically by Trollop#options.
|
22
21
|
class VersionNeeded < StandardError; end
|
23
22
|
|
@@ -66,6 +65,11 @@ class Parser
|
|
66
65
|
## for testing.)
|
67
66
|
attr_reader :specs
|
68
67
|
|
68
|
+
## A flag that determines whether or not to raise an error if the parser is passed one or more
|
69
|
+
## options that were not registered ahead of time. If 'true', then the parser will simply
|
70
|
+
## ignore options that it does not recognize.
|
71
|
+
attr_accessor :ignore_invalid_options
|
72
|
+
|
69
73
|
## Initializes the parser, and instance-evaluates any block given.
|
70
74
|
def initialize *a, &b
|
71
75
|
@version = nil
|
@@ -122,7 +126,7 @@ class Parser
|
|
122
126
|
## If you want a multi-value, multi-occurrence argument with a default
|
123
127
|
## value, you must specify +:type+ as well.
|
124
128
|
|
125
|
-
def opt name, desc="", opts={}
|
129
|
+
def opt name, desc="", opts={}, &b
|
126
130
|
raise ArgumentError, "you already have an argument named '#{name}'" if @specs.member? name
|
127
131
|
|
128
132
|
## fill in :type
|
@@ -220,7 +224,7 @@ class Parser
|
|
220
224
|
|
221
225
|
## fill in :multi
|
222
226
|
opts[:multi] ||= false
|
223
|
-
|
227
|
+
opts[:callback] ||= b if block_given?
|
224
228
|
opts[:desc] ||= desc
|
225
229
|
@long[opts[:long]] = name
|
226
230
|
@short[opts[:short]] = name if opts[:short] && opts[:short] != :none
|
@@ -233,6 +237,20 @@ class Parser
|
|
233
237
|
## <version number>".
|
234
238
|
def version s=nil; @version = s if s; @version end
|
235
239
|
|
240
|
+
## Sets the usage string. If set the message will be printed as the
|
241
|
+
## first line in the help (educate) output and ending in two new
|
242
|
+
## lines.
|
243
|
+
def usage s=nil; @usage = s if s; @usage end
|
244
|
+
|
245
|
+
## Sets the usage string. If set the message will be printed as the
|
246
|
+
## first line in the help (educate) output and ending in two new
|
247
|
+
## lines.
|
248
|
+
def usage s=nil; @usage = s if s; @usage end
|
249
|
+
|
250
|
+
## Adds a synopsis (command summary description) right below the
|
251
|
+
## usage line, or as the first line if usage isn't specified.
|
252
|
+
def synopsis s=nil; @synopsis = s if s; @synopsis end
|
253
|
+
|
236
254
|
## Adds text to the help display. Can be interspersed with calls to
|
237
255
|
## #opt to build a multi-section help page.
|
238
256
|
def banner s; @order << [:text, s] end
|
@@ -245,7 +263,7 @@ class Parser
|
|
245
263
|
syms.each { |sym| raise ArgumentError, "unknown option '#{sym}'" unless @specs[sym] }
|
246
264
|
@constraints << [:depends, syms]
|
247
265
|
end
|
248
|
-
|
266
|
+
|
249
267
|
## Marks two (or more!) options as conflicting.
|
250
268
|
def conflicts *syms
|
251
269
|
syms.each { |sym| raise ArgumentError, "unknown option '#{sym}'" unless @specs[sym] }
|
@@ -310,7 +328,10 @@ class Parser
|
|
310
328
|
|
311
329
|
sym = nil if arg =~ /--no-/ # explicitly invalidate --no-no- arguments
|
312
330
|
|
313
|
-
|
331
|
+
unless sym
|
332
|
+
next 0 if ignore_invalid_options
|
333
|
+
raise CommandlineError, "unknown argument '#{arg}'" unless sym
|
334
|
+
end
|
314
335
|
|
315
336
|
if given_args.include?(sym) && !@specs[sym][:multi]
|
316
337
|
raise CommandlineError, "option '#{arg}' specified multiple times"
|
@@ -363,7 +384,10 @@ class Parser
|
|
363
384
|
arg, params, negative_given = given_data.values_at :arg, :params, :negative_given
|
364
385
|
|
365
386
|
opts = @specs[sym]
|
366
|
-
|
387
|
+
if params.empty? && opts[:type] != :flag
|
388
|
+
raise CommandlineError, "option '#{arg}' needs a parameter" unless opts[:default]
|
389
|
+
params << [opts[:default]]
|
390
|
+
end
|
367
391
|
|
368
392
|
vals["#{sym}_given".intern] = true # mark argument as specified on the commandline
|
369
393
|
|
@@ -392,6 +416,8 @@ class Parser
|
|
392
416
|
vals[sym] = vals[sym][0] # single option, with multiple parameters
|
393
417
|
end
|
394
418
|
# else: multiple options, with multiple parameters
|
419
|
+
|
420
|
+
opts[:callback].call(vals[sym]) if opts.has_key?(:callback)
|
395
421
|
end
|
396
422
|
|
397
423
|
## modify input in place with only those
|
@@ -411,6 +437,7 @@ class Parser
|
|
411
437
|
def parse_date_parameter param, arg #:nodoc:
|
412
438
|
begin
|
413
439
|
begin
|
440
|
+
require 'chronic'
|
414
441
|
time = Chronic.parse(param)
|
415
442
|
rescue NameError
|
416
443
|
# chronic is not available
|
@@ -427,28 +454,33 @@ class Parser
|
|
427
454
|
# call this unless the cursor's at the beginning of a line.
|
428
455
|
left = {}
|
429
456
|
@specs.each do |name, spec|
|
430
|
-
left[name] =
|
431
|
-
(spec[:
|
432
|
-
(spec[:short] && spec[:short] != :none ? ",
|
457
|
+
left[name] =
|
458
|
+
(spec[:short] && spec[:short] != :none ? "-#{spec[:short]}" : "") +
|
459
|
+
(spec[:short] && spec[:short] != :none ? ", " : "") + "--#{spec[:long]}" +
|
433
460
|
case spec[:type]
|
434
461
|
when :flag; ""
|
435
|
-
when :int; "
|
436
|
-
when :ints; "
|
437
|
-
when :string; "
|
438
|
-
when :strings; "
|
439
|
-
when :float; "
|
440
|
-
when :floats; "
|
441
|
-
when :io; "
|
442
|
-
when :ios; "
|
443
|
-
when :date; "
|
444
|
-
when :dates; "
|
445
|
-
end
|
462
|
+
when :int; "=<i>"
|
463
|
+
when :ints; "=<i+>"
|
464
|
+
when :string; "=<s>"
|
465
|
+
when :strings; "=<s+>"
|
466
|
+
when :float; "=<f>"
|
467
|
+
when :floats; "=<f+>"
|
468
|
+
when :io; "=<filename/uri>"
|
469
|
+
when :ios; "=<filename/uri+>"
|
470
|
+
when :date; "=<date>"
|
471
|
+
when :dates; "=<date+>"
|
472
|
+
end +
|
473
|
+
(spec[:type] == :flag && spec[:default] ? ", --no-#{spec[:long]}" : "")
|
446
474
|
end
|
447
475
|
|
448
476
|
leftcol_width = left.values.map { |s| s.length }.max || 0
|
449
477
|
rightcol_start = leftcol_width + 6 # spaces
|
450
478
|
|
451
479
|
unless @order.size > 0 && @order.first.first == :text
|
480
|
+
command_name = File.basename($0).gsub /\.[^.]+$/, ''
|
481
|
+
stream.puts "Usage: #{command_name} #@usage\n" if @usage
|
482
|
+
stream.puts "#@synopsis\n" if @synopsis
|
483
|
+
stream.puts if @usage or @synopsis
|
452
484
|
stream.puts "#@version\n" if @version
|
453
485
|
stream.puts "Options:"
|
454
486
|
end
|
@@ -460,7 +492,7 @@ class Parser
|
|
460
492
|
end
|
461
493
|
|
462
494
|
spec = @specs[opt]
|
463
|
-
stream.printf "
|
495
|
+
stream.printf " %-#{leftcol_width}s ", left[opt]
|
464
496
|
desc = spec[:desc] + begin
|
465
497
|
default_s = case spec[:default]
|
466
498
|
when $stdout; "<stdout>"
|
@@ -506,7 +538,12 @@ class Parser
|
|
506
538
|
if str == ""
|
507
539
|
[""]
|
508
540
|
else
|
509
|
-
|
541
|
+
inner = false
|
542
|
+
str.split("\n").map do |s|
|
543
|
+
line = wrap_line s, opts.merge(:inner => inner)
|
544
|
+
inner = true
|
545
|
+
line
|
546
|
+
end.flatten
|
510
547
|
end
|
511
548
|
end
|
512
549
|
|
@@ -596,7 +633,7 @@ private
|
|
596
633
|
end
|
597
634
|
|
598
635
|
def parse_integer_parameter param, arg
|
599
|
-
raise CommandlineError, "option '#{arg}' needs an integer" unless param =~
|
636
|
+
raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^-?[\d_]+$/
|
600
637
|
param.to_i
|
601
638
|
end
|
602
639
|
|
@@ -648,7 +685,7 @@ private
|
|
648
685
|
start = 0
|
649
686
|
ret = []
|
650
687
|
until start > str.length
|
651
|
-
nextt =
|
688
|
+
nextt =
|
652
689
|
if start + width >= str.length
|
653
690
|
str.length
|
654
691
|
else
|
@@ -656,7 +693,7 @@ private
|
|
656
693
|
x = str.index(/\s/, start) if x && x < start
|
657
694
|
x || str.length
|
658
695
|
end
|
659
|
-
ret << (ret.empty? ? "" : " " * prefix) + str[start ... nextt]
|
696
|
+
ret << ((ret.empty? && !opts[:inner]) ? "" : " " * prefix) + str[start ... nextt]
|
660
697
|
start = nextt + 1
|
661
698
|
end
|
662
699
|
ret
|
@@ -777,6 +814,27 @@ def die arg, msg=nil
|
|
777
814
|
end
|
778
815
|
end
|
779
816
|
|
780
|
-
|
817
|
+
## Displays the help message and dies. Example:
|
818
|
+
##
|
819
|
+
## options do
|
820
|
+
## opt :volume, :default => 0.0
|
821
|
+
## banner <<-EOS
|
822
|
+
## Usage:
|
823
|
+
## #$0 [options] <name>
|
824
|
+
## where [options] are:
|
825
|
+
## EOS
|
826
|
+
## end
|
827
|
+
##
|
828
|
+
## Trollop::educate if ARGV.empty?
|
829
|
+
def educate
|
830
|
+
if @last_parser
|
831
|
+
@last_parser.educate
|
832
|
+
exit
|
833
|
+
else
|
834
|
+
raise ArgumentError, "Trollop::educate can only be called after Trollop::options"
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
838
|
+
module_function :options, :die, :educate, :with_standard_exception_handling
|
781
839
|
|
782
840
|
end # module
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
unless ENV['MUTANT']
|
4
|
+
require "coveralls"
|
5
|
+
require "simplecov"
|
6
|
+
|
7
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
8
|
+
Coveralls::SimpleCov::Formatter,
|
9
|
+
SimpleCov::Formatter::HTMLFormatter,
|
10
|
+
]
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
begin
|
15
|
+
require "pry"
|
16
|
+
rescue LoadError
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'test/unit'
|
20
|
+
|
21
|
+
SimpleCov.start unless ENV['MUTANT']
|
22
|
+
|
23
|
+
require 'trollop'
|
data/test/test_trollop.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
## test/test_trollop.rb -- unit tests for trollop
|
2
|
-
## Author:: William Morgan (mailto: wmorgan-trollop@masanjin.net)
|
3
|
-
## Copyright:: Copyright 2007 William Morgan
|
4
|
-
## License:: GNU GPL version 2
|
5
|
-
|
6
|
-
require 'rubygems'
|
7
|
-
require 'test/unit'
|
8
1
|
require 'stringio'
|
9
|
-
|
2
|
+
require_relative 'test_helper'
|
10
3
|
|
11
4
|
module Trollop
|
12
5
|
module Test
|
@@ -16,6 +9,11 @@ class Trollop < ::Test::Unit::TestCase
|
|
16
9
|
@p = Parser.new
|
17
10
|
end
|
18
11
|
|
12
|
+
def test_die_without_options_ever_run
|
13
|
+
::Trollop.send(:instance_variable_set, "@last_parser", nil)
|
14
|
+
assert_raise(ArgumentError) { ::Trollop.die 'hello' }
|
15
|
+
end
|
16
|
+
|
19
17
|
def test_unknown_arguments
|
20
18
|
assert_raise(CommandlineError) { @p.parse(%w(--arg)) }
|
21
19
|
@p.opt "arg"
|
@@ -78,6 +76,8 @@ class Trollop < ::Test::Unit::TestCase
|
|
78
76
|
## type is correctly derived from :default
|
79
77
|
def test_type_correctly_derived_from_default
|
80
78
|
assert_raise(ArgumentError) { @p.opt "badarg", "desc", :default => [] }
|
79
|
+
assert_raise(ArgumentError) { @p.opt "badarg3", "desc", :default => [{1 => 2}] }
|
80
|
+
assert_raise(ArgumentError) { @p.opt "badarg4", "desc", :default => Hash.new }
|
81
81
|
|
82
82
|
opts = nil
|
83
83
|
|
@@ -87,6 +87,11 @@ class Trollop < ::Test::Unit::TestCase
|
|
87
87
|
assert_equal 0, opts["argsi"]
|
88
88
|
assert_nothing_raised { opts = @p.parse(%w(--argsi 4)) }
|
89
89
|
assert_equal 4, opts["argsi"]
|
90
|
+
assert_nothing_raised { opts = @p.parse(%w(--argsi=4)) }
|
91
|
+
assert_equal 4, opts["argsi"]
|
92
|
+
assert_nothing_raised { opts = @p.parse(%w(--argsi=-4)) }
|
93
|
+
assert_equal -4, opts["argsi"]
|
94
|
+
|
90
95
|
assert_raise(CommandlineError) { @p.parse(%w(--argsi 4.2)) }
|
91
96
|
assert_raise(CommandlineError) { @p.parse(%w(--argsi hello)) }
|
92
97
|
|
@@ -156,7 +161,7 @@ class Trollop < ::Test::Unit::TestCase
|
|
156
161
|
assert_equal ["3.4"], opts["argmst"]
|
157
162
|
assert_nothing_raised { opts = @p.parse(%w(--argmst goodbye)) }
|
158
163
|
assert_equal ["goodbye"], opts["argmst"]
|
159
|
-
end
|
164
|
+
end
|
160
165
|
|
161
166
|
## :type and :default must match if both are specified
|
162
167
|
def test_type_and_default_must_match
|
@@ -175,6 +180,26 @@ class Trollop < ::Test::Unit::TestCase
|
|
175
180
|
assert_nothing_raised { @p.opt "argmst", "desc", :type => :strings, :default => ["yo"] }
|
176
181
|
end
|
177
182
|
|
183
|
+
##
|
184
|
+
def test_flags_with_defaults_and_no_args_act_as_switches
|
185
|
+
opts = nil
|
186
|
+
|
187
|
+
@p.opt :argd, "desc", :default => "default_string"
|
188
|
+
|
189
|
+
opts = @p.parse(%w(--))
|
190
|
+
assert !opts[:argd_given]
|
191
|
+
assert_equal "default_string", opts[:argd]
|
192
|
+
|
193
|
+
opts = @p.parse(%w( --argd ))
|
194
|
+
assert opts[:argd_given]
|
195
|
+
assert_equal "default_string", opts[:argd]
|
196
|
+
|
197
|
+
opts = @p.parse(%w(--argd different_string))
|
198
|
+
assert opts[:argd_given]
|
199
|
+
assert_equal "different_string", opts[:argd]
|
200
|
+
|
201
|
+
end
|
202
|
+
|
178
203
|
def test_long_detects_bad_names
|
179
204
|
assert_nothing_raised { @p.opt "goodarg", "desc", :long => "none" }
|
180
205
|
assert_nothing_raised { @p.opt "goodarg2", "desc", :long => "--two" }
|
@@ -233,7 +258,7 @@ class Trollop < ::Test::Unit::TestCase
|
|
233
258
|
|
234
259
|
sio = StringIO.new "w"
|
235
260
|
@p.educate sio
|
236
|
-
assert sio.string =~ /--arg
|
261
|
+
assert sio.string =~ /--arg\s+desc/
|
237
262
|
|
238
263
|
assert_raise(CommandlineError) { @p.parse %w(-a) }
|
239
264
|
end
|
@@ -387,6 +412,20 @@ where [options] are:
|
|
387
412
|
EOM
|
388
413
|
end
|
389
414
|
|
415
|
+
def test_multi_line_description
|
416
|
+
out = StringIO.new
|
417
|
+
@p.opt :arg, <<-EOM, :type => :int
|
418
|
+
This is an arg
|
419
|
+
with a multi-line description
|
420
|
+
EOM
|
421
|
+
@p.educate(out)
|
422
|
+
assert_equal <<-EOM, out.string
|
423
|
+
Options:
|
424
|
+
--arg=<i> This is an arg
|
425
|
+
with a multi-line description
|
426
|
+
EOM
|
427
|
+
end
|
428
|
+
|
390
429
|
def test_floating_point_formatting
|
391
430
|
@p.opt :arg, "desc", :type => :float, :short => "f"
|
392
431
|
opts = nil
|
@@ -422,13 +461,8 @@ EOM
|
|
422
461
|
opts = nil
|
423
462
|
assert_nothing_raised { opts = @p.parse(['-d', 'Jan 4, 2007']) }
|
424
463
|
assert_equal Date.civil(2007, 1, 4), opts[:arg]
|
425
|
-
|
426
|
-
|
427
|
-
assert_nothing_raised { opts = @p.parse(['-d', 'today']) }
|
428
|
-
assert_equal Date.today, opts[:arg]
|
429
|
-
rescue LoadError
|
430
|
-
# chronic is not available
|
431
|
-
end
|
464
|
+
assert_nothing_raised { opts = @p.parse(['-d', 'today']) }
|
465
|
+
assert_equal Date.today, opts[:arg]
|
432
466
|
end
|
433
467
|
|
434
468
|
def test_short_options_cant_be_numeric
|
@@ -471,7 +505,7 @@ EOM
|
|
471
505
|
assert_equal [], @p.leftovers
|
472
506
|
end
|
473
507
|
|
474
|
-
def
|
508
|
+
def test_short_options_with_multiple_options_does_not_affect_flags_type
|
475
509
|
opts = nil
|
476
510
|
|
477
511
|
assert_nothing_raised do
|
@@ -674,6 +708,41 @@ EOM
|
|
674
708
|
assert_equal 2, help.length # banner, -h
|
675
709
|
end
|
676
710
|
|
711
|
+
def test_help_has_optional_usage
|
712
|
+
@p = Parser.new
|
713
|
+
@p.usage "OPTIONS FILES"
|
714
|
+
sio = StringIO.new "w"
|
715
|
+
@p.parse []
|
716
|
+
@p.educate sio
|
717
|
+
help = sio.string.split "\n"
|
718
|
+
assert help[0] =~ /OPTIONS FILES/i
|
719
|
+
assert_equal 4, help.length # line break, options, then -h
|
720
|
+
end
|
721
|
+
|
722
|
+
def test_help_has_optional_synopsis
|
723
|
+
@p = Parser.new
|
724
|
+
@p.synopsis "About this program"
|
725
|
+
sio = StringIO.new "w"
|
726
|
+
@p.parse []
|
727
|
+
@p.educate sio
|
728
|
+
help = sio.string.split "\n"
|
729
|
+
assert help[0] =~ /About this program/i
|
730
|
+
assert_equal 4, help.length # line break, options, then -h
|
731
|
+
end
|
732
|
+
|
733
|
+
def test_help_has_specific_order_for_usage_and_synopsis
|
734
|
+
@p = Parser.new
|
735
|
+
@p.usage "OPTIONS FILES"
|
736
|
+
@p.synopsis "About this program"
|
737
|
+
sio = StringIO.new "w"
|
738
|
+
@p.parse []
|
739
|
+
@p.educate sio
|
740
|
+
help = sio.string.split "\n"
|
741
|
+
assert help[0] =~ /OPTIONS FILES/i
|
742
|
+
assert help[1] =~ /About this program/i
|
743
|
+
assert_equal 5, help.length # line break, options, then -h
|
744
|
+
end
|
745
|
+
|
677
746
|
def test_help_preserves_positions
|
678
747
|
@p.opt :zzz, "zzz"
|
679
748
|
@p.opt :aaa, "aaa"
|
@@ -685,6 +754,44 @@ EOM
|
|
685
754
|
assert help[2] =~ /aaa/
|
686
755
|
end
|
687
756
|
|
757
|
+
def test_help_includes_option_types
|
758
|
+
@p.opt :arg1, 'arg', :type => :int
|
759
|
+
@p.opt :arg2, 'arg', :type => :ints
|
760
|
+
@p.opt :arg3, 'arg', :type => :string
|
761
|
+
@p.opt :arg4, 'arg', :type => :strings
|
762
|
+
@p.opt :arg5, 'arg', :type => :float
|
763
|
+
@p.opt :arg6, 'arg', :type => :floats
|
764
|
+
@p.opt :arg7, 'arg', :type => :io
|
765
|
+
@p.opt :arg8, 'arg', :type => :ios
|
766
|
+
@p.opt :arg9, 'arg', :type => :date
|
767
|
+
@p.opt :arg10, 'arg', :type => :dates
|
768
|
+
sio = StringIO.new "w"
|
769
|
+
@p.educate sio
|
770
|
+
|
771
|
+
help = sio.string.split "\n"
|
772
|
+
assert help[1] =~ /<i>/
|
773
|
+
assert help[2] =~ /<i\+>/
|
774
|
+
assert help[3] =~ /<s>/
|
775
|
+
assert help[4] =~ /<s\+>/
|
776
|
+
assert help[5] =~ /<f>/
|
777
|
+
assert help[6] =~ /<f\+>/
|
778
|
+
assert help[7] =~ /<filename\/uri>/
|
779
|
+
assert help[8] =~ /<filename\/uri\+>/
|
780
|
+
assert help[9] =~ /<date>/
|
781
|
+
assert help[10] =~ /<date\+>/
|
782
|
+
end
|
783
|
+
|
784
|
+
def test_help_has_grammatical_default_text
|
785
|
+
@p.opt :arg1, 'description with period.', :default => 'hello'
|
786
|
+
@p.opt :arg2, 'description without period', :default => 'world'
|
787
|
+
sio = StringIO.new 'w'
|
788
|
+
@p.educate sio
|
789
|
+
|
790
|
+
help = sio.string.split "\n"
|
791
|
+
assert help[1] =~ /Default/
|
792
|
+
assert help[2] =~ /default/
|
793
|
+
end
|
794
|
+
|
688
795
|
def test_version_and_help_short_args_can_be_overridden
|
689
796
|
@p.opt :verbose, "desc", :short => "-v"
|
690
797
|
@p.opt :hello, "desc", :short => "-h"
|
@@ -951,6 +1058,31 @@ EOM
|
|
951
1058
|
end
|
952
1059
|
end
|
953
1060
|
|
1061
|
+
def test_date_arg_type
|
1062
|
+
temp = Date.new
|
1063
|
+
@p.opt :arg, 'desc', :type => :date
|
1064
|
+
@p.opt :arg2, 'desc', :type => Date
|
1065
|
+
@p.opt :arg3, 'desc', :default => temp
|
1066
|
+
|
1067
|
+
opts = nil
|
1068
|
+
assert_nothing_raised { opts = @p.parse }
|
1069
|
+
assert_equal temp, opts[:arg3]
|
1070
|
+
|
1071
|
+
assert_nothing_raised { opts = @p.parse %w(--arg 5/1/2010) }
|
1072
|
+
assert_kind_of Date, opts[:arg]
|
1073
|
+
assert_equal Date.new(2010, 5, 1), opts[:arg]
|
1074
|
+
|
1075
|
+
assert_nothing_raised { opts = @p.parse %w(--arg2 5/1/2010) }
|
1076
|
+
assert_kind_of Date, opts[:arg2]
|
1077
|
+
assert_equal Date.new(2010, 5, 1), opts[:arg2]
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
def test_unknown_arg_class_type
|
1081
|
+
assert_raise ArgumentError do
|
1082
|
+
@p.opt :arg, 'desc', :type => Hash
|
1083
|
+
end
|
1084
|
+
end
|
1085
|
+
|
954
1086
|
def test_io_arg_type
|
955
1087
|
@p.opt :arg, "desc", :type => :io
|
956
1088
|
@p.opt :arg2, "desc", :type => IO
|
@@ -1124,12 +1256,52 @@ EOM
|
|
1124
1256
|
end
|
1125
1257
|
|
1126
1258
|
def test_simple_interface_handles_die
|
1259
|
+
old_stderr, $stderr = $stderr, StringIO.new('w')
|
1127
1260
|
ARGV.clear
|
1128
1261
|
ARGV.unshift "--potato"
|
1129
1262
|
::Trollop::options do
|
1130
1263
|
opt :potato
|
1131
1264
|
end
|
1132
1265
|
assert_raises(SystemExit) { ::Trollop::die :potato, "is invalid" }
|
1266
|
+
ensure
|
1267
|
+
$stderr = old_stderr
|
1268
|
+
end
|
1269
|
+
|
1270
|
+
def test_simple_interface_handles_die_without_message
|
1271
|
+
old_stderr, $stderr = $stderr, StringIO.new('w')
|
1272
|
+
ARGV.clear
|
1273
|
+
ARGV.unshift "--potato"
|
1274
|
+
opts = ::Trollop::options do
|
1275
|
+
opt :potato
|
1276
|
+
end
|
1277
|
+
assert_raises(SystemExit) { ::Trollop::die :potato }
|
1278
|
+
assert $stderr.string =~ /Error:/
|
1279
|
+
ensure
|
1280
|
+
$stderr = old_stderr
|
1281
|
+
end
|
1282
|
+
|
1283
|
+
def test_with_standard_exception_handling
|
1284
|
+
assert_raise(SystemExit) do
|
1285
|
+
::Trollop.with_standard_exception_handling(@p) do
|
1286
|
+
raise ::Trollop::CommandlineError.new('cl error')
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
def test_supports_callback_inline
|
1292
|
+
assert_raises(RuntimeError, "good") do
|
1293
|
+
@p.opt :cb1 do |vals|
|
1294
|
+
raise "good"
|
1295
|
+
end
|
1296
|
+
@p.parse(%w(--cb1))
|
1297
|
+
end
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
def test_supports_callback_param
|
1301
|
+
assert_raises(RuntimeError, "good") do
|
1302
|
+
@p.opt :cb1, "with callback", :callback => lambda { |vals| raise "good" }
|
1303
|
+
@p.parse(%w(--cb1))
|
1304
|
+
end
|
1133
1305
|
end
|
1134
1306
|
end
|
1135
1307
|
|
data/trollop.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'trollop'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "trollop"
|
8
|
+
spec.version = Trollop::VERSION
|
9
|
+
spec.authors = ["William Morgan", "Keenan Brock"]
|
10
|
+
spec.email = "keenan@thebrocks.net"
|
11
|
+
spec.summary = "Trollop is a commandline option parser for Ruby that just gets out of your way."
|
12
|
+
spec.description = "Trollop is a commandline option parser for Ruby that just
|
13
|
+
gets out of your way. One line of code per option is all you need to write.
|
14
|
+
For that, you get a nice automatically-generated help page, robust option
|
15
|
+
parsing, command subcompletion, and sensible defaults for everything you don't
|
16
|
+
specify."
|
17
|
+
spec.homepage = "http://manageiq.github.io/trollop/"
|
18
|
+
spec.license = "MIT"
|
19
|
+
|
20
|
+
spec.files = `git ls-files -z`.split("\x0")
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'curses'
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_development_dependency "minitest", "~> 4.7.3"
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "chronic"
|
31
|
+
spec.add_development_dependency "simplecov"
|
32
|
+
spec.add_development_dependency "coveralls"
|
33
|
+
end
|
metadata
CHANGED
@@ -1,59 +1,162 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trollop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- William Morgan
|
8
|
+
- Keenan Brock
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
14
|
-
|
15
|
-
|
12
|
+
date: 2015-01-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: curses
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: minitest
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 4.7.3
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 4.7.3
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: bundler
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.6'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.6'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rake
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '10.0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '10.0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: chronic
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: simplecov
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: coveralls
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
description: |-
|
113
|
+
Trollop is a commandline option parser for Ruby that just
|
16
114
|
gets out of your way. One line of code per option is all you need to write.
|
17
|
-
|
18
115
|
For that, you get a nice automatically-generated help page, robust option
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
specify.'
|
23
|
-
email: wmorgan-trollop@masanjin.net
|
116
|
+
parsing, command subcompletion, and sensible defaults for everything you don't
|
117
|
+
specify.
|
118
|
+
email: keenan@thebrocks.net
|
24
119
|
executables: []
|
25
120
|
extensions: []
|
26
121
|
extra_rdoc_files: []
|
27
122
|
files:
|
28
|
-
-
|
29
|
-
-
|
123
|
+
- ".gitignore"
|
124
|
+
- ".travis.yml"
|
30
125
|
- FAQ.txt
|
126
|
+
- Gemfile
|
31
127
|
- History.txt
|
128
|
+
- README.md
|
129
|
+
- Rakefile
|
130
|
+
- lib/trollop.rb
|
32
131
|
- release-script.txt
|
33
|
-
-
|
34
|
-
|
35
|
-
|
132
|
+
- test/test_helper.rb
|
133
|
+
- test/test_trollop.rb
|
134
|
+
- trollop.gemspec
|
135
|
+
homepage: http://manageiq.github.io/trollop/
|
136
|
+
licenses:
|
137
|
+
- MIT
|
138
|
+
metadata: {}
|
36
139
|
post_install_message:
|
37
140
|
rdoc_options: []
|
38
141
|
require_paths:
|
39
142
|
- lib
|
40
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
144
|
requirements:
|
43
|
-
- -
|
145
|
+
- - ">="
|
44
146
|
- !ruby/object:Gem::Version
|
45
147
|
version: '0'
|
46
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
149
|
requirements:
|
49
|
-
- -
|
150
|
+
- - ">="
|
50
151
|
- !ruby/object:Gem::Version
|
51
152
|
version: '0'
|
52
153
|
requirements: []
|
53
|
-
rubyforge_project:
|
54
|
-
rubygems_version:
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 2.2.2
|
55
156
|
signing_key:
|
56
|
-
specification_version:
|
157
|
+
specification_version: 4
|
57
158
|
summary: Trollop is a commandline option parser for Ruby that just gets out of your
|
58
159
|
way.
|
59
|
-
test_files:
|
160
|
+
test_files:
|
161
|
+
- test/test_helper.rb
|
162
|
+
- test/test_trollop.rb
|
data/README.txt
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
== trollop
|
2
|
-
|
3
|
-
by William Morgan (http://masanjin.net/)
|
4
|
-
|
5
|
-
Main page: http://trollop.rubyforge.org
|
6
|
-
|
7
|
-
Release announcements and comments: http://masanjin.net/blog/label/trollop/.
|
8
|
-
|
9
|
-
Documentation quickstart: See Trollop.options and then Trollop::Parser#opt.
|
10
|
-
Also see the examples at http://trollop.rubyforge.org/.
|
11
|
-
|
12
|
-
== DESCRIPTION
|
13
|
-
|
14
|
-
Trollop is a commandline option parser for Ruby that just gets out of your way.
|
15
|
-
One line of code per option is all you need to write. For that, you get a nice
|
16
|
-
automatically-generated help page, robust option parsing, and sensible defaults
|
17
|
-
for everything you don't specify.
|
18
|
-
|
19
|
-
== FEATURES
|
20
|
-
|
21
|
-
- Dirt-simple usage.
|
22
|
-
- Single file. Throw it in lib/ if you don't want to make it a Rubygem dependency.
|
23
|
-
- Sensible defaults. No tweaking necessary, much tweaking possible.
|
24
|
-
- Support for long options, short options, subcommands, and automatic type validation and
|
25
|
-
conversion.
|
26
|
-
- Automatic help message generation, wrapped to current screen width.
|
27
|
-
|
28
|
-
== REQUIREMENTS
|
29
|
-
|
30
|
-
* A burning desire to write less code.
|
31
|
-
|
32
|
-
== INSTALL
|
33
|
-
|
34
|
-
* gem install trollop
|
35
|
-
|
36
|
-
== SYNOPSIS
|
37
|
-
|
38
|
-
require 'trollop'
|
39
|
-
opts = Trollop::options do
|
40
|
-
opt :monkey, "Use monkey mode" # flag --monkey, default false
|
41
|
-
opt :name, "Monkey name", :type => :string # string --name <s>, default nil
|
42
|
-
opt :num_limbs, "Number of limbs", :default => 4 # integer --num-limbs <i>, default to 4
|
43
|
-
end
|
44
|
-
|
45
|
-
p opts # a hash: { :monkey=>false, :name=>nil, :num_limbs=>4, :help=>false }
|
46
|
-
|
47
|
-
== LICENSE
|
48
|
-
|
49
|
-
Copyright (c) 2008--2012 William Morgan. Trollop is distributed under the same
|
50
|
-
terms as Ruby.
|