getopt 1.3.9 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ == 1.4.0 - 5-Sep-2009
2
+ * Fixed a packaging bug where the libs weren't actually being included! Gah!
3
+ Thanks go to Steven Hilton for the spot.
4
+ * Other minor refactorings to the gemspec.
5
+ * The release number does not reflect any code changes. I simply ran out
6
+ of numbers. :)
7
+
1
8
  == 1.3.9 - 29-Jul-2009
2
9
  * Now compatible with Ruby 1.9.x.
3
10
  * Gemspec updates, including a license change to Artistic 2.0.
data/README CHANGED
@@ -180,6 +180,4 @@ INCREMENT
180
180
  All Rights Reserved
181
181
 
182
182
  == Author
183
- Daniel J. Berger
184
- djberg96 at nospam at gmail.com
185
- imperator on IRC (freenode)
183
+ Daniel J. Berger
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ desc "Install the getopt package (non-gem)"
5
+ task :install do
6
+ dest = File.join(Config::CONFIG['sitelibdir'], 'getopt')
7
+ Dir.mkdir(dest) unless File.exists? dest
8
+ cp 'lib/getopt/std.rb', dest, :verbose => true
9
+ cp 'lib/getopt/long.rb', dest, :verbose => true
10
+ end
11
+
12
+ desc "Install the getopt package as a gem"
13
+ task :install_gem do
14
+ ruby 'getopt.gemspec'
15
+ file = Dir["*.gem"].first
16
+ sh "gem install #{file}"
17
+ end
18
+
19
+ Rake::TestTask.new do |t|
20
+ t.warning = true
21
+ t.verbose = true
22
+ end
23
+
24
+ Rake::TestTask.new('test_getopt_long') do |t|
25
+ t.test_files = 'test/test_getopt_long.rb'
26
+ t.warning = true
27
+ t.verbose = true
28
+ end
29
+
30
+ Rake::TestTask.new('test_getopt_std') do |t|
31
+ t.test_files = 'test/test_getopt_std.rb'
32
+ t.warning = true
33
+ t.verbose = true
34
+ end
data/getopt.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+
3
+ spec = Gem::Specification.new do |gem|
4
+ gem.name = 'getopt'
5
+ gem.version = '1.4.0'
6
+ gem.author = 'Daniel J. Berger'
7
+ gem.license = 'Artistic 2.0'
8
+ gem.email = 'djberg96@gmail.com'
9
+ gem.homepage = 'http://www.rubyforge.org/projects/shards'
10
+ gem.platform = Gem::Platform::RUBY
11
+ gem.summary = 'Getopt::Std and Getopt::Long option parsers for Ruby'
12
+ gem.test_files = Dir['test/*.rb']
13
+ gem.has_rdoc = true
14
+ gem.files = Dir['**/*'].reject{ |f| f.include?('CVS') }
15
+
16
+ gem.rubyforge_project = 'shards'
17
+ gem.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
18
+
19
+ gem.add_development_dependency('test-unit', '>= 2.0.3')
20
+
21
+ gem.description = <<-EOF
22
+ The getopt library provides two different command line option parsers.
23
+ They are meant as easier and more convenient replacements for the
24
+ command line parsers that ship as part of the Ruby standard library.
25
+ Please see the README for additional comments.
26
+ EOF
27
+ end
28
+
29
+ Gem::Builder.new(spec).build
@@ -0,0 +1,244 @@
1
+ # The Getopt module serves as a namespace only
2
+ module Getopt
3
+
4
+ REQUIRED = 0 # Argument is required if switch is provided.
5
+ BOOLEAN = 1 # Value of argument is true if provided, false otherwise.
6
+ OPTIONAL = 2 # Argument is optional if switch is provided.
7
+ INCREMENT = 3 # Argument is incremented by 1 each time the switch appears.
8
+
9
+ # NEGATABLE = 4 # Automatically provide negative switch equivalent.
10
+ # INTEGER = 5 # Argument automatically converted to integer if provided.
11
+ # FLOAT = 6 # Argument automatically converted to float if provided.
12
+
13
+ # The Getopt::Long class encapsulates longhanded parameter parsing options
14
+ class Long
15
+
16
+ # Error raised if an illegal option or argument is passed
17
+ class Error < StandardError; end
18
+
19
+ # The version of the getopt library
20
+ VERSION = '1.4.0'
21
+
22
+ # Takes an array of switches. Each array consists of up to three
23
+ # elements that indicate the name and type of switch. Returns a hash
24
+ # containing each switch name, minus the '-', as a key. The value
25
+ # for each key depends on the type of switch and/or the value provided
26
+ # by the user.
27
+ #
28
+ # The long switch _must_ be provided. The short switch defaults to the
29
+ # first letter of the short switch. The default type is BOOLEAN.
30
+ #
31
+ # Example:
32
+ #
33
+ # opts = Getopt::Long.getopts(
34
+ # ['--debug' ],
35
+ # ['--verbose', '-v' ],
36
+ # ['--level', '-l', INCREMENT]
37
+ # )
38
+ #
39
+ # See the README file for more information.
40
+ #
41
+ def self.getopts(*switches)
42
+ if switches.empty?
43
+ raise ArgumentError, 'no switches provided'
44
+ end
45
+
46
+ hash = {} # Hash returned to user
47
+ valid = [] # Tracks valid switches
48
+ types = {} # Tracks argument types
49
+ syns = {} # Tracks long and short arguments, or multiple shorts
50
+
51
+ # If a string is passed, split it and convert it to an array of arrays
52
+ if switches.first.kind_of?(String)
53
+ switches = switches.join.split
54
+ switches.map!{ |switch| switch = [switch] }
55
+ end
56
+
57
+ # Set our list of valid switches, and proper types for each switch
58
+ switches.each{ |switch|
59
+ valid.push(switch[0]) # Set valid long switches
60
+
61
+ # Set type for long switch, default to BOOLEAN.
62
+ if switch[1].kind_of?(Fixnum)
63
+ switch[2] = switch[1]
64
+ types[switch[0]] = switch[2]
65
+ switch[1] = switch[0][1..2]
66
+ else
67
+ switch[2] ||= BOOLEAN
68
+ types[switch[0]] = switch[2]
69
+ switch[1] ||= switch[0][1..2]
70
+ end
71
+
72
+ # Create synonym hash. Default to first char of long switch for
73
+ # short switch, e.g. "--verbose" creates a "-v" synonym. The same
74
+ # synonym can only be used once - first one wins.
75
+ syns[switch[0]] = switch[1] unless syns[switch[1]]
76
+ syns[switch[1]] = switch[0] unless syns[switch[1]]
77
+
78
+ switch[1] = [switch[1]] if RUBY_VERSION.to_f >= 1.9
79
+
80
+ switch[1].each{ |char|
81
+ types[char] = switch[2] # Set type for short switch
82
+ valid.push(char) # Set valid short switches
83
+ }
84
+ }
85
+
86
+ re_long = /^(--\w+[-\w+]*)?$/
87
+ re_short = /^(-\w)$/
88
+ re_long_eq = /^(--\w+[-\w+]*)?=(.*?)$|(-\w?)=(.*?)$/
89
+ re_short_sq = /^(-\w)(\S+?)$/
90
+
91
+ ARGV.each_with_index{ |opt, index|
92
+
93
+ # Allow either -x -v or -xv style for single char args
94
+ if re_short_sq.match(opt)
95
+ chars = opt.split("")[1..-1].map{ |s| s = "-#{s}" }
96
+
97
+ chars.each_with_index{ |char, i|
98
+ unless valid.include?(char)
99
+ raise Error, "invalid switch '#{char}'"
100
+ end
101
+
102
+ # Grab the next arg if the switch takes a required arg
103
+ if types[char] == REQUIRED
104
+ # Deal with a argument squished up against switch
105
+ if chars[i+1]
106
+ arg = chars[i+1..-1].join.tr('-', '')
107
+ ARGV.push(char, arg)
108
+ break
109
+ else
110
+ arg = ARGV.delete_at(index+1)
111
+ if arg.nil? || valid.include?(arg) # Minor cheat here
112
+ err = "no value provided for required argument '#{char}'"
113
+ raise Error, err
114
+ end
115
+ ARGV.push(char, arg)
116
+ end
117
+ elsif types[char] == OPTIONAL
118
+ if chars[i+1] && !valid.include?(chars[i+1])
119
+ arg = chars[i+1..-1].join.tr("-","")
120
+ ARGV.push(char, arg)
121
+ break
122
+ elsif
123
+ if ARGV[index+1] && !valid.include?(ARGV[index+1])
124
+ arg = ARGV.delete_at(index+1)
125
+ ARGV.push(char, arg)
126
+ end
127
+ else
128
+ ARGV.push(char)
129
+ end
130
+ else
131
+ ARGV.push(char)
132
+ end
133
+ }
134
+ next
135
+ end
136
+
137
+ if match = re_long.match(opt) || match = re_short.match(opt)
138
+ switch = match.captures.first
139
+ end
140
+
141
+ if match = re_long_eq.match(opt)
142
+ switch, value = match.captures.compact
143
+ ARGV.push(switch, value)
144
+ next
145
+ end
146
+
147
+ # Make sure that all the switches are valid. If 'switch' isn't
148
+ # defined at this point, it means an option was passed without
149
+ # a preceding switch, e.g. --option foo bar.
150
+ unless valid.include?(switch)
151
+ switch ||= opt
152
+ raise Error, "invalid switch '#{switch}'"
153
+ end
154
+
155
+ # Required arguments
156
+ if types[switch] == REQUIRED
157
+ nextval = ARGV[index+1]
158
+
159
+ # Make sure there's a value for mandatory arguments
160
+ if nextval.nil?
161
+ err = "no value provided for required argument '#{switch}'"
162
+ raise Error, err
163
+ end
164
+
165
+ # If there is a value, make sure it's not another switch
166
+ if valid.include?(nextval)
167
+ err = "cannot pass switch '#{nextval}' as an argument"
168
+ raise Error, err
169
+ end
170
+
171
+ # If the same option appears more than once, put the values
172
+ # in array.
173
+ if hash[switch]
174
+ hash[switch] = [hash[switch], nextval].flatten
175
+ else
176
+ hash[switch] = nextval
177
+ end
178
+ ARGV.delete_at(index+1)
179
+ end
180
+
181
+ # For boolean arguments set the switch's value to true.
182
+ if types[switch] == BOOLEAN
183
+ if hash.has_key?(switch)
184
+ raise Error, 'boolean switch already set'
185
+ end
186
+ hash[switch] = true
187
+ end
188
+
189
+ # For increment arguments, set the switch's value to 0, or
190
+ # increment it by one if it already exists.
191
+ if types[switch] == INCREMENT
192
+ if hash.has_key?(switch)
193
+ hash[switch] += 1
194
+ else
195
+ hash[switch] = 1
196
+ end
197
+ end
198
+
199
+ # For optional argument, there may be an argument. If so, it
200
+ # cannot be another switch. If not, it is set to true.
201
+ if types[switch] == OPTIONAL
202
+ nextval = ARGV[index+1]
203
+ if valid.include?(nextval)
204
+ hash[switch] = true
205
+ else
206
+ hash[switch] = nextval
207
+ ARGV.delete_at(index+1)
208
+ end
209
+ end
210
+ }
211
+
212
+ # Set synonymous switches to the same value, e.g. if -t is a synonym
213
+ # for --test, and the user passes "--test", then set "-t" to the same
214
+ # value that "--test" was set to.
215
+ #
216
+ # This allows users to refer to the long or short switch and get
217
+ # the same value
218
+ hash.each{ |switch, val|
219
+ if syns.keys.include?(switch)
220
+ syns[switch] = [syns[switch]] if RUBY_VERSION.to_f >= 1.9
221
+ syns[switch].each{ |key|
222
+ hash[key] = val
223
+ }
224
+ end
225
+ }
226
+
227
+ # Get rid of leading "--" and "-" to make it easier to reference
228
+ hash.each{ |key, value|
229
+ if key =~ /^-/
230
+ if key[0,2] == '--'
231
+ nkey = key.sub('--', '')
232
+ else
233
+ nkey = key.sub('-', '')
234
+ end
235
+ hash.delete(key)
236
+ hash[nkey] = value
237
+ end
238
+ }
239
+
240
+ hash
241
+ end
242
+
243
+ end
244
+ end
data/lib/getopt/std.rb ADDED
@@ -0,0 +1,108 @@
1
+ # The Getopt module serves as a namespace only
2
+ module Getopt
3
+
4
+ # The Getopt::Std class serves as a base class for the getopts method.
5
+ class Std
6
+
7
+ # The Getopt::Std::Error class is raised if there are any illegal
8
+ # command line arguments.
9
+ #
10
+ class Error < StandardError; end
11
+
12
+ # The version of the getopt library
13
+ VERSION = '1.4.0'
14
+
15
+ # Processes single character command line options with option
16
+ # clustering. This information is parsed from ARGV and returned
17
+ # as a hash, with the switch (minus the "-") as the key. The value
18
+ # for that key is either true/false (boolean switches) or the argument
19
+ # that was passed to the switch.
20
+ #
21
+ # Characters followed by a ":" require an argument. The rest are
22
+ # considered boolean switches. If a switch that accepts an argument
23
+ # appears more than once, the value for that key becomes an array
24
+ # of values.
25
+ #
26
+ # Example:
27
+ #
28
+ # # Look for -o with argument, and -I and -D boolean arguments
29
+ # opt = Getopt::Std.getopts("o:ID")
30
+ #
31
+ # if opt["I"]
32
+ # # Do something if -I passed
33
+ # end
34
+ #
35
+ # if opt["D"]
36
+ # # Do something if -D passed
37
+ # end
38
+ #
39
+ # if opt["o"]
40
+ # case opt["o"]
41
+ # # Do something
42
+ # end
43
+ # end
44
+ #
45
+ def self.getopts(switches)
46
+ args = switches.split(/ */)
47
+ hash = {}
48
+
49
+ while !ARGV.empty? && ARGV.first =~ /^-(.)(.*)/s
50
+ first, rest = $1, $2
51
+ pos = switches.index(first)
52
+
53
+ # Switches on the command line must appear among the characters
54
+ # declared in +switches+.
55
+ raise Error, "invalid option '#{first}'" unless pos
56
+
57
+ if args[pos+1] == ":"
58
+ ARGV.shift
59
+ if rest.empty?
60
+ rest = ARGV.shift
61
+
62
+ # Ensure that switches requiring arguments actually
63
+ # receive a (non-switch) argument.
64
+ if rest.nil? || rest.empty?
65
+ raise Error, "missing argument for '-#{args[pos]}'"
66
+ end
67
+
68
+ # Do not permit switches that require arguments to be
69
+ # followed immediately by another switch.
70
+ temp_args = args.map{ |e| "-#{e}" }
71
+
72
+ if temp_args.include?(rest) || temp_args.include?(rest[1..-1])
73
+ err = "cannot use switch '#{rest}' as argument "
74
+ err << "to another switch"
75
+ raise Error, err
76
+ end
77
+
78
+ # For non boolean switches, arguments that appear multiple
79
+ # times are converted to an array (or pushed onto an already
80
+ # existant array).
81
+ if hash.has_key?(first)
82
+ hash[first] = [hash[first], rest].flatten
83
+ else
84
+ hash[first] = rest
85
+ end
86
+ else
87
+ # Do not permit switches that require arguments to be
88
+ # followed immediately by another switch.
89
+ if args.include?(rest) || args.include?(rest[1..-1])
90
+ err = "cannot use switch '#{rest}' as argument "
91
+ err += "to another switch"
92
+ raise Error, err
93
+ end
94
+ end
95
+ else
96
+ hash[first] = true # Boolean switch
97
+ if rest.empty?
98
+ ARGV.shift
99
+ else
100
+ ARGV[0] = "-#{rest}"
101
+ end
102
+ end
103
+ end
104
+
105
+ hash
106
+ end
107
+ end
108
+ end
@@ -17,7 +17,7 @@ class TC_Getopt_Long < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  def test_version
20
- assert_equal('1.3.9', Long::VERSION)
20
+ assert_equal('1.4.0', Long::VERSION)
21
21
  end
22
22
 
23
23
  def test_constants
@@ -14,7 +14,7 @@ include Getopt
14
14
  class TC_Getopt_Std < Test::Unit::TestCase
15
15
 
16
16
  def test_version
17
- assert_equal('1.3.9', Std::VERSION)
17
+ assert_equal('1.4.0', Std::VERSION)
18
18
  end
19
19
 
20
20
  def test_getopts_basic
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: getopt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.9
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-29 00:00:00 -06:00
12
+ date: 2009-09-05 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -33,13 +33,17 @@ extra_rdoc_files:
33
33
  - CHANGES
34
34
  - MANIFEST
35
35
  files:
36
+ - CHANGES
36
37
  - examples/example_long.rb
37
38
  - examples/example_std.rb
39
+ - getopt.gemspec
40
+ - lib/getopt/long.rb
41
+ - lib/getopt/std.rb
42
+ - MANIFEST
43
+ - Rakefile
44
+ - README
38
45
  - test/test_getopt_long.rb
39
46
  - test/test_getopt_std.rb
40
- - README
41
- - CHANGES
42
- - MANIFEST
43
47
  has_rdoc: true
44
48
  homepage: http://www.rubyforge.org/projects/shards
45
49
  licenses: