trollop 1.9 → 1.10

Sign up to get free protection for your applications and to get access to all the features.
data/FAQ.txt CHANGED
@@ -33,12 +33,3 @@ A: Because it's ambiguous whether these are arguments or negative
33
33
  that require floating-point parameters, and allow such short option
34
34
  names in those cases, but opted for simplicity and consistency.
35
35
 
36
- Q: Why does Trollop disallow options appearing multiple times, despite
37
- the POSIX standard allowing it?
38
- A: Because basically I think it's confusing, and more often than
39
- not, a symptom of you making a mistake (e.g. getting lost in a long
40
- command line and accidentally setting the same thing twice.)
41
- I also don't see that much advantage to "-vvvvv" over "-v 5", so
42
- Trollop will produce an error if you try to use the same argument
43
- multiple times.
44
-
@@ -1,3 +1,8 @@
1
+ == 1.10 / 2008-10-21
2
+ * Added :io type for parameters that point to IO streams (filenames, URIs, etc).
3
+ * For screen size detection, first try `stty size` before loading Curses.
4
+ * Improved documentation.
5
+
1
6
  == 1.9 / 2008-08-20
2
7
  * Added 'stop_on_unknown' command to stop parsing on any unknown argument.
3
8
  This is useful for handling sub-commands when you don't know the entire
data/README.txt CHANGED
@@ -23,62 +23,6 @@ subcompletion, and sensible defaults for everything you don't specify.
23
23
  - Automatic help message generation, wrapped to current screen width.
24
24
  - Lots of unit tests.
25
25
 
26
- == SYNOPSIS
27
-
28
- ####################
29
- ###### simple ######
30
- ####################
31
-
32
- require 'trollop'
33
- opts = Trollop::options do
34
- opt :monkey, "Use monkey mode"
35
- opt :goat, "Use goat mode", :default => true
36
- opt :num_limbs, "Set number of limbs", :default => 4
37
- end
38
-
39
- p opts # { :monkey => false, :goat => true, :num_limbs => 4 }
40
-
41
- ####################
42
- ###### medium ######
43
- ####################
44
-
45
- require 'trollop'
46
- opts = Trollop::options do
47
- version "test 1.2.3 (c) 2007 William Morgan"
48
- banner <<-EOS
49
- Test is an awesome program that does something very, very important.
50
-
51
- Usage:
52
- test [options] <filenames>+
53
- where [options] are:
54
- EOS
55
-
56
- opt :ignore, "Ignore incorrect values"
57
- opt :file, "Extra data filename to read in, with a very long option description like this one", :type => String
58
- opt :volume, "Volume level", :default => 3.0
59
- opt :iters, "Number of iterations", :default => 5
60
- end
61
- Trollop::die :volume, "must be non-negative" if opts[:volume] < 0
62
- Trollop::die :file, "must exist" unless File.exist?(opts[:file]) if opts[:file]
63
- ################################
64
- ##### sub-command support ######
65
- ################################
66
-
67
- require 'trollop'
68
- global_opts = Trollop::options do
69
- opt :global_option, "This is a global option"
70
- stop_on %w(sub-command-1 sub-command-2)
71
- end
72
-
73
- cmd = ARGV.shift
74
- cmd_opts = Trollop::options do
75
- opt :cmd_option, "This is an option only for the subcommand"
76
- end
77
-
78
- p global_opts
79
- p cmd
80
- p cmd_opts
81
-
82
26
  == REQUIREMENTS
83
27
 
84
28
  * A burning desire to write less code.
@@ -89,6 +33,4 @@ subcompletion, and sensible defaults for everything you don't specify.
89
33
 
90
34
  == LICENSE
91
35
 
92
- Copyright (c) 2008 William Morgan.
93
-
94
- Trollop is distributed under the same terms as Ruby.
36
+ Copyright (c) 2008 William Morgan. Trollop is distributed under the same terms as Ruby.
@@ -5,7 +5,7 @@
5
5
 
6
6
  module Trollop
