darksky-ruby 0.0.2 → 1.0.0
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.
- checksums.yaml +5 -5
- data/LICENSE +21 -0
- data/README.md +84 -0
- data/bin/darksky +4 -4
- data/darksky-ruby.gemspec +4 -4
- data/lib/darksky-ruby/api.rb +1 -1
- data/lib/darksky-ruby/{trollop.rb → optimist.rb} +381 -278
- metadata +7 -7
- data/lib/darksky-ruby/version.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cbc838749139b38df86429dd389d8758c5202fd9c77cf4ee7c8c3dc195e79ab3
|
4
|
+
data.tar.gz: 0ef99dc1e4d4d3dccf3b206118da701b2655a89e05576fee1f6ddd3e366cf809
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18eb161d289183c5b59dcef356665988db7e2f34d1d6a77d32a74f951b565f1960a5c65e6e95a9480b57622452a9fea8b2d1cdabbc8b34eb5eab6ad7518915fc
|
7
|
+
data.tar.gz: 2e7f16e29f5e1f566a55cabfb2fb58652cf02f66b4960eb9858b97efe76fe860c7d4fd1d0563f4d844ec14518de3b2be99640100197dc7c09b59b8f34925fb09
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Ken J.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# darksky-ruby
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/kajiki)
|
4
|
+
|
5
|
+
Pure simple Ruby based [Dark Sky API](https://darksky.net/dev/) gem
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
```
|
10
|
+
$ gem install darksky-ruby
|
11
|
+
```
|
12
|
+
|
13
|
+
## Use
|
14
|
+
|
15
|
+
### [Forecast Request](https://darksky.net/dev/docs#forecast-request)
|
16
|
+
|
17
|
+
Example of querying weather forecast for [SFO](https://www.airport-sfo.com/).
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'darksky-ruby'
|
21
|
+
|
22
|
+
api = DarkSkyAPI.new(key: 'Your_Dark_Sky_API_Secret_Key')
|
23
|
+
data = api.forecast(lat: 37.6211, lon: -122.383)
|
24
|
+
p data[:hourly][:summary]
|
25
|
+
# => "Partly cloudy throughout the day."
|
26
|
+
```
|
27
|
+
|
28
|
+
### [Time Machine Request](https://darksky.net/dev/docs#time-machine-request)
|
29
|
+
|
30
|
+
Requesting observed weather for noon of Jan. 1, 2018 at SFO.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
data = api.timemachine(lat: 37.6211, lon: -122.383, ts: Time.new(2018,1,1,12))
|
34
|
+
p data[:currently][:temperature]
|
35
|
+
# => 57.56
|
36
|
+
```
|
37
|
+
|
38
|
+
### [Response Format](https://darksky.net/dev/docs#response-format)
|
39
|
+
|
40
|
+
`data` in above examples would contain a Ruby Hash of the entire API response; all keys are symbolized.
|
41
|
+
|
42
|
+
### Options
|
43
|
+
|
44
|
+
You can limit the response data size by excluding unnecessary blocks.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
api.blocks = {minutely: false, hourly: false} # excludes blocks marked false
|
48
|
+
api.include_only([:currently, :alerts]) # excludes everything except specified
|
49
|
+
api.blocks
|
50
|
+
# => {:currently=>true, :minutely=>false, :hourly=>false, :daily=>false,
|
51
|
+
# :alerts=>true, :flags=>false}
|
52
|
+
```
|
53
|
+
|
54
|
+
Hint, you can use `api.blocks` first to get a default Hash to get started. After you've modified the Hash, you can save it with `api.blocks =`.
|
55
|
+
|
56
|
+
Other options can be set like so.
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
api.options = {lang: 'es', units: 'si'} # Spanish language, SI units
|
60
|
+
data = api.timemachine(lat: 37.6211, lon: -122.383, ts: Time.new(2018,1,1,12))
|
61
|
+
p data[:currently][:summary]
|
62
|
+
# => "Parcialmente Nublado"
|
63
|
+
p data[:currently][:temperature]
|
64
|
+
# => 14.2
|
65
|
+
```
|
66
|
+
|
67
|
+
## CLI
|
68
|
+
|
69
|
+
This gem includes an executable as an example.
|
70
|
+
|
71
|
+
```
|
72
|
+
$ darksky -h
|
73
|
+
darksky [options] <LAT,LON>
|
74
|
+
-k, --key=<s> API secret key
|
75
|
+
-l, --loc=<s> Location (latitude,longtitude)
|
76
|
+
-o, --log=<s> Log file
|
77
|
+
-t, --time=<s> Timestamp for Time Machine request
|
78
|
+
-v, --verbose Verbose mode
|
79
|
+
-h, --help Show this message
|
80
|
+
```
|
81
|
+
|
82
|
+
## More
|
83
|
+
|
84
|
+
Since this is a simple gem with no external dependencies, you can directly include the `lib` contents in your project if you prefer not to use Ruby Gems, such as in [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/ruby-package.html). If you do, be sure to include my copyright and license details.
|
data/bin/darksky
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require 'darksky-ruby/
|
2
|
+
require 'darksky-ruby/optimist'
|
3
3
|
require 'darksky-ruby'
|
4
4
|
|
5
5
|
|
6
|
-
opts =
|
6
|
+
opts = Optimist::options do
|
7
7
|
banner "darksky [options] <LAT,LON>"
|
8
8
|
opt :key, 'API secret key', type: :string
|
9
9
|
opt :loc, 'Location (latitude,longtitude)', type: :string
|
@@ -28,9 +28,9 @@ log.debug("Command line arguments: #{opts}")
|
|
28
28
|
loc = opts[:loc]
|
29
29
|
loc ||= ARGV.shift
|
30
30
|
|
31
|
-
|
31
|
+
Optimist::die :loc, "is missing" if loc.nil?
|
32
32
|
|
33
|
-
api =
|
33
|
+
api = DarkSkyAPI.new(key: opts[:key])
|
34
34
|
api.blocks = {minutely: false, hourly: false, daily: false, alerts: false, flags: false}
|
35
35
|
|
36
36
|
if opts[:time_given]
|
data/darksky-ruby.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
2
|
-
require 'darksky-ruby
|
2
|
+
require 'darksky-ruby'
|
3
3
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'darksky-ruby'
|
7
|
-
s.version =
|
7
|
+
s.version = '1.0.0'
|
8
8
|
s.authors = ['Ken J.']
|
9
9
|
s.email = ['kenjij@gmail.com']
|
10
|
-
s.summary = %q{Pure simple Ruby based
|
11
|
-
s.description = %q{
|
10
|
+
s.summary = %q{Pure simple Ruby based Dark Sky API gem}
|
11
|
+
s.description = %q{Dark Sky gem written in pure Ruby without any external dependency.}
|
12
12
|
s.homepage = 'https://github.com/kenjij/darksky-ruby'
|
13
13
|
s.license = 'MIT'
|
14
14
|
|
data/lib/darksky-ruby/api.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
# lib/
|
1
|
+
# lib/optimist.rb -- optimist command-line processing library
|
2
2
|
# Copyright (c) 2008-2014 William Morgan.
|
3
3
|
# Copyright (c) 2014 Red Hat, Inc.
|
4
|
-
#
|
4
|
+
# optimist is licensed under the MIT license.
|
5
5
|
|
6
6
|
require 'date'
|
7
7
|
|
8
|
-
module
|
8
|
+
module Optimist
|
9
9
|
# note: this is duplicated in gemspec
|
10
10
|
# please change over there too
|
11
|
-
VERSION = "
|
11
|
+
VERSION = "3.0.0"
|
12
12
|
|
13
13
|
## Thrown by Parser in the event of a commandline error. Not needed if
|
14
|
-
## you're using the
|
14
|
+
## you're using the Optimist::options entry.
|
15
15
|
class CommandlineError < StandardError
|
16
16
|
attr_reader :error_code
|
17
17
|
|
@@ -22,12 +22,12 @@ class CommandlineError < StandardError
|
|
22
22
|
end
|
23
23
|
|
24
24
|
## Thrown by Parser if the user passes in '-h' or '--help'. Handled
|
25
|
-
## automatically by
|
25
|
+
## automatically by Optimist#options.
|
26
26
|
class HelpNeeded < StandardError
|
27
27
|
end
|
28
28
|
|
29
29
|
## Thrown by Parser if the user passes in '-v' or '--version'. Handled
|
30
|
-
## automatically by
|
30
|
+
## automatically by Optimist#options.
|
31
31
|
class VersionNeeded < StandardError
|
32
32
|
end
|
33
33
|
|
@@ -38,15 +38,38 @@ FLOAT_RE = /^-?((\d+(\.\d+)?)|(\.\d+))([eE][-+]?[\d]+)?$/
|
|
38
38
|
PARAM_RE = /^-(-|\.$|[^\d\.])/
|
39
39
|
|
40
40
|
## The commandline parser. In typical usage, the methods in this class
|
41
|
-
## will be handled internally by
|
41
|
+
## will be handled internally by Optimist::options. In this case, only the
|
42
42
|
## #opt, #banner and #version, #depends, and #conflicts methods will
|
43
43
|
## typically be called.
|
44
44
|
##
|
45
45
|
## If you want to instantiate this class yourself (for more complicated
|
46
46
|
## argument-parsing logic), call #parse to actually produce the output hash,
|
47
47
|
## and consider calling it from within
|
48
|
-
##
|
48
|
+
## Optimist::with_standard_exception_handling.
|
49
49
|
class Parser
|
50
|
+
|
51
|
+
## The registry is a class-instance-variable map of option aliases to their subclassed Option class.
|
52
|
+
@registry = {}
|
53
|
+
|
54
|
+
## The Option subclasses are responsible for registering themselves using this function.
|
55
|
+
def self.register(lookup, klass)
|
56
|
+
@registry[lookup.to_sym] = klass
|
57
|
+
end
|
58
|
+
|
59
|
+
## Gets the class from the registry.
|
60
|
+
## Can be given either a class-name, e.g. Integer, a string, e.g "integer", or a symbol, e.g :integer
|
61
|
+
def self.registry_getopttype(type)
|
62
|
+
return nil unless type
|
63
|
+
if type.respond_to?(:name)
|
64
|
+
type = type.name
|
65
|
+
lookup = type.downcase.to_sym
|
66
|
+
else
|
67
|
+
lookup = type.to_sym
|
68
|
+
end
|
69
|
+
raise ArgumentError, "Unsupported argument type '#{type}', registry lookup '#{lookup}'" unless @registry.has_key?(lookup)
|
70
|
+
return @registry[lookup].new
|
71
|
+
end
|
72
|
+
|
50
73
|
INVALID_SHORT_ARG_REGEX = /[\d-]/ #:nodoc:
|
51
74
|
|
52
75
|
## The values from the commandline that were not interpreted by #parse.
|
@@ -75,7 +98,7 @@ class Parser
|
|
75
98
|
@educate_on_error = false
|
76
99
|
@synopsis = nil
|
77
100
|
@usage = nil
|
78
|
-
|
101
|
+
|
79
102
|
# instance_eval(&b) if b # can't take arguments
|
80
103
|
cloaker(&b).bind(self).call(*a) if b
|
81
104
|
end
|
@@ -90,7 +113,7 @@ class Parser
|
|
90
113
|
## [+: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.
|
91
114
|
## [+:short+] Specify the short form of the argument, i.e. the form with one dash. If unspecified, will be automatically derived from +name+. Use :none: to not have a short value.
|
92
115
|
## [+: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.
|
93
|
-
## [+:default+] Set the default value for an argument. Without a default value, the hash returned by #parse (and thus
|
116
|
+
## [+:default+] Set the default value for an argument. Without a default value, the hash returned by #parse (and thus Optimist::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+.
|
94
117
|
## [+:required+] If set to +true+, the argument must be provided on the commandline.
|
95
118
|
## [+: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.)
|
96
119
|
##
|
@@ -116,7 +139,7 @@ class Parser
|
|
116
139
|
## There's one ambiguous case to be aware of: when +:multi+: is true and a
|
117
140
|
## +:default+ is set to an array (of something), it's ambiguous whether this
|
118
141
|
## is a multi-value argument as well as a multi-occurrence argument.
|
119
|
-
## In thise case,
|
142
|
+
## In thise case, Optimist assumes that it's not a multi-value argument.
|
120
143
|
## If you want a multi-value, multi-occurrence argument with a default
|
121
144
|
## value, you must specify +:type+ as well.
|
122
145
|
|
@@ -164,7 +187,7 @@ class Parser
|
|
164
187
|
|
165
188
|
## Marks two (or more!) options as requiring each other. Only handles
|
166
189
|
## undirected (i.e., mutual) dependencies. Directed dependencies are
|
167
|
-
## better modeled with
|
190
|
+
## better modeled with Optimist::die.
|
168
191
|
def depends(*syms)
|
169
192
|
syms.each { |sym| raise ArgumentError, "unknown option '#{sym}'" unless @specs[sym] }
|
170
193
|
@constraints << [:depends, syms]
|
@@ -182,7 +205,7 @@ class Parser
|
|
182
205
|
## intact.
|
183
206
|
##
|
184
207
|
## A typical use case would be for subcommand support, where these
|
185
|
-
## would be set to the list of subcommands. A subsequent
|
208
|
+
## would be set to the list of subcommands. A subsequent Optimist
|
186
209
|
## invocation would then be used to parse subcommand options, after
|
187
210
|
## shifting the subcommand off of ARGV.
|
188
211
|
def stop_on(*words)
|
@@ -203,7 +226,7 @@ class Parser
|
|
203
226
|
@educate_on_error = true
|
204
227
|
end
|
205
228
|
|
206
|
-
## Parses the commandline. Typically called by
|
229
|
+
## Parses the commandline. Typically called by Optimist::options,
|
207
230
|
## but you can call it directly if you need more control.
|
208
231
|
##
|
209
232
|
## throws CommandlineError, HelpNeeded, and VersionNeeded exceptions.
|
@@ -240,7 +263,7 @@ class Parser
|
|
240
263
|
|
241
264
|
sym = nil if arg =~ /--no-/ # explicitly invalidate --no-no- arguments
|
242
265
|
|
243
|
-
next
|
266
|
+
next nil if ignore_invalid_options && !sym
|
244
267
|
raise CommandlineError, "unknown argument '#{arg}'" unless sym
|
245
268
|
|
246
269
|
if given_args.include?(sym) && !@specs[sym].multi?
|
@@ -255,7 +278,7 @@ class Parser
|
|
255
278
|
# The block returns the number of parameters taken.
|
256
279
|
num_params_taken = 0
|
257
280
|
|
258
|
-
unless params.
|
281
|
+
unless params.empty?
|
259
282
|
if @specs[sym].single_arg?
|
260
283
|
given_args[sym][:params] << params[0, 1] # take the first parameter
|
261
284
|
num_params_taken = 1
|
@@ -301,20 +324,7 @@ class Parser
|
|
301
324
|
|
302
325
|
vals["#{sym}_given".intern] = true # mark argument as specified on the commandline
|
303
326
|
|
304
|
-
|
305
|
-
when :flag
|
306
|
-
vals[sym] = (sym.to_s =~ /^no_/ ? negative_given : !negative_given)
|
307
|
-
when :int, :ints
|
308
|
-
vals[sym] = params.map { |pg| pg.map { |p| parse_integer_parameter p, arg } }
|
309
|
-
when :float, :floats
|
310
|
-
vals[sym] = params.map { |pg| pg.map { |p| parse_float_parameter p, arg } }
|
311
|
-
when :string, :strings
|
312
|
-
vals[sym] = params.map { |pg| pg.map(&:to_s) }
|
313
|
-
when :io, :ios
|
314
|
-
vals[sym] = params.map { |pg| pg.map { |p| parse_io_parameter p, arg } }
|
315
|
-
when :date, :dates
|
316
|
-
vals[sym] = params.map { |pg| pg.map { |p| parse_date_parameter p, arg } }
|
317
|
-
end
|
327
|
+
vals[sym] = opts.parse(params, negative_given)
|
318
328
|
|
319
329
|
if opts.single_arg?
|
320
330
|
if opts.multi? # multiple options, each with a single parameter
|
@@ -344,41 +354,13 @@ class Parser
|
|
344
354
|
vals
|
345
355
|
end
|
346
356
|
|
347
|
-
def parse_date_parameter(param, arg) #:nodoc:
|
348
|
-
begin
|
349
|
-
require 'chronic'
|
350
|
-
time = Chronic.parse(param)
|
351
|
-
rescue LoadError
|
352
|
-
# chronic is not available
|
353
|
-
end
|
354
|
-
time ? Date.new(time.year, time.month, time.day) : Date.parse(param)
|
355
|
-
rescue ArgumentError
|
356
|
-
raise CommandlineError, "option '#{arg}' needs a date"
|
357
|
-
end
|
358
|
-
|
359
357
|
## Print the help message to +stream+.
|
360
358
|
def educate(stream = $stdout)
|
361
359
|
width # hack: calculate it now; otherwise we have to be careful not to
|
362
360
|
# call this unless the cursor's at the beginning of a line.
|
361
|
+
|
363
362
|
left = {}
|
364
|
-
@specs.each
|
365
|
-
left[name] =
|
366
|
-
(spec.short? ? "-#{spec.short}, " : "") + "--#{spec.long}" +
|
367
|
-
case spec.type
|
368
|
-
when :flag then ""
|
369
|
-
when :int then "=<i>"
|
370
|
-
when :ints then "=<i+>"
|
371
|
-
when :string then "=<s>"
|
372
|
-
when :strings then "=<s+>"
|
373
|
-
when :float then "=<f>"
|
374
|
-
when :floats then "=<f+>"
|
375
|
-
when :io then "=<filename/uri>"
|
376
|
-
when :ios then "=<filename/uri+>"
|
377
|
-
when :date then "=<date>"
|
378
|
-
when :dates then "=<date+>"
|
379
|
-
end +
|
380
|
-
(spec.flag? && spec.default ? ", --no-#{spec.long}" : "")
|
381
|
-
end
|
363
|
+
@specs.each { |name, spec| left[name] = spec.educate }
|
382
364
|
|
383
365
|
leftcol_width = left.values.map(&:length).max || 0
|
384
366
|
rightcol_start = leftcol_width + 6 # spaces
|
@@ -400,27 +382,8 @@ class Parser
|
|
400
382
|
|
401
383
|
spec = @specs[opt]
|
402
384
|
stream.printf " %-#{leftcol_width}s ", left[opt]
|
403
|
-
desc = spec.
|
404
|
-
default_s = case spec.default
|
405
|
-
when $stdout then "<stdout>"
|
406
|
-
when $stdin then "<stdin>"
|
407
|
-
when $stderr then "<stderr>"
|
408
|
-
when Array
|
409
|
-
spec.default.join(", ")
|
410
|
-
else
|
411
|
-
spec.default.to_s
|
412
|
-
end
|
385
|
+
desc = spec.description_with_default
|
413
386
|
|
414
|
-
if spec.default
|
415
|
-
if spec.desc =~ /\.$/
|
416
|
-
" (Default: #{default_s})"
|
417
|
-
else
|
418
|
-
" (default: #{default_s})"
|
419
|
-
end
|
420
|
-
else
|
421
|
-
""
|
422
|
-
end
|
423
|
-
end
|
424
387
|
stream.puts wrap(desc, :width => width - rightcol_start - 1, :prefix => rightcol_start)
|
425
388
|
end
|
426
389
|
end
|
@@ -460,8 +423,9 @@ class Parser
|
|
460
423
|
end
|
461
424
|
end
|
462
425
|
|
463
|
-
## The per-parser version of
|
426
|
+
## The per-parser version of Optimist::die (see that for documentation).
|
464
427
|
def die(arg, msg = nil, error_code = nil)
|
428
|
+
msg, error_code = nil, msg if msg.kind_of?(Integer)
|
465
429
|
if msg
|
466
430
|
$stderr.puts "Error: argument --#{@specs[arg].long} #{msg}."
|
467
431
|
else
|
@@ -489,47 +453,60 @@ private
|
|
489
453
|
when /^--$/ # arg terminator
|
490
454
|
return remains += args[(i + 1)..-1]
|
491
455
|
when /^--(\S+?)=(.*)$/ # long argument with equals
|
492
|
-
yield "--#{$1}", [$2]
|
456
|
+
num_params_taken = yield "--#{$1}", [$2]
|
457
|
+
if num_params_taken.nil?
|
458
|
+
remains << args[i]
|
459
|
+
if @stop_on_unknown
|
460
|
+
return remains += args[i + 1..-1]
|
461
|
+
end
|
462
|
+
end
|
493
463
|
i += 1
|
494
464
|
when /^--(\S+)$/ # long argument
|
495
465
|
params = collect_argument_parameters(args, i + 1)
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
if @stop_on_unknown
|
503
|
-
return remains += args[i + 1..-1]
|
504
|
-
else
|
505
|
-
remains += params
|
506
|
-
end
|
466
|
+
num_params_taken = yield args[i], params
|
467
|
+
|
468
|
+
if num_params_taken.nil?
|
469
|
+
remains << args[i]
|
470
|
+
if @stop_on_unknown
|
471
|
+
return remains += args[i + 1..-1]
|
507
472
|
end
|
508
|
-
|
473
|
+
else
|
474
|
+
i += num_params_taken
|
509
475
|
end
|
476
|
+
i += 1
|
510
477
|
when /^-(\S+)$/ # one or more short arguments
|
478
|
+
short_remaining = ""
|
511
479
|
shortargs = $1.split(//)
|
512
480
|
shortargs.each_with_index do |a, j|
|
513
481
|
if j == (shortargs.length - 1)
|
514
482
|
params = collect_argument_parameters(args, i + 1)
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
return remains += args[i + 1..-1]
|
523
|
-
else
|
524
|
-
remains += params
|
525
|
-
end
|
483
|
+
|
484
|
+
num_params_taken = yield "-#{a}", params
|
485
|
+
unless num_params_taken
|
486
|
+
short_remaining << a
|
487
|
+
if @stop_on_unknown
|
488
|
+
remains << "-#{short_remaining}"
|
489
|
+
return remains += args[i + 1..-1]
|
526
490
|
end
|
527
|
-
|
491
|
+
else
|
492
|
+
i += num_params_taken
|
528
493
|
end
|
529
494
|
else
|
530
|
-
yield "-#{a}",
|
495
|
+
unless yield "-#{a}", []
|
496
|
+
short_remaining << a
|
497
|
+
if @stop_on_unknown
|
498
|
+
short_remaining += shortargs[j + 1..-1].join
|
499
|
+
remains << "-#{short_remaining}"
|
500
|
+
return remains += args[i + 1..-1]
|
501
|
+
end
|
502
|
+
end
|
531
503
|
end
|
532
504
|
end
|
505
|
+
|
506
|
+
unless short_remaining.empty?
|
507
|
+
remains << "-#{short_remaining}"
|
508
|
+
end
|
509
|
+
i += 1
|
533
510
|
else
|
534
511
|
if @stop_on_unknown
|
535
512
|
return remains += args[i..-1]
|
@@ -543,29 +520,6 @@ private
|
|
543
520
|
remains
|
544
521
|
end
|
545
522
|
|
546
|
-
def parse_integer_parameter(param, arg)
|
547
|
-
raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^-?[\d_]+$/
|
548
|
-
param.to_i
|
549
|
-
end
|
550
|
-
|
551
|
-
def parse_float_parameter(param, arg)
|
552
|
-
raise CommandlineError, "option '#{arg}' needs a floating-point number" unless param =~ FLOAT_RE
|
553
|
-
param.to_f
|
554
|
-
end
|
555
|
-
|
556
|
-
def parse_io_parameter(param, arg)
|
557
|
-
if param =~ /^(stdin|-)$/i
|
558
|
-
$stdin
|
559
|
-
else
|
560
|
-
require 'open-uri'
|
561
|
-
begin
|
562
|
-
open param
|
563
|
-
rescue SystemCallError => e
|
564
|
-
raise CommandlineError, "file or url for option '#{arg}' cannot be opened: #{e.message}"
|
565
|
-
end
|
566
|
-
end
|
567
|
-
end
|
568
|
-
|
569
523
|
def collect_argument_parameters(args, start_at)
|
570
524
|
params = []
|
571
525
|
pos = start_at
|
@@ -621,173 +575,318 @@ private
|
|
621
575
|
end
|
622
576
|
end
|
623
577
|
|
624
|
-
## The option for each flag
|
625
578
|
class Option
|
626
|
-
## The set of values that indicate a flag option when passed as the
|
627
|
-
## +:type+ parameter of #opt.
|
628
|
-
FLAG_TYPES = [:flag, :bool, :boolean]
|
629
579
|
|
630
|
-
|
631
|
-
|
632
|
-
##
|
633
|
-
## A value of +io+ corresponds to a readable IO resource, including
|
634
|
-
## a filename, URI, or the strings 'stdin' or '-'.
|
635
|
-
SINGLE_ARG_TYPES = [:int, :integer, :string, :double, :float, :io, :date]
|
636
|
-
|
637
|
-
## The set of values that indicate a multiple-parameter option (i.e., that
|
638
|
-
## takes multiple space-separated values on the commandline) when passed as
|
639
|
-
## the +:type+ parameter of #opt.
|
640
|
-
MULTI_ARG_TYPES = [:ints, :integers, :strings, :doubles, :floats, :ios, :dates]
|
641
|
-
|
642
|
-
## The complete set of legal values for the +:type+ parameter of #opt.
|
643
|
-
TYPES = FLAG_TYPES + SINGLE_ARG_TYPES + MULTI_ARG_TYPES
|
644
|
-
|
645
|
-
attr_accessor :name, :opts
|
646
|
-
|
647
|
-
def initialize(name, desc="", opts={}, &b)
|
648
|
-
## fill in :type
|
649
|
-
opts[:type] = # normalize
|
650
|
-
case opts[:type]
|
651
|
-
when :boolean, :bool then :flag
|
652
|
-
when :integer then :int
|
653
|
-
when :integers then :ints
|
654
|
-
when :double then :float
|
655
|
-
when :doubles then :floats
|
656
|
-
when Class
|
657
|
-
case opts[:type].name
|
658
|
-
when 'TrueClass',
|
659
|
-
'FalseClass' then :flag
|
660
|
-
when 'String' then :string
|
661
|
-
when 'Integer' then :int
|
662
|
-
when 'Float' then :float
|
663
|
-
when 'IO' then :io
|
664
|
-
when 'Date' then :date
|
665
|
-
else
|
666
|
-
raise ArgumentError, "unsupported argument type '#{opts[:type].class.name}'"
|
667
|
-
end
|
668
|
-
when nil then nil
|
669
|
-
else
|
670
|
-
raise ArgumentError, "unsupported argument type '#{opts[:type]}'" unless TYPES.include?(opts[:type])
|
671
|
-
opts[:type]
|
672
|
-
end
|
580
|
+
attr_accessor :name, :short, :long, :default
|
581
|
+
attr_writer :multi_given
|
673
582
|
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
583
|
+
def initialize
|
584
|
+
@long = nil
|
585
|
+
@short = nil
|
586
|
+
@name = nil
|
587
|
+
@multi_given = false
|
588
|
+
@hidden = false
|
589
|
+
@default = nil
|
590
|
+
@optshash = Hash.new()
|
591
|
+
end
|
592
|
+
|
593
|
+
def opts(key)
|
594
|
+
@optshash[key]
|
595
|
+
end
|
596
|
+
|
597
|
+
def opts=(o)
|
598
|
+
@optshash = o
|
599
|
+
end
|
600
|
+
|
601
|
+
## Indicates a flag option, which is an option without an argument
|
602
|
+
def flag? ; false ; end
|
603
|
+
def single_arg?
|
604
|
+
!self.multi_arg? && !self.flag?
|
605
|
+
end
|
606
|
+
|
607
|
+
def multi ; @multi_given ; end
|
608
|
+
alias multi? multi
|
609
|
+
|
610
|
+
## Indicates that this is a multivalued (Array type) argument
|
611
|
+
def multi_arg? ; false ; end
|
612
|
+
## note: Option-Types with both multi_arg? and flag? false are single-parameter (normal) options.
|
613
|
+
|
614
|
+
def array_default? ; self.default.kind_of?(Array) ; end
|
615
|
+
|
616
|
+
def short? ; short && short != :none ; end
|
617
|
+
|
618
|
+
def callback ; opts(:callback) ; end
|
619
|
+
def desc ; opts(:desc) ; end
|
620
|
+
|
621
|
+
def required? ; opts(:required) ; end
|
622
|
+
|
623
|
+
def parse(_paramlist, _neg_given)
|
624
|
+
raise NotImplementedError, "parse must be overridden for newly registered type"
|
625
|
+
end
|
626
|
+
|
627
|
+
# provide type-format string. default to empty, but user should probably override it
|
628
|
+
def type_format ; "" ; end
|
629
|
+
|
630
|
+
def educate
|
631
|
+
(short? ? "-#{short}, " : "") + "--#{long}" + type_format + (flag? && default ? ", --no-#{long}" : "")
|
632
|
+
end
|
633
|
+
|
634
|
+
## Format the educate-line description including the default-value(s)
|
635
|
+
def description_with_default
|
636
|
+
return desc unless default
|
637
|
+
default_s = case default
|
638
|
+
when $stdout then '<stdout>'
|
639
|
+
when $stdin then '<stdin>'
|
640
|
+
when $stderr then '<stderr>'
|
641
|
+
when Array
|
642
|
+
default.join(', ')
|
643
|
+
else
|
644
|
+
default.to_s
|
645
|
+
end
|
646
|
+
defword = desc.end_with?('.') ? 'Default' : 'default'
|
647
|
+
return "#{desc} (#{defword}: #{default_s})"
|
648
|
+
end
|
649
|
+
|
650
|
+
## Provide a way to register symbol aliases to the Parser
|
651
|
+
def self.register_alias(*alias_keys)
|
652
|
+
alias_keys.each do |alias_key|
|
653
|
+
# pass in the alias-key and the class
|
654
|
+
Parser.register(alias_key, self)
|
682
655
|
end
|
656
|
+
end
|
683
657
|
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
if opts[:default].empty?
|
695
|
-
if opts[:type]
|
696
|
-
raise ArgumentError, "multiple argument type must be plural" unless MULTI_ARG_TYPES.include?(opts[:type])
|
697
|
-
nil
|
698
|
-
else
|
699
|
-
raise ArgumentError, "multiple argument type cannot be deduced from an empty array for '#{opts[:default][0].class.name}'"
|
700
|
-
end
|
701
|
-
else
|
702
|
-
case opts[:default][0] # the first element determines the types
|
703
|
-
when Integer then :ints
|
704
|
-
when Numeric then :floats
|
705
|
-
when String then :strings
|
706
|
-
when IO then :ios
|
707
|
-
when Date then :dates
|
708
|
-
else
|
709
|
-
raise ArgumentError, "unsupported multiple argument type '#{opts[:default][0].class.name}'"
|
710
|
-
end
|
711
|
-
end
|
712
|
-
when nil then nil
|
713
|
-
else
|
714
|
-
raise ArgumentError, "unsupported argument type '#{opts[:default].class.name}'"
|
715
|
-
end
|
658
|
+
## Factory class methods ...
|
659
|
+
|
660
|
+
# Determines which type of object to create based on arguments passed
|
661
|
+
# to +Optimist::opt+. This is trickier in Optimist, than other cmdline
|
662
|
+
# parsers (e.g. Slop) because we allow the +default:+ to be able to
|
663
|
+
# set the option's type.
|
664
|
+
def self.create(name, desc="", opts={}, settings={})
|
665
|
+
|
666
|
+
opttype = Optimist::Parser.registry_getopttype(opts[:type])
|
667
|
+
opttype_from_default = get_klass_from_default(opts, opttype)
|
716
668
|
|
717
|
-
raise ArgumentError, ":type specification and default type don't match (default type is #{
|
669
|
+
raise ArgumentError, ":type specification and default type don't match (default type is #{opttype_from_default.class})" if opttype && opttype_from_default && (opttype.class != opttype_from_default.class)
|
718
670
|
|
719
|
-
|
671
|
+
opt_inst = (opttype || opttype_from_default || Optimist::BooleanOption.new)
|
720
672
|
|
721
673
|
## fill in :long
|
722
|
-
|
723
|
-
opts[:long] = case opts[:long]
|
724
|
-
when /^--([^-].*)$/ then $1
|
725
|
-
when /^[^-]/ then opts[:long]
|
726
|
-
else raise ArgumentError, "invalid long option name #{opts[:long].inspect}"
|
727
|
-
end
|
674
|
+
opt_inst.long = handle_long_opt(opts[:long], name)
|
728
675
|
|
729
676
|
## fill in :short
|
730
|
-
|
731
|
-
opts[:short] = case opts[:short]
|
732
|
-
when /^-(.)$/ then $1
|
733
|
-
when nil, :none, /^.$/ then opts[:short]
|
734
|
-
else raise ArgumentError, "invalid short option name '#{opts[:short].inspect}'"
|
735
|
-
end
|
677
|
+
opt_inst.short = handle_short_opt(opts[:short])
|
736
678
|
|
737
|
-
|
738
|
-
|
739
|
-
|
679
|
+
## fill in :multi
|
680
|
+
multi_given = opts[:multi] || false
|
681
|
+
opt_inst.multi_given = multi_given
|
740
682
|
|
741
683
|
## fill in :default for flags
|
742
|
-
|
684
|
+
defvalue = opts[:default] || opt_inst.default
|
743
685
|
|
744
686
|
## autobox :default for :multi (multi-occurrence) arguments
|
745
|
-
|
687
|
+
defvalue = [defvalue] if defvalue && multi_given && !defvalue.kind_of?(Array)
|
688
|
+
opt_inst.default = defvalue
|
689
|
+
opt_inst.name = name
|
690
|
+
opt_inst.opts = opts
|
691
|
+
opt_inst
|
692
|
+
end
|
746
693
|
|
747
|
-
|
748
|
-
opts[:multi] ||= false
|
694
|
+
private
|
749
695
|
|
750
|
-
|
751
|
-
|
696
|
+
def self.get_type_from_disdef(optdef, opttype, disambiguated_default)
|
697
|
+
if disambiguated_default.is_a? Array
|
698
|
+
return(optdef.first.class.name.downcase + "s") if !optdef.empty?
|
699
|
+
if opttype
|
700
|
+
raise ArgumentError, "multiple argument type must be plural" unless opttype.multi_arg?
|
701
|
+
return nil
|
702
|
+
else
|
703
|
+
raise ArgumentError, "multiple argument type cannot be deduced from an empty array"
|
704
|
+
end
|
705
|
+
end
|
706
|
+
return disambiguated_default.class.name.downcase
|
752
707
|
end
|
753
708
|
|
754
|
-
def
|
755
|
-
|
709
|
+
def self.get_klass_from_default(opts, opttype)
|
710
|
+
## for options with :multi => true, an array default doesn't imply
|
711
|
+
## a multi-valued argument. for that you have to specify a :type
|
712
|
+
## as well. (this is how we disambiguate an ambiguous situation;
|
713
|
+
## see the docs for Parser#opt for details.)
|
714
|
+
|
715
|
+
disambiguated_default = if opts[:multi] && opts[:default].is_a?(Array) && opttype.nil?
|
716
|
+
opts[:default].first
|
717
|
+
else
|
718
|
+
opts[:default]
|
719
|
+
end
|
720
|
+
|
721
|
+
return nil if disambiguated_default.nil?
|
722
|
+
type_from_default = get_type_from_disdef(opts[:default], opttype, disambiguated_default)
|
723
|
+
return Optimist::Parser.registry_getopttype(type_from_default)
|
756
724
|
end
|
757
725
|
|
758
|
-
def
|
759
|
-
|
760
|
-
|
761
|
-
|
726
|
+
def self.handle_long_opt(lopt, name)
|
727
|
+
lopt = lopt ? lopt.to_s : name.to_s.gsub("_", "-")
|
728
|
+
lopt = case lopt
|
729
|
+
when /^--([^-].*)$/ then $1
|
730
|
+
when /^[^-]/ then lopt
|
731
|
+
else raise ArgumentError, "invalid long option name #{lopt.inspect}"
|
732
|
+
end
|
762
733
|
end
|
763
734
|
|
764
|
-
def
|
765
|
-
|
735
|
+
def self.handle_short_opt(sopt)
|
736
|
+
sopt = sopt.to_s if sopt && sopt != :none
|
737
|
+
sopt = case sopt
|
738
|
+
when /^-(.)$/ then $1
|
739
|
+
when nil, :none, /^.$/ then sopt
|
740
|
+
else raise ArgumentError, "invalid short option name '#{sopt.inspect}'"
|
741
|
+
end
|
766
742
|
|
767
|
-
|
768
|
-
|
743
|
+
if sopt
|
744
|
+
raise ArgumentError, "a short option name can't be a number or a dash" if sopt =~ ::Optimist::Parser::INVALID_SHORT_ARG_REGEX
|
745
|
+
end
|
746
|
+
return sopt
|
769
747
|
end
|
770
748
|
|
771
|
-
|
772
|
-
#? def multi_default ; opts.default || opts.multi && [] ; end
|
773
|
-
def array_default? ; opts[:default].kind_of?(Array) ; end
|
749
|
+
end
|
774
750
|
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
def
|
779
|
-
|
780
|
-
|
781
|
-
|
751
|
+
# Flag option. Has no arguments. Can be negated with "no-".
|
752
|
+
class BooleanOption < Option
|
753
|
+
register_alias :flag, :bool, :boolean, :trueclass, :falseclass
|
754
|
+
def initialize
|
755
|
+
super()
|
756
|
+
@default = false
|
757
|
+
end
|
758
|
+
def flag? ; true ; end
|
759
|
+
def parse(_paramlist, neg_given)
|
760
|
+
return(self.name.to_s =~ /^no_/ ? neg_given : !neg_given)
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
# Floating point number option class.
|
765
|
+
class FloatOption < Option
|
766
|
+
register_alias :float, :double
|
767
|
+
def type_format ; "=<f>" ; end
|
768
|
+
def parse(paramlist, _neg_given)
|
769
|
+
paramlist.map do |pg|
|
770
|
+
pg.map do |param|
|
771
|
+
raise CommandlineError, "option '#{self.name}' needs a floating-point number" unless param.is_a?(Numeric) || param =~ FLOAT_RE
|
772
|
+
param.to_f
|
773
|
+
end
|
774
|
+
end
|
775
|
+
end
|
776
|
+
end
|
777
|
+
|
778
|
+
# Integer number option class.
|
779
|
+
class IntegerOption < Option
|
780
|
+
register_alias :int, :integer, :fixnum
|
781
|
+
def type_format ; "=<i>" ; end
|
782
|
+
def parse(paramlist, _neg_given)
|
783
|
+
paramlist.map do |pg|
|
784
|
+
pg.map do |param|
|
785
|
+
raise CommandlineError, "option '#{self.name}' needs an integer" unless param.is_a?(Numeric) || param =~ /^-?[\d_]+$/
|
786
|
+
param.to_i
|
787
|
+
end
|
788
|
+
end
|
789
|
+
end
|
790
|
+
end
|
791
|
+
|
792
|
+
# Option class for handling IO objects and URLs.
|
793
|
+
# Note that this will return the file-handle, not the file-name
|
794
|
+
# in the case of file-paths given to it.
|
795
|
+
class IOOption < Option
|
796
|
+
register_alias :io
|
797
|
+
def type_format ; "=<filename/uri>" ; end
|
798
|
+
def parse(paramlist, _neg_given)
|
799
|
+
paramlist.map do |pg|
|
800
|
+
pg.map do |param|
|
801
|
+
if param =~ /^(stdin|-)$/i
|
802
|
+
$stdin
|
803
|
+
else
|
804
|
+
require 'open-uri'
|
805
|
+
begin
|
806
|
+
open param
|
807
|
+
rescue SystemCallError => e
|
808
|
+
raise CommandlineError, "file or url for option '#{self.name}' cannot be opened: #{e.message}"
|
809
|
+
end
|
810
|
+
end
|
811
|
+
end
|
812
|
+
end
|
813
|
+
end
|
814
|
+
end
|
782
815
|
|
783
|
-
|
816
|
+
# Option class for handling Strings.
|
817
|
+
class StringOption < Option
|
818
|
+
register_alias :string
|
819
|
+
def type_format ; "=<s>" ; end
|
820
|
+
def parse(paramlist, _neg_given)
|
821
|
+
paramlist.map { |pg| pg.map(&:to_s) }
|
822
|
+
end
|
823
|
+
end
|
784
824
|
|
785
|
-
|
786
|
-
|
825
|
+
# Option for dates. Uses Chronic if it exists.
|
826
|
+
class DateOption < Option
|
827
|
+
register_alias :date
|
828
|
+
def type_format ; "=<date>" ; end
|
829
|
+
def parse(paramlist, _neg_given)
|
830
|
+
paramlist.map do |pg|
|
831
|
+
pg.map do |param|
|
832
|
+
next param if param.is_a?(Date)
|
833
|
+
begin
|
834
|
+
begin
|
835
|
+
require 'chronic'
|
836
|
+
time = Chronic.parse(param)
|
837
|
+
rescue LoadError
|
838
|
+
# chronic is not available
|
839
|
+
end
|
840
|
+
time ? Date.new(time.year, time.month, time.day) : Date.parse(param)
|
841
|
+
rescue ArgumentError
|
842
|
+
raise CommandlineError, "option '#{self.name}' needs a date"
|
843
|
+
end
|
844
|
+
end
|
845
|
+
end
|
787
846
|
end
|
788
847
|
end
|
789
848
|
|
790
|
-
|
849
|
+
### MULTI_OPT_TYPES :
|
850
|
+
## The set of values that indicate a multiple-parameter option (i.e., that
|
851
|
+
## takes multiple space-separated values on the commandline) when passed as
|
852
|
+
## the +:type+ parameter of #opt.
|
853
|
+
|
854
|
+
# Option class for handling multiple Integers
|
855
|
+
class IntegerArrayOption < IntegerOption
|
856
|
+
register_alias :fixnums, :ints, :integers
|
857
|
+
def type_format ; "=<i+>" ; end
|
858
|
+
def multi_arg? ; true ; end
|
859
|
+
end
|
860
|
+
|
861
|
+
# Option class for handling multiple Floats
|
862
|
+
class FloatArrayOption < FloatOption
|
863
|
+
register_alias :doubles, :floats
|
864
|
+
def type_format ; "=<f+>" ; end
|
865
|
+
def multi_arg? ; true ; end
|
866
|
+
end
|
867
|
+
|
868
|
+
# Option class for handling multiple Strings
|
869
|
+
class StringArrayOption < StringOption
|
870
|
+
register_alias :strings
|
871
|
+
def type_format ; "=<s+>" ; end
|
872
|
+
def multi_arg? ; true ; end
|
873
|
+
end
|
874
|
+
|
875
|
+
# Option class for handling multiple dates
|
876
|
+
class DateArrayOption < DateOption
|
877
|
+
register_alias :dates
|
878
|
+
def type_format ; "=<date+>" ; end
|
879
|
+
def multi_arg? ; true ; end
|
880
|
+
end
|
881
|
+
|
882
|
+
# Option class for handling Files/URLs via 'open'
|
883
|
+
class IOArrayOption < IOOption
|
884
|
+
register_alias :ios
|
885
|
+
def type_format ; "=<filename/uri+>" ; end
|
886
|
+
def multi_arg? ; true ; end
|
887
|
+
end
|
888
|
+
|
889
|
+
## The easy, syntactic-sugary entry method into Optimist. Creates a Parser,
|
791
890
|
## passes the block to it, then parses +args+ with it, handling any errors or
|
792
891
|
## requests for help or version information appropriately (and then exiting).
|
793
892
|
## Modifies +args+ in place. Returns a hash of option values.
|
@@ -804,8 +903,8 @@ end
|
|
804
903
|
##
|
805
904
|
## Example:
|
806
905
|
##
|
807
|
-
## require '
|
808
|
-
## opts =
|
906
|
+
## require 'optimist'
|
907
|
+
## opts = Optimist::options do
|
809
908
|
## opt :monkey, "Use monkey mode" # a flag --monkey, defaulting to false
|
810
909
|
## opt :name, "Monkey name", :type => :string # a string --name <s>, defaulting to nil
|
811
910
|
## opt :num_limbs, "Number of limbs", :default => 4 # an integer --num-limbs <i>, defaulting to 4
|
@@ -817,13 +916,13 @@ end
|
|
817
916
|
## ## if called with --monkey
|
818
917
|
## p opts # => {:monkey=>true, :name=>nil, :num_limbs=>4, :help=>false, :monkey_given=>true}
|
819
918
|
##
|
820
|
-
## See more examples at http://
|
919
|
+
## See more examples at http://optimist.rubyforge.org.
|
821
920
|
def options(args = ARGV, *a, &b)
|
822
921
|
@last_parser = Parser.new(*a, &b)
|
823
922
|
with_standard_exception_handling(@last_parser) { @last_parser.parse args }
|
824
923
|
end
|
825
924
|
|
826
|
-
## If
|
925
|
+
## If Optimist::options doesn't do quite what you want, you can create a Parser
|
827
926
|
## object and call Parser#parse on it. That method will throw CommandlineError,
|
828
927
|
## HelpNeeded and VersionNeeded exceptions when necessary; if you want to
|
829
928
|
## have these handled for you in the standard manner (e.g. show the help
|
@@ -834,15 +933,15 @@ end
|
|
834
933
|
##
|
835
934
|
## Usage example:
|
836
935
|
##
|
837
|
-
## require '
|
838
|
-
## p =
|
936
|
+
## require 'optimist'
|
937
|
+
## p = Optimist::Parser.new do
|
839
938
|
## opt :monkey, "Use monkey mode" # a flag --monkey, defaulting to false
|
840
939
|
## opt :goat, "Use goat mode", :default => true # a flag --goat, defaulting to true
|
841
940
|
## end
|
842
941
|
##
|
843
|
-
## opts =
|
942
|
+
## opts = Optimist::with_standard_exception_handling p do
|
844
943
|
## o = p.parse ARGV
|
845
|
-
## raise
|
944
|
+
## raise Optimist::HelpNeeded if ARGV.empty? # show help screen
|
846
945
|
## o
|
847
946
|
## end
|
848
947
|
##
|
@@ -877,12 +976,16 @@ end
|
|
877
976
|
## opt :whatever # ...
|
878
977
|
## end
|
879
978
|
##
|
880
|
-
##
|
979
|
+
## Optimist::die "need at least one filename" if ARGV.empty?
|
980
|
+
##
|
981
|
+
## An exit code can be provide if needed
|
982
|
+
##
|
983
|
+
## Optimist::die "need at least one filename", -2 if ARGV.empty?
|
881
984
|
def die(arg, msg = nil, error_code = nil)
|
882
985
|
if @last_parser
|
883
986
|
@last_parser.die arg, msg, error_code
|
884
987
|
else
|
885
|
-
raise ArgumentError, "
|
988
|
+
raise ArgumentError, "Optimist::die can only be called after Optimist::options"
|
886
989
|
end
|
887
990
|
end
|
888
991
|
|
@@ -897,15 +1000,15 @@ end
|
|
897
1000
|
## EOS
|
898
1001
|
## end
|
899
1002
|
##
|
900
|
-
##
|
1003
|
+
## Optimist::educate if ARGV.empty?
|
901
1004
|
def educate
|
902
1005
|
if @last_parser
|
903
1006
|
@last_parser.educate
|
904
1007
|
exit
|
905
1008
|
else
|
906
|
-
raise ArgumentError, "
|
1009
|
+
raise ArgumentError, "Optimist::educate can only be called after Optimist::options"
|
907
1010
|
end
|
908
1011
|
end
|
909
1012
|
|
910
1013
|
module_function :options, :die, :educate, :with_standard_exception_handling
|
911
|
-
end # module
|
1014
|
+
end # module
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: darksky-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken J.
|
@@ -10,7 +10,7 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2019-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description: Dark Sky gem written in pure Ruby without any external dependency.
|
14
14
|
email:
|
15
15
|
- kenjij@gmail.com
|
16
16
|
executables:
|
@@ -18,13 +18,14 @@ executables:
|
|
18
18
|
extensions: []
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
+
- LICENSE
|
22
|
+
- README.md
|
21
23
|
- bin/darksky
|
22
24
|
- darksky-ruby.gemspec
|
23
25
|
- lib/darksky-ruby.rb
|
24
26
|
- lib/darksky-ruby/api.rb
|
25
27
|
- lib/darksky-ruby/http.rb
|
26
|
-
- lib/darksky-ruby/
|
27
|
-
- lib/darksky-ruby/version.rb
|
28
|
+
- lib/darksky-ruby/optimist.rb
|
28
29
|
homepage: https://github.com/kenjij/darksky-ruby
|
29
30
|
licenses:
|
30
31
|
- MIT
|
@@ -44,9 +45,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
45
|
- !ruby/object:Gem::Version
|
45
46
|
version: '0'
|
46
47
|
requirements: []
|
47
|
-
|
48
|
-
rubygems_version: 2.6.14
|
48
|
+
rubygems_version: 3.0.6
|
49
49
|
signing_key:
|
50
50
|
specification_version: 4
|
51
|
-
summary: Pure simple Ruby based
|
51
|
+
summary: Pure simple Ruby based Dark Sky API gem
|
52
52
|
test_files: []
|