trollop 2.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.swp
13
+ *.o
14
+ *.a
15
+ mkmf.log
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0"
5
+ - "2.1"
data/FAQ.txt CHANGED
@@ -93,6 +93,3 @@ A: The big change was boolean parameter (aka flag) handling. In pre-2.0,
93
93
 
94
94
  Using --magic will result in :no_magic => false, and --no-magic will result in
95
95
  :no_magic => true, and neither will result in :no_magic => true.
96
-
97
-
98
-
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in trollop.gemspec
4
+ gemspec
@@ -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.
@@ -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 &copy; 2008-2014 [William Morgan](http://masanjin.net/).
54
+
55
+ Copyright &copy; 2014 Red Hat, Inc.
56
+
57
+ Trollop is licensed under the same terms as Ruby.
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+ require 'coveralls/rake/task'
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs << 'test'
9
+ t.pattern = "test/test_*.rb"
10
+ end
11
+
12
+ Coveralls::RakeTask.new
@@ -1,13 +1,12 @@
1
- ## lib/trollop.rb -- trollop command-line processing library
2
- ## Author:: William Morgan (mailto: wmorgan-trollop@masanjin.net)
3
- ## Copyright:: Copyright 2007 William Morgan
4
- ## License:: the same terms as ruby itself
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 '-h' or '--version'. Handled
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
- raise CommandlineError, "unknown argument '#{arg}'" unless sym
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
- raise CommandlineError, "option '#{arg}' needs a parameter" if params.empty? && opts[:type] != :flag
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] = "--#{spec[:long]}" +
431
- (spec[:type] == :flag && spec[:default] ? ", --no-#{spec[:long]}" : "") +
432
- (spec[:short] && spec[:short] != :none ? ", -#{spec[:short]}" : "") +
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; " <i>"
436
- when :ints; " <i+>"
437
- when :string; " <s>"
438
- when :strings; " <s+>"
439
- when :float; " <f>"
440
- when :floats; " <f+>"
441
- when :io; " <filename/uri>"
442
- when :ios; " <filename/uri+>"
443
- when :date; " <date>"
444
- when :dates; " <date+>"
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 " %#{leftcol_width}s: ", left[opt]
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
- str.split("\n").map { |s| wrap_line s, opts }.flatten
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 =~ /^\d+$/
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
- module_function :options, :die, :with_standard_exception_handling
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
@@ -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'
@@ -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
- require 'trollop'
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:\s+desc/
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
- begin
426
- require 'chronic'
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 short_options_with_multiple_options_does_not_affect_flags_type
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
 
@@ -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: '2.0'
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: 2012-08-14 00:00:00.000000000 Z
13
- dependencies: []
14
- description: ! 'Trollop is a commandline option parser for Ruby that just
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
- parsing, command subcompletion, and sensible defaults for everything you don''t
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
- - lib/trollop.rb
29
- - test/test_trollop.rb
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
- - README.txt
34
- homepage: http://trollop.rubyforge.org
35
- licenses: []
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: trollop
54
- rubygems_version: 1.8.23
154
+ rubyforge_project:
155
+ rubygems_version: 2.2.2
55
156
  signing_key:
56
- specification_version: 3
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.