trollop 1.10 → 1.10.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.
@@ -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: []