7
7
 
8
- VERSION = "1.9"
8
+ VERSION = "1.10"
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,26 +26,31 @@ 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 which case only the
30
- ## methods #opt, #banner and #version, #depends, and #conflicts will
29
+ ## will be handled internally by Trollop#options. In this case, only the
30
+ ## #opt, #banner and #version, #depends, and #conflicts methods will
31
31
  ## typically be called.
32
+ ##
33
+ ## If it's necessary to instantiate this class (for more complicated
34
+ ## argument-parsing situations), be sure to call #parse to actually
35
+ ## produce the output hash.
32
36
  class Parser
33
37
 
34
- ## The set of values that indicate a flag type of option when one of
35
- ## the values is given to the :type parameter to #opt.
38
+ ## The set of values that indicate a flag option when passed as the
39
+ ## +:type+ parameter of #opt.
36
40
  FLAG_TYPES = [:flag, :bool, :boolean]
37
41
 
38
- ## The set of values that indicate an option that takes a single
39
- ## parameter when one of the values is given to the :type parameter to
40
- ## #opt.
41
- SINGLE_ARG_TYPES = [:int, :integer, :string, :double, :float]
42
+ ## The set of values that indicate a single-parameter option when
43
+ ## passed as the +:type+ parameter of #opt.
44
+ ##
45
+ ## A value of +io+ corresponds to a readable IO resource, including
46
+ ## a filename, URI, or the strings 'stdin' or '-'.
47
+ SINGLE_ARG_TYPES = [:int, :integer, :string, :double, :float, :io]
42
48
 
43
- ## The set of values that indicate an option that takes multiple
44
- ## parameters when one of the values is given to the :type parameter to
45
- ## #opt.
46
- MULTI_ARG_TYPES = [:ints, :integers, :strings, :doubles, :floats]
49
+ ## The set of values that indicate a multiple-parameter option when
50
+ ## passed as the +:type+ parameter of #opt.
51
+ MULTI_ARG_TYPES = [:ints, :integers, :strings, :doubles, :floats, :ios]
47
52
 
48
- ## The set of values specifiable as the :type parameter to #opt.
53
+ ## The complete set of legal values for the +:type+ parameter of #opt.
49
54
  TYPES = FLAG_TYPES + SINGLE_ARG_TYPES + MULTI_ARG_TYPES
50
55
 
51
56
  INVALID_SHORT_ARG_REGEX = /[\d-]/ #:nodoc:
@@ -73,62 +78,44 @@ class Parser
73
78
  cloaker(&b).bind(self).call(*a) if b
74
79
  end
75
80
 
76
- ## Add an option. 'name' is the argument name, a unique identifier
77
- ## for the option that you will use internally. 'desc' a string
78
- ## description which will be displayed in help messages. Takes the
79
- ## following optional arguments:
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.
80
85
  ##
81
- ## * :long: Specify the long form of the argument, i.e. the form
82
- ## with two dashes. If unspecified, will be automatically derived
83
- ## based on the argument name.
84
- ## * :short: Specify the short form of the argument, i.e. the form
85
- ## with one dash. If unspecified, will be automatically derived
86
- ## based on the argument name.
87
- ## * :type: Require that the argument take a parameter or parameters
88
- ## of type 'type'. For a single parameter, the value can be a
89
- ## member of the SINGLE_ARG_TYPES constant or a corresponding class
90
- ## (e.g. Integer for :int). For multiple parameters, the value can
91
- ## be a member of the MULTI_ARG_TYPES constant. If unset, the
92
- ## default argument type is :flag, meaning that the argument does
93
- ## not take a parameter. The specification of :type is not
94
- ## necessary if :default is given.
95
- ## * :default: Set the default value for an argument. Without a
96
- ## default value, the hash returned by #parse (and thus
97
- ## Trollop#options) will not contain the argument unless it is
98
- ## given on the commandline. The argument type is derived
99
- ## automatically from the class of the default value given, if
100
- ## any. Specifying a :flag argument on the commandline whose
101
- ## default value is true will change its value to false.
102
- ## * :required: If set to true, the argument must be provided on the
103
- ## commandline.
104
- ## * :multi: If set to true, allows multiple instances of the
105
- ## option. Otherwise, only a single instance of the option is
106
- ## allowed.
86
+ ## Takes the following optional arguments:
87
+ ##
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
+ ## [+: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+.
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.
107
94
  def opt name, desc="", opts={}
