trollop 1.10 → 1.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ == 1.10.1 / 2008-10-22
2
+ * Options hash now responds to method calls as well as standard hash lookup.
3
+ * Default values for multi-occurrence parameters now autoboxed.
4
+ * The relationship between multi-value, multi-occurrence, and default values
5
+ improved and explained.
6
+ * Documentation improvements.
7
+
1
8
  == 1.10 / 2008-10-21
2
9
  * Added :io type for parameters that point to IO streams (filenames, URIs, etc).
3
10
  * For screen size detection, first try `stty size` before loading Curses.
data/README.txt CHANGED
@@ -4,7 +4,7 @@ by William Morgan <wmorgan-trollop@masanjin.net>
4
4
 
5
5
  http://trollop.rubyforge.org
6
6
 
7
- Documentation quickstart: See Trollop::Parser.
7
+ Documentation quickstart: See Trollop::options and Trollop::Parser#opt.
8
8
 
9
9
  == DESCRIPTION
10
10
 
data/Rakefile CHANGED
@@ -7,8 +7,8 @@ $:.unshift "lib"
7
7
  require 'trollop'
8
8
 
9
9
  class Hoe
10
- def extra_deps; @extra_deps.reject { |x| Array(x).first == "hoe" } end
11
- end # thanks to "Mike H"
10
+ def extra_dev_deps; @extra_dev_deps.reject { |x| x[0] == "hoe" } end
11
+ end
12
12
 
13
13
  Hoe.new('trollop', Trollop::VERSION) do |p|
14
14
  p.rubyforge_name = 'trollop'
@@ -25,8 +25,12 @@ task :upload_webpage => WWW_FILES do |t|
25
25
  sh "rsync -Paz -essh #{t.prerequisites * ' '} wmorgan@rubyforge.org:/var/www/gforge-projects/trollop/"
26
26
  end
27
27
 
28
- task :upload_docs => [:docs] do |t|
29
- sh "rsync -Paz -essh doc/* wmorgan@rubyforge.org:/var/www/gforge-projects/trollop/trollop/"
28
+ task :rdoc do |t|
29
+ sh "rdoc lib README.txt History.txt"
30
+ end
31
+
32
+ task :upload_docs => [:rdoc] do |t|
33
+ sh "rsync -az -essh doc/* wmorgan@rubyforge.org:/var/www/gforge-projects/trollop/trollop/"
30
34
  end
31
35
 
32
36
  # vim: syntax=ruby
@@ -5,7 +5,7 @@
5
5
 
6
6
  module Trollop
7
7
 
8
- VERSION = "1.10"
8
+ VERSION = "1.10.1"
9
9
 
10
10
  ## Thrown by Parser in the event of a commandline error. Not needed if
11
11
  ## you're using the Trollop::options entry.
@@ -26,7 +26,7 @@ FLOAT_RE = /^-?((\d+(\.\d+)?)|(\.\d+))$/
26
26
  PARAM_RE = /^-(-|\.$|[^\d\.])/
27
27
 
28
28
  ## The commandline parser. In typical usage, the methods in this class
29
- ## will be handled internally by Trollop#options. In this case, only the
29
+ ## will be handled internally by Trollop::options. In this case, only the
30
30
  ## #opt, #banner and #version, #depends, and #conflicts methods will
31
31
  ## typically be called.
32
32
  ##
@@ -79,18 +79,43 @@ class Parser
79
79
  end
80
80
 
81
81
  ## Define an option. +name+ is the option name, a unique identifier
82
- ## for the option that you will use internally. This should probably
83
- ## be a symbol. +desc+ is a string description which will be displayed
84
- ## in help messages.
82
+ ## for the option that you will use internally, which should be a
83
+ ## symbol or a string. +desc+ is a string description which will be
84
+ ## displayed in help messages.
85
85
  ##
86
86
  ## Takes the following optional arguments:
87
87
  ##
88
88
  ## [+:long+] Specify the long form of the argument, i.e. the form with two dashes. If unspecified, will be automatically derived based on the argument name by turning the +name+ option into a string, and replacing any _'s by -'s.
89
89
  ## [+:short+] Specify the short form of the argument, i.e. the form with one dash. If unspecified, will be automatically derived from +name+.
