options_by_example 4.1.0 → 4.2.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 +4 -4
- data/README.md +2 -2
- data/lib/options_by_example/commandline_parser.rb +26 -13
- data/lib/options_by_example/usage_specification.rb +22 -10
- data/lib/options_by_example/version.rb +9 -1
- data/lib/options_by_example.rb +13 -4
- metadata +3 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 59f737886cd6b035ebefb01b6d513d6a4cd66957858d9c3f9d4b489058fe5725
|
|
4
|
+
data.tar.gz: d3f6f2d559a4f5c077f878dec4e8fb8c8f9cf9e4daaeebaba8b5611f343ac86b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad0b05e43b8ec21c9bbc434085896082fe0a956190d255c5ef24382f3f0ec8faf5f05b32f3acda272ca8d0fbbb63e736d9a5db4860e6bd750be26f7601a263c6
|
|
7
|
+
data.tar.gz: e2008e435bbfc129170599f7e28626ede57501b078e65684c436fea0644d69b8a564c388da1bd197a60332c4c34404d60424541dd9912307c0b2316ad069a811
|
data/README.md
CHANGED
|
@@ -16,8 +16,8 @@ require %(options_by_example)
|
|
|
16
16
|
|
|
17
17
|
flags = OptionsByExample.read(DATA).parse(ARGV)
|
|
18
18
|
|
|
19
|
-
puts 'Feeling verbose today' if flags.
|
|
20
|
-
puts flags.
|
|
19
|
+
puts 'Feeling verbose today' if flags.include_verbose?
|
|
20
|
+
puts flags.get_words.sample(flags.get_num)
|
|
21
21
|
|
|
22
22
|
__END__
|
|
23
23
|
Choose at random from a list of provided words.
|
|
@@ -46,7 +46,7 @@ class OptionsByExample
|
|
|
46
46
|
|
|
47
47
|
def treat_everything_after_double_dash_as_positionals
|
|
48
48
|
index = @slices.index { |head,| head == '--' }
|
|
49
|
-
@slices[index
|
|
49
|
+
@slices[index..-1] = [@slices.drop(index).flatten] if index
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def exit_if_help_option
|
|
@@ -120,15 +120,32 @@ class OptionsByExample
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
option = current.shift # consume the option/flag
|
|
123
|
-
option_name,
|
|
123
|
+
option_name, argument_arity, _, _ = @option_names[option]
|
|
124
124
|
@option_values[option_name] = true
|
|
125
125
|
|
|
126
|
-
if
|
|
126
|
+
if argument_arity == :required
|
|
127
127
|
raise "Expected argument for option '#{option}', got none" unless current.first
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
|
|
129
|
+
if pending.length == 1
|
|
130
|
+
minimum_count = count_arguments(:required) + count_arguments(:vararg)
|
|
131
|
+
if current.length <= minimum_count
|
|
132
|
+
raise "Ambiguous argument for option '#{option}', not enough remaining positional arguments"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
@argument_values[option_name] = current.shift
|
|
137
|
+
elsif argument_arity == :optional && current.first
|
|
138
|
+
if pending.length == 1
|
|
139
|
+
required_count = count_arguments(:required)
|
|
140
|
+
if current.length <= required_count and required_count == @argument_names.length
|
|
141
|
+
return current
|
|
142
|
+
end
|
|
143
|
+
if current.length <= required_count or required_count != @argument_names.length
|
|
144
|
+
raise "Ambiguous argument for option '#{option}', please use -- before positional arguments"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
@argument_values[option_name] = current.shift
|
|
132
149
|
end
|
|
133
150
|
|
|
134
151
|
pending.shift if current.empty?
|
|
@@ -138,12 +155,12 @@ class OptionsByExample
|
|
|
138
155
|
end
|
|
139
156
|
|
|
140
157
|
def coerce_num_date_time_etc
|
|
141
|
-
@option_names.each do |option, (each,
|
|
158
|
+
@option_names.each do |option, (each, _, argument_type, default_value)|
|
|
142
159
|
value = @argument_values.fetch(each, default_value)
|
|
143
160
|
next unless value
|
|
144
161
|
|
|
145
162
|
begin
|
|
146
|
-
case
|
|
163
|
+
case argument_type
|
|
147
164
|
when 'NUM'
|
|
148
165
|
expected_type = 'an integer value'
|
|
149
166
|
value = Integer value
|
|
@@ -197,10 +214,6 @@ class OptionsByExample
|
|
|
197
214
|
# :nocov:
|
|
198
215
|
end
|
|
199
216
|
|
|
200
|
-
if @option_took_argument
|
|
201
|
-
msg += " (considering #{@option_took_argument} takes an argument)"
|
|
202
|
-
end
|
|
203
|
-
|
|
204
217
|
raise msg
|
|
205
218
|
end
|
|
206
219
|
end
|
|
@@ -23,7 +23,7 @@ class OptionsByExample
|
|
|
23
23
|
|
|
24
24
|
usage_line = text.lines.grep(/Usage:/).first
|
|
25
25
|
raise "Expected usage string, got none" unless usage_line
|
|
26
|
-
tokens = usage_line.
|
|
26
|
+
tokens = usage_line.split(/(\[.*?\]?\]|\w+ \.\.\.)|\s+/).reject(&:empty?)
|
|
27
27
|
raise "Expected usage line to start with 'Usage:'" unless tokens.shift == 'Usage:'
|
|
28
28
|
raise "Expected command name on same line as 'Usage:'" unless tokens.shift
|
|
29
29
|
tokens.shift if tokens.first == '[options]'
|
|
@@ -74,30 +74,42 @@ class OptionsByExample
|
|
|
74
74
|
|
|
75
75
|
options = inline_options + text.lines.grep(/^\s*--?\w/)
|
|
76
76
|
options.each do |string|
|
|
77
|
-
tokens = string.
|
|
77
|
+
tokens = string.strip.split(/(\s+)|(,)\s*/)
|
|
78
78
|
|
|
79
79
|
short_form = nil
|
|
80
80
|
long_form = nil
|
|
81
81
|
option_name = nil
|
|
82
|
-
|
|
82
|
+
argument_arity = nil
|
|
83
|
+
argument_type = nil
|
|
83
84
|
default_value = nil
|
|
84
85
|
|
|
85
|
-
if /^-(\w)
|
|
86
|
-
short_form
|
|
86
|
+
if /^-(\w)$/ === tokens.first
|
|
87
|
+
short_form = tokens.shift
|
|
87
88
|
option_name = sanitize $1
|
|
88
|
-
tokens.shift if ','
|
|
89
|
+
tokens.shift if tokens.first == ','
|
|
89
90
|
end
|
|
90
91
|
|
|
91
|
-
if /^--([\w-]+)
|
|
92
|
-
long_form
|
|
92
|
+
if /^--([\w-]+)$/ === tokens.first
|
|
93
|
+
long_form = tokens.shift
|
|
93
94
|
option_name = sanitize $1
|
|
94
95
|
end
|
|
95
96
|
|
|
96
|
-
if
|
|
97
|
+
if tokens.shift == ' '
|
|
98
|
+
if /^(\[(.+)\]|(.+)\?)$/ === tokens.first
|
|
99
|
+
argument_type = $2 || $3
|
|
100
|
+
argument_arity = :optional
|
|
101
|
+
tokens.shift
|
|
102
|
+
else
|
|
103
|
+
argument_type = tokens.shift
|
|
104
|
+
argument_arity = :required
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
if /\(default\s+(\S+)\)$/ === tokens.join
|
|
97
109
|
default_value = $1
|
|
98
110
|
end
|
|
99
111
|
|
|
100
|
-
ary = [option_name,
|
|
112
|
+
ary = [option_name, argument_arity, argument_type, default_value]
|
|
101
113
|
[short_form, long_form].each do |each|
|
|
102
114
|
@option_names[each] = ary if each
|
|
103
115
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class OptionsByExample
|
|
4
|
-
VERSION = '4.
|
|
4
|
+
VERSION = '4.2.0'
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
|
|
@@ -11,6 +11,14 @@ __END__
|
|
|
11
11
|
# Minor version bump when backward-compatible changes or enhancements
|
|
12
12
|
# Patch version bump when backward-compatible bug fixes, security updates etc
|
|
13
13
|
|
|
14
|
+
4.2.0
|
|
15
|
+
- Generate #get_NAME methods for arguments
|
|
16
|
+
- Keep #argument_NAME as backwards-compatible aliases
|
|
17
|
+
- New method #get_at_most_one returns the provided option or nil
|
|
18
|
+
- New method #get_mutually_exclusive aliases #get_at_most_one
|
|
19
|
+
- Deprecate #expect_at_most_one_of in favor of #expect_at_most_one
|
|
20
|
+
- Support optional option arguments, eg '--compress [NUM]'
|
|
21
|
+
|
|
14
22
|
4.1.0
|
|
15
23
|
- Treat everything after double-dash as positional arguments
|
|
16
24
|
- Improve error message when usage is split across lines
|
data/lib/options_by_example.rb
CHANGED
|
@@ -32,16 +32,24 @@ class OptionsByExample
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def expect_at_most_one_except(*extra_options)
|
|
35
|
-
|
|
35
|
+
expect_at_most_one *(@options.keys - extra_options)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def expect_at_most_one_of(*mutually_exclusive_options)
|
|
39
|
+
expect_at_most_one *mutually_exclusive_options
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_at_most_one(*mutually_exclusive_options)
|
|
39
43
|
provided_options = @options.keys & mutually_exclusive_options
|
|
40
44
|
if provided_options.length > 1
|
|
41
45
|
abort "ERR: Found more than one mutually-exclusive option {#{provided_options.join ', '}}"
|
|
42
46
|
end
|
|
47
|
+
provided_options.first
|
|
43
48
|
end
|
|
44
49
|
|
|
50
|
+
alias expect_at_most_one get_at_most_one
|
|
51
|
+
alias get_mutually_exclusive get_at_most_one
|
|
52
|
+
|
|
45
53
|
def fetch(*args, &block)
|
|
46
54
|
@arguments.fetch(*args, &block)
|
|
47
55
|
end
|
|
@@ -77,14 +85,16 @@ class OptionsByExample
|
|
|
77
85
|
[
|
|
78
86
|
*@usage_spec.argument_names.keys,
|
|
79
87
|
*@usage_spec.option_names.values
|
|
80
|
-
.map { |option_name,
|
|
88
|
+
.map { |option_name, argument_arity| option_name if argument_arity }
|
|
81
89
|
.compact,
|
|
82
90
|
].each do |argument_name|
|
|
83
91
|
instance_eval %{
|
|
84
|
-
def
|
|
92
|
+
def get_#{argument_name}
|
|
85
93
|
val = @arguments[:#{argument_name}]
|
|
86
94
|
val && block_given? ? (yield val) : val
|
|
87
95
|
end
|
|
96
|
+
|
|
97
|
+
alias argument_#{argument_name} get_#{argument_name}
|
|
88
98
|
}
|
|
89
99
|
end
|
|
90
100
|
end
|
|
@@ -99,4 +109,3 @@ class OptionsByExample
|
|
|
99
109
|
end
|
|
100
110
|
end
|
|
101
111
|
end
|
|
102
|
-
|
metadata
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: options_by_example
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adrian Kuhn
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies: []
|
|
13
|
-
description:
|
|
14
12
|
email:
|
|
15
13
|
- akuhn@iam.unibe.ch
|
|
16
14
|
executables: []
|
|
@@ -29,7 +27,6 @@ metadata:
|
|
|
29
27
|
homepage_uri: https://github.com/akuhn/options_by_example
|
|
30
28
|
source_code_uri: https://github.com/akuhn/options_by_example
|
|
31
29
|
changelog_uri: https://github.com/akuhn/options_by_example/blob/master/lib/options_by_example/version.rb
|
|
32
|
-
post_install_message:
|
|
33
30
|
rdoc_options: []
|
|
34
31
|
require_paths:
|
|
35
32
|
- lib
|
|
@@ -44,8 +41,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
44
41
|
- !ruby/object:Gem::Version
|
|
45
42
|
version: '0'
|
|
46
43
|
requirements: []
|
|
47
|
-
rubygems_version: 3.
|
|
48
|
-
signing_key:
|
|
44
|
+
rubygems_version: 3.6.9
|
|
49
45
|
specification_version: 4
|
|
50
46
|
summary: No-code options parser that extracts arguments directly from usage text.
|
|
51
47
|
test_files: []
|