108
95
  raise ArgumentError, "you already have an argument named '#{name}'" if @specs.member? name
109
96
 
110
97
  ## fill in :type
111
- opts[:type] =
98
+ opts[:type] = # normalize
112
99
  case opts[:type]
113
- when :flag, :boolean, :bool; :flag
114
- when :int, :integer; :int
115
- when :ints, :integers; :ints
116
- when :string; :string
117
- when :strings; :strings
118
- when :double, :float; :float
119
- when :doubles, :floats; :floats
100
+ when :boolean, :bool; :flag
101
+ when :integer; :int
102
+ when :integers; :ints
103
+ when :double; :float
104
+ when :doubles; :floats
120
105
  when Class
121
106
  case opts[:type].to_s # sigh... there must be a better way to do this
122
107
  when 'TrueClass', 'FalseClass'; :flag
123
108
  when 'String'; :string
124
109
  when 'Integer'; :int
125
110
  when 'Float'; :float
111
+ when 'IO'; :io
126
112
  else
127
113
  raise ArgumentError, "unsupported argument type '#{opts[:type].class.name}'"
128
114
  end
129
115
  when nil; nil
130
116
  else
131
117
  raise ArgumentError, "unsupported argument type '#{opts[:type]}'" unless TYPES.include?(opts[:type])
118
+ opts[:type]
132
119
  end
133
120
 
134
121
  type_from_default =
@@ -137,6 +124,7 @@ class Parser
137
124
  when Numeric; :float
138
125
  when TrueClass, FalseClass; :flag
139
126
  when String; :string
127
+ when IO; :io
140
128
  when Array
141
129
  if opts[:default].empty?
142
130
  raise ArgumentError, "multiple argument type cannot be deduced from an empty array for '#{opts[:default][0].class.name}'"
@@ -145,6 +133,7 @@ class Parser
145
133
  when Integer; :ints
146
134
  when Numeric; :floats
147
135
  when String; :strings
136
+ when IO; :ios
148
137
  else
149
138
  raise ArgumentError, "unsupported multiple argument type '#{opts[:default][0].class.name}'"
150
139
  end
@@ -206,11 +195,12 @@ class Parser
206
195
  end
207
196
 
208
197
  ## Sets the version string. If set, the user can request the version
209
- ## on the commandline. Should be of the form "<program name>
198
+ ## on the commandline. Should probably be of the form "<program name>
210
199
  ## <version number>".
211
200
  def version s=nil; @version = s if s; @version end
212
201
 
213
- ## Adds text to the help display.
202
+ ## Adds text to the help display. Can be interspersed with calls to
203
+ ## #opt to build a multi-section help page.
214
204
  def banner s; @order << [:text, s] end
215
205
  alias :text :banner
216
206
 
@@ -228,19 +218,23 @@ class Parser
228
218
  @constraints << [:conflicts, syms]
229
219
  end
230
220
 
231
- ## Defines a set of words which cause parsing to terminate when encountered,
232
- ## such that any options to the left of the word are parsed as usual, and
233
- ## options to the right of the word are left intact.
221
+ ## Defines a set of words which cause parsing to terminate when
222
+ ## encountered, such that any options to the left of the word are
223
+ ## parsed as usual, and options to the right of the word are left
224
+ ## intact.
234
225
  ##
235
- ## A typical use case would be for subcommand support, where these would be
236
- ## set to the list of subcommands. A subsequent Trollop invocation would
237
- ## then be used to parse subcommand options.
226
+ ## A typical use case would be for subcommand support, where these
227
+ ## would be set to the list of subcommands. A subsequent Trollop
228
+ ## invocation would then be used to parse subcommand options, after
229
+ ## shifting the subcommand off of ARGV.
238
230
  def stop_on *words