90
- ## [+:type+] Require that the argument take a parameter or parameters of type +type+. For a single parameter, the value can be a member of +SINGLE_ARG_TYPES+, or a corresponding Ruby class (e.g. +Integer+ for +:int+). For multiple parameters, the value can be any member of +MULTI_ARG_TYPES+ constant. If unset, the default argument type is +:flag+, meaning that the argument does not take a parameter. The specification of +:type+ is not necessary if +:default+ is given.
91
- ## [+:default+] Set the default value for an argument. Without a default value, the hash returned by #parse (and thus Trollop#options) will have a +nil+ value for this key unless the option is set on the commandline. The argument type is derived automatically from the class of the default value given, if any. Specifying a +:flag+ argument on the commandline whose default value is +true+ will result in a value of +false+.
90
+ ## [+:type+] Require that the argument take a parameter or parameters of type +type+. For a single parameter, the value can be a member of +SINGLE_ARG_TYPES+, or a corresponding Ruby class (e.g. +Integer+ for +:int+). For multiple-argument parameters, the value can be any member of +MULTI_ARG_TYPES+ constant. If unset, the default argument type is +:flag+, meaning that the argument does not take a parameter. The specification of +:type+ is not necessary if a +:default+ is given.
91
+ ## [+:default+] Set the default value for an argument. Without a default value, the hash returned by #parse (and thus Trollop::options) will have a +nil+ value for this key unless the argument is given on the commandline. The argument type is derived automatically from the class of the default value given, so specifying a +:type+ is not necessary if a +:default+ is given. (But see below for an important caveat when +:multi+: is specified too.) If the argument is a flag, and the default is set to +true+, then if it is specified on the the commandline the value will be +false+.
92
92
  ## [+:required+] If set to +true+, the argument must be provided on the commandline.
93
- ## [+:multi+] If set to +true+, allows multiple instances of the option on the commandline. Otherwise, only a single instance of the option is allowed.
93
+ ## [+:multi+] If set to +true+, allows multiple occurrences of the option on the commandline. Otherwise, only a single instance of the option is allowed. (Note that this is different from taking multiple parameters. See below.)
94
+ ##
95
+ ## Note that there are two types of argument multiplicity: an argument
96
+ ## can take multiple values, e.g. "--arg 1 2 3". An argument can also
97
+ ## be allowed to occur multiple times, e.g. "--arg 1 --arg 2".
98
+ ##
99
+ ## Arguments that take multiple values should have a +:type+ parameter
100
+ ## drawn from +MULTI_ARG_TYPES+ (e.g. +:strings+), or a +:default:+
101
+ ## value of an array of the correct type (e.g. [String]). The
102
+ ## value of this argument will be an array of the parameters on the
103
+ ## commandline.
104
+ ##
105
+ ## Arguments that can occur multiple times should be marked with
106
+ ## +:multi+ => +true+. The value of this argument will also be an array.
107
+ ##
108
+ ## These two attributes can be combined (e.g. +:type+ => +:strings+,
109
+ ## +:multi+ => +true+), in which case the value of the argument will be
110
+ ## an array of arrays.
111
+ ##
112
+ ## There's one ambiguous case to be aware of: when +:multi+: is true and a
113
+ ## +:default+ is set to an array (of something), it's ambiguous whether this
114
+ ## is a multi-value argument as well as a multi-occurrence argument.
115
+ ## In thise case, Trollop assumes that it's not a multi-value argument.
116
+ ## If you want a multi-value, multi-occurrence argument with a default
117
+ ## value, you must specify +:type+ as well.
118
+
94
119
  def opt name, desc="", opts={}
95
120
  raise ArgumentError, "you already have an argument named '#{name}'" if @specs.member? name
96
121
 
@@ -118,8 +143,19 @@ class Parser
118
143
  opts[:type]
119
144
  end
120
145
 
146
+ ## for options with :multi => true, an array default doesn't imply
147
+ ## a multi-valued argument. for that you have to specify a :type
148
+ ## as well. (this is how we disambiguate an ambiguous situation;
149
+ ## see the docs for Parser#opt for details.)
150
+ disambiguated_default =
151
+ if opts[:multi] && opts[:default].is_a?(Array) && !opts[:type]
152
+ opts[:default].first
153
+ else
154
+ opts[:default]
155
+ end
156
+
121
157
  type_from_default =
