trollop 1.9 → 1.10

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.
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