239
231
  @stop_words = [*words].flatten
240
232
  end
241
233
 
242
- ## Similar to stop_on, but stops on any unknown word when encountered (unless
243
- ## it is a parameter for an argument).
234
+ ## Similar to #stop_on, but stops on any unknown word when encountered
235
+ ## (unless it is a parameter for an argument). This is useful for
236
+ ## cases where you don't know the set of subcommands ahead of time,
237
+ ## i.e., without first parsing the global options.
244
238
  def stop_on_unknown
245
239
  @stop_on_unknown = true
246
240
  end
@@ -317,7 +311,8 @@ class Parser
317
311
  remains
318
312
  end
319
313
 
320
- def parse cmdline #:nodoc:
314
+ ## Parses the commandline. Typically called by Trollop::options.
315
+ def parse cmdline=ARGV
321
316
  vals = {}
322
317
  required = {}
323
318
 
@@ -406,6 +401,8 @@ class Parser
406
401
  vals[sym] = params.map { |pg| pg.map { |p| parse_float_parameter p, arg } }
407
402
  when :string, :strings
408
403
  vals[sym] = params.map { |pg| pg.map { |p| p.to_s } }
404
+ when :io, :ios
405
+ vals[sym] = params.map { |pg| pg.map { |p| parse_io_parameter p, arg } }
409
406
  end
410
407
 
411
408
  if SINGLE_ARG_TYPES.include?(opts[:type])
@@ -433,6 +430,19 @@ class Parser
433
430
  param.to_f
434
431
  end
435
432
 
433
+ def parse_io_parameter param, arg #:nodoc:
434
+ case param
435
+ when /^(stdin|-)$/i; $stdin
436
+ else
437
+ require 'open-uri'
438
+ begin
439
+ open param
440
+ rescue SystemCallError => e
441
+ raise CommandlineError, "file or url for option '#{arg}' cannot be opened: #{e.message}"
442
+ end
443
+ end
444
+ end
445
+
436
446
  def collect_argument_parameters args, start_at #:nodoc:
437
447
  params = []
438
448
  pos = start_at
@@ -446,21 +456,22 @@ class Parser
446
456
  def width #:nodoc:
447
457
  @width ||=
448
458
  if $stdout.tty?
449
- begin
450
- require 'curses'
451
- Curses::init_screen
452
- x = Curses::cols
453
- Curses::close_screen
454
- x
455
- rescue Exception
456
- 80
459
+ if `stty size` =~ /^(\d+) (\d+)$/
460
+ $2.to_i
461
+ else
462
+ begin
463
+ require 'curses'
464
+ Curses::init_screen
465
+ x = Curses::cols
466
+ Curses::close_screen
467
+ x
468
+ rescue Exception
469
+ end
457
470
  end
458
- else
459
- 80
460
- end
471
+ end || 80
461
472
  end
462
473
 
463
- ## Print the help message to 'stream'.
474
+ ## Print the help message to +stream+.
464
475
  def educate stream=$stdout
465
476
  width # just calculate it now; otherwise we have to be careful not to
466
477
  # call this unless the cursor's at the beginning of a line.
@@ -477,6 +488,8 @@ class Parser
477
488
  when :strings; " <s+>"
478
489
  when :float; " <f>"
479
490
  when :floats; " <f+>"
491
+ when :io; " <filename/uri>"
492
+ when :ios; " <filename/uri+>"
480
493
  end
481
494
  end
482
495
 
@@ -552,15 +565,15 @@ end
552
565
 
553
566
  ## The top-level entry method into Trollop. Creates a Parser object,
554
567
  ## passes the block to it, then parses +args+ with it, handling any