122
- case opts[:default]
158
+ case disambiguated_default
123
159
  when Integer; :int
124
160
  when Numeric; :float
125
161
  when TrueClass, FalseClass; :flag
@@ -144,7 +180,7 @@ class Parser
144
180
 
145
181
  raise ArgumentError, ":type specification and default type don't match" if opts[:type] && type_from_default && opts[:type] != type_from_default
146
182
 
147
- opts[:type] = (opts[:type] || type_from_default || :flag)
183
+ opts[:type] = opts[:type] || type_from_default || :flag
148
184
 
149
185
  ## fill in :long
150
186
  opts[:long] = opts[:long] ? opts[:long].to_s : name.to_s.gsub("_", "-")
@@ -184,6 +220,9 @@ class Parser
184
220
  ## fill in :default for flags
185
221
  opts[:default] = false if opts[:type] == :flag && opts[:default].nil?
186
222
 
223
+ ## autobox :default for :multi (multi-occurrence) arguments
224
+ opts[:default] = [opts[:default]] if opts[:default] && opts[:multi] && !opts[:default].is_a?(Array)
225
+
187
226
  ## fill in :multi
188
227
  opts[:multi] ||= false
189
228
 
@@ -417,6 +456,12 @@ class Parser
417
456
  # else: multiple options, with multiple parameters
418
457
  end
419
458
 
459
+ ## allow openstruct-style accessors
460
+ class << vals
461
+ def method_missing(m, *args)
462
+ self[m] || self[m.to_s]
463
+ end
464
+ end
420
465
  vals
421
466
  end
422
467
 
@@ -509,16 +554,27 @@ class Parser
509
554
 
510
555
  spec = @specs[opt]
511
556
  stream.printf " %#{leftcol_width}s: ", left[opt]
512
- desc = spec[:desc] +
557
+ desc = spec[:desc] + begin
558
+ default_s = case spec[:default]
559
+ when $stdout; "<stdout>"
560
+ when $stdin; "<stdin>"
561
+ when $stderr; "<stderr>"
562
+ when Array
563
+ spec[:default].join(", ")
564
+ else
565
+ spec[:default].to_s
566
+ end
567
+
513
568
  if spec[:default]
514
569
  if spec[:desc] =~ /\.$/
515
- " (Default: #{spec[:default]})"
570
+ " (Default: #{default_s})"
516
571
  else
517
- " (default: #{spec[:default]})"
572
+ " (default: #{default_s})"
518
573
  end
519
574
  else
520
575
  ""
521
576
  end
577
+ end
522
578
  stream.puts wrap(desc, :width => width - rightcol_start - 1, :prefix => rightcol_start)
523
579
  end
524
580
  end
@@ -573,7 +629,19 @@ end
573
629
  ## (Parser#opt), zero or more calls to +text+ (Parser#text), and
574
630
  ## probably a call to +version+ (Parser#version).
575
631
  ##
576
- ## See the examples at http://trollop.rubyforge.org.
632
+ ## Example:
633
+ ##
634
+ ## require 'trollop'
635
+ ## opts = Trollop::options do
636
+ ## opt :monkey, "Use monkey mode" # a flag --monkey, defaulting to false
637
+ ## opt :goat, "Use goat mode", :default => true # a flag --goat, defaulting to true
638
+ ## opt :num_limbs, "Number of limbs", :default => 4 # an integer --num-limbs <i>, defaulting to 4
639
+ ## opt :num_thumbs, "Number of thumbs", :type => :int # an integer --num-thumbs <i>, defaulting to nil
640
+ ## end
641
+ ##
642
+ ## p opts # returns a hash: { :monkey => false, :goat => true, :num_limbs => 4, :num_thumbs => nil }
643
+ ##
644
+ ## See more examples at http://trollop.rubyforge.org.
577
645
  def options args = ARGV, *a, &b
578
646
  @p = Parser.new(*a, &b)
579
647
  begin
@@ -884,14 +884,73 @@ EOM
884
884
  assert_kind_of File, opts[:arg]
885
885
  assert_equal "/dev/null", opts[:arg].path
886
886
 