555
- ## errors or requests for help or version information appropriately
556
- ## (and then exiting). Modifies +args+ in place. Returns a hash of
557
- ## option values.
568
+ ## errors or requests for help or version information appropriately (and
569
+ ## then exiting). Modifies +args+ in place. Returns a hash of option
570
+ ## values.
558
571
  ##
559
- ## The block passed in should contain one or more calls to #opt
560
- ## (Parser#opt), one or more calls to text (Parser#text), and
561
- ## probably a call to version (Parser#version).
572
+ ## The block passed in should contain zero or more calls to +opt+
573
+ ## (Parser#opt), zero or more calls to +text+ (Parser#text), and
574
+ ## probably a call to +version+ (Parser#version).
562
575
  ##
563
- ## See the synopsis in README.txt for examples.
576
+ ## See the examples at http://trollop.rubyforge.org.
564
577
  def options args = ARGV, *a, &b
565
578
  @p = Parser.new(*a, &b)
566
579
  begin
@@ -612,3 +625,4 @@ end
612
625
  module_function :options, :die
613
626
 
614
627
  end # module
628
+
@@ -870,6 +870,28 @@ EOM
870
870
  assert_equal true, opts[physicist]
871
871
  end
872
872
  end
873
+
874
+ def test_io_arg_type
875
+ @p.opt :arg, "desc", :type => :io
876
+ @p.opt :arg2, "desc", :type => IO
877
+ @p.opt :arg3, "desc", :default => $stdout
878
+
879
+ opts = nil
880
+ assert_nothing_raised { opts = @p.parse() }
881
+ assert_equal $stdout, opts[:arg3]
882
+
883
+ assert_nothing_raised { opts = @p.parse %w(--arg /dev/null) }
884
+ assert_kind_of File, opts[:arg]
885
+ assert_equal "/dev/null", opts[:arg].path
886
+
887
+ assert_nothing_raised { opts = @p.parse %w(--arg2 http://google.com/) }
888
+ assert_kind_of StringIO, opts[:arg2]
889
+
890
+ assert_nothing_raised { opts = @p.parse %w(--arg3 stdin) }
891
+ assert_equal $stdin, opts[:arg3]
892
+
893
+ assert_raises(CommandlineError) { opts = @p.parse %w(--arg /fdasfasef/fessafef/asdfasdfa/fesasf) }
894
+ end
873
895
  end
874
896
 
875
897
  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.9"
4
+ version: "1.10"
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Morgan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-20 00:00:00 -07:00
12
+ date: 2008-10-21 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,9 +20,9 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 1.7.0
23
+ version: 1.8.0
24
24
  version:
25
- 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. #################### ###### simple ###### #################### require 'trollop' opts = Trollop::options do opt :monkey, \"Use monkey mode\" opt :goat, \"Use goat mode\", :default => true opt :num_limbs, \"Set number of limbs\", :default => 4 end p opts # { :monkey => false, :goat => true, :num_limbs => 4 } #################### ###### medium ###### #################### require 'trollop' opts = Trollop::options do version \"test 1.2.3 (c) 2007 William Morgan\" banner <<-EOS Test is an awesome program that does something very, very important. Usage: test [options] <filenames>+ where [options] are: EOS opt :ignore, \"Ignore incorrect values\" opt :file, \"Extra data filename to read in, with a very long option description like this one\", :type => String opt :volume, \"Volume level\", :default => 3.0 opt :iters, \"Number of iterations\", :default => 5 end Trollop::die :volume, \"must be non-negative\" if opts[:volume] < 0 Trollop::die :file, \"must exist\" unless File.exist?(opts[:file]) if opts[:file] ################################ ##### sub-command support ###### ################################ require 'trollop' global_opts = Trollop::options do opt :global_option, \"This is a global option\" stop_on %w(sub-command-1 sub-command-2) end cmd = ARGV.shift cmd_opts = Trollop::options do opt :cmd_option, \"This is an option only for the subcommand\" end p global_opts p cmd p cmd_opts"
25
+ 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
26
  email: wmorgan-trollop@masanjin.net
27
27
  executables: []
28
28