887
- assert_nothing_raised { opts = @p.parse %w(--arg2 http://google.com/) }
888
- assert_kind_of StringIO, opts[:arg2]
887
+ #TODO: move to mocks
888
+ #assert_nothing_raised { opts = @p.parse %w(--arg2 http://google.com/) }
889
+ #assert_kind_of StringIO, opts[:arg2]
889
890
 
890
891
  assert_nothing_raised { opts = @p.parse %w(--arg3 stdin) }
891
892
  assert_equal $stdin, opts[:arg3]
892
893
 
893
894
  assert_raises(CommandlineError) { opts = @p.parse %w(--arg /fdasfasef/fessafef/asdfasdfa/fesasf) }
894
895
  end
896
+
897
+ def test_openstruct_style_access
898
+ @p.opt "arg1", "desc", :type => :int
899
+ @p.opt :arg2, "desc", :type => :int
900
+
901
+ opts = @p.parse(%w(--arg1 3 --arg2 4))
902
+
903
+ assert_nothing_raised { opts.arg1 }
904
+ assert_nothing_raised { opts.arg2 }
905
+ assert_equal 3, opts.arg1
906
+ assert_equal 4, opts.arg2
907
+ end
908
+
909
+ def test_multi_args_autobox_defaults
910
+ @p.opt :arg1, "desc", :default => "hello", :multi => true
911
+ @p.opt :arg2, "desc", :default => ["hello"], :multi => true
912
+
913
+ opts = @p.parse
914
+ assert_equal ["hello"], opts[:arg1]
915
+ assert_equal ["hello"], opts[:arg2]
916
+
917
+ opts = @p.parse %w(--arg1 hello)
918
+ assert_equal ["hello"], opts[:arg1]
919
+ assert_equal ["hello"], opts[:arg2]
920
+
921
+ opts = @p.parse %w(--arg1 hello --arg1 there)
922
+ assert_equal ["hello", "there"], opts[:arg1]
923
+ end
924
+
925
+ def test_ambigious_multi_plus_array_default_resolved_as_specified_by_documentation
926
+ @p.opt :arg1, "desc", :default => ["potato"], :multi => true
927
+ @p.opt :arg2, "desc", :default => ["potato"], :multi => true, :type => :strings
928
+ @p.opt :arg3, "desc", :default => ["potato"]
929
+ @p.opt :arg4, "desc", :default => ["potato", "rhubarb"], :short => :none, :multi => true
930
+
931
+ ## arg1 should be multi-occurring but not multi-valued
932
+ opts = @p.parse %w(--arg1 one two)
933
+ assert_equal ["one"], opts[:arg1]
934
+ assert_equal ["two"], @p.leftovers
935
+
936
+ opts = @p.parse %w(--arg1 one --arg1 two)
937
+ assert_equal ["one", "two"], opts[:arg1]
938
+ assert_equal [], @p.leftovers
939
+
940
+ ## arg2 should be multi-valued and multi-occurring
941
+ opts = @p.parse %w(--arg2 one two)
942
+ assert_equal [["one", "two"]], opts[:arg2]
943
+ assert_equal [], @p.leftovers
944
+
945
+ ## arg3 should be multi-valued but not multi-occurring
946
+ opts = @p.parse %w(--arg3 one two)
947
+ assert_equal ["one", "two"], opts[:arg3]
948
+ assert_equal [], @p.leftovers
949
+
950
+ ## arg4 should be multi-valued but not multi-occurring
951
+ opts = @p.parse %w()
952
+ assert_equal ["potato", "rhubarb"], opts[:arg4]
953
+ end
895
954
  end
896
955
 
897
956
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trollop
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.10"
4
+ version: 1.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Morgan
@@ -9,19 +9,10 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-21 00:00:00 -07:00
12
+ date: 2008-10-22 00:00:00 -07:00
13
13
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: hoe
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 1.8.0
24
- version:
14
+ dependencies: []
15
+
25
16
  description: == DESCRIPTION Trollop is a commandline option parser for Ruby that just gets out of your way. One line of code per option is all you need to write. For that, you get a nice automatically-generated help page, robust option parsing, command subcompletion, and sensible defaults for everything you don't specify. * A burning desire to write less code. == INSTALL * gem install trollop == LICENSE Copyright (c) 2008 William Morgan. Trollop is distributed under the same terms as Ruby.
26
17
  email: wmorgan-trollop@masanjin.net
27
18
  executables: []