optparse2 0.5.3 → 0.7.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/lib/optparse2/context.rb +51 -0
- data/lib/optparse2/switch-helpers.rb +171 -0
- data/lib/optparse2/version.rb +1 -1
- data/lib/optparse2.rb +142 -73
- data/publish +4 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6f61087f5b177ee9ffd0a587eb64ba8ff08893468ac8e0920621ee77d7b4a1b6
|
|
4
|
+
data.tar.gz: e5608123d52c5ad10d460f11ceb67bc9e9b0d5b145a502f9db16255e8df9ca0d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1155a87469ff90eaf3734338e4b883f97077e85327b4099a83bf360dd5f63bc5f136da6c3dee8a4de1ce0c0d8f98c1f85ae180f845ed0615dee4aee98747b345
|
|
7
|
+
data.tar.gz: e7099e4a6c7e2c0021a35c3b8b95ecafd632ed63bf86f26e9aca2884c42bb749d3f03c1baab1ad3527a90fb4a5434c2540ca1ac6f1ed4ce3167e7fa4eeedcc14
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
class OptParse2
|
|
2
|
+
# A Context is in charge of all option parsing
|
|
3
|
+
class Context
|
|
4
|
+
class << self
|
|
5
|
+
attr_accessor :current
|
|
6
|
+
|
|
7
|
+
def with_context(...)
|
|
8
|
+
context = new(...)
|
|
9
|
+
old, self.current = current, context
|
|
10
|
+
yield context
|
|
11
|
+
ensure
|
|
12
|
+
self.current = old
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attr_reader :non_options, :deferred_options, :already_parsed_options
|
|
17
|
+
|
|
18
|
+
def initialize(into:, nonopt:)
|
|
19
|
+
@into = into
|
|
20
|
+
@nonopt = nonopt
|
|
21
|
+
|
|
22
|
+
@already_parsed_options = {}
|
|
23
|
+
@non_options = []
|
|
24
|
+
@deferred_options = {}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def add_non_option(non_option)
|
|
28
|
+
@non_options << non_option
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def handle_deferred!
|
|
32
|
+
@deferred_options.each do |key, deferred|
|
|
33
|
+
self[key] = deferred[:proc].call(deferred[:data]) if deferred[:proc]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def key?(key)
|
|
38
|
+
@already_parsed_options.key?(key)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Directly assigns `value` to `key`, both in the internal list of parsed
|
|
42
|
+
# options, as well as in the `into:` option (if one is provided).
|
|
43
|
+
#
|
|
44
|
+
# Note that if `value` is `DONT_ASSIGN` nothing happens
|
|
45
|
+
def []=(key, value)
|
|
46
|
+
return if DONT_ASSIGN.equal?(value)
|
|
47
|
+
@already_parsed_options[key] = value
|
|
48
|
+
@into[key] = value if @into
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
class OptParse2
|
|
2
|
+
## Helpers is a mixin that contains methods to modify how the original `Switch` works
|
|
3
|
+
|
|
4
|
+
module Helpers
|
|
5
|
+
# Mark the switch as hidden (so it won't show up in the usage)
|
|
6
|
+
def set_hidden
|
|
7
|
+
def self.summarize(*) end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# The name of the switch; this is the key that's used when assigning options into an `into:`.
|
|
11
|
+
# It normally corresponds to the flag name (`--foo-bar` -> `foo-bar`), but can be overwritten
|
|
12
|
+
# as needed.
|
|
13
|
+
attr_writer :switch_name
|
|
14
|
+
def switch_name
|
|
15
|
+
defined?(@switch_name) ? @switch_name : super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def set_multiple(multiple)
|
|
19
|
+
old_block = @block
|
|
20
|
+
sw = switch_name.to_sym
|
|
21
|
+
|
|
22
|
+
case multiple
|
|
23
|
+
in :first!
|
|
24
|
+
@block = ->(arg, **nil) do
|
|
25
|
+
ctx = OptParse2::Context.current
|
|
26
|
+
if ctx.deferred_options.key? sw
|
|
27
|
+
OptParse2::DONT_ASSIGN
|
|
28
|
+
else
|
|
29
|
+
ctx.deferred_options[sw] = {}
|
|
30
|
+
old_block ? old_block.call(arg) : arg
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
in :first
|
|
34
|
+
@block = ->(arg, **nil) do
|
|
35
|
+
ctx = OptParse2::Context.current
|
|
36
|
+
if ctx.deferred_options.key? sw
|
|
37
|
+
OptParse2::DONT_ASSIGN
|
|
38
|
+
else
|
|
39
|
+
ctx.deferred_options[sw] = {
|
|
40
|
+
proc: old_block ? proc{ old_block.call(arg) } : proc { arg }
|
|
41
|
+
}
|
|
42
|
+
OptParse2::DONT_ASSIGN
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
in :last!, nil
|
|
46
|
+
# don't do anything, this is the default behaviour
|
|
47
|
+
in :last
|
|
48
|
+
@block = ->(arg, **nil) do
|
|
49
|
+
ctx = OptParse2::Context.current
|
|
50
|
+
ctx.deferred_options[sw] = {
|
|
51
|
+
proc: old_block ? proc { old_block.call(arg) } : proc { arg }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
OptParse2::DONT_ASSIGN
|
|
55
|
+
end
|
|
56
|
+
in :raise
|
|
57
|
+
@block = ->(arg) do
|
|
58
|
+
ctx = OptParse2::Context.current
|
|
59
|
+
if ctx.already_parsed_options.key? sw or ctx.deferred_options.key? sw
|
|
60
|
+
raise OptParse2::ParseError, "encountered repeated option"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
old_block ? old_block.call(arg) : arg
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
in :count
|
|
67
|
+
@block = ->(amnt, **nil) do
|
|
68
|
+
ctx = OptParse2::Context.current
|
|
69
|
+
|
|
70
|
+
ctx.deferred_options[sw] ||= {
|
|
71
|
+
proc: old_block ? proc { |data| old_block.call(data) } : proc { |data| data },
|
|
72
|
+
data: 0
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if amnt == true || amnt.nil?
|
|
76
|
+
ctx.deferred_options[sw][:data] += 1
|
|
77
|
+
else
|
|
78
|
+
ctx.deferred_options[sw][:data] = amnt
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
OptParse2::DONT_ASSIGN
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
in :count!
|
|
85
|
+
@block = ->(amnt, *a, **k, &b) do
|
|
86
|
+
ctx = OptParse2::Context.current
|
|
87
|
+
|
|
88
|
+
ctx.deferred_options[sw] ||= { data: 0 }
|
|
89
|
+
|
|
90
|
+
if amnt == true || amnt.nil?
|
|
91
|
+
ctx.deferred_options[sw][:data] += 1
|
|
92
|
+
else
|
|
93
|
+
ctx.deferred_options[sw][:data] = amnt
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
new_amnt = old_block ? old_block.call(ctx.deferred_options[sw][:data], *a, **k, &b) : ctx.deferred_options[sw][:data]
|
|
97
|
+
ctx.deferred_options[sw][:data] = new_amnt unless OptParse2::DONT_ASSIGN.equal? new_amnt
|
|
98
|
+
|
|
99
|
+
new_amnt
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
in :collect | [:collect, _]
|
|
103
|
+
transform = Array(multiple)[1]
|
|
104
|
+
@block = ->(arg, **nil) do
|
|
105
|
+
ctx = OptParse2::Context.current
|
|
106
|
+
ctx.deferred_options[sw] ||= {
|
|
107
|
+
proc: proc { |data| old_block ? old_block.call(data) : data },
|
|
108
|
+
data: []
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
ctx.deferred_options[sw][:data] << (transform ? transform.(arg) : arg)
|
|
112
|
+
OptParse2::DONT_ASSIGN
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
else
|
|
116
|
+
raise ArgumentError, "invalid multiple type: #{multiple}", caller(2)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Same as `switch_name`, except it also will set the block to just return the original switch
|
|
121
|
+
# name as a symbol. Useful for group switches which don't actually have blocks:
|
|
122
|
+
# op.on '--interactive', key: :mode
|
|
123
|
+
# op.on '--force', key: :mode
|
|
124
|
+
# instead of:
|
|
125
|
+
# op.on '--interactive', key: :mode do :interactive end
|
|
126
|
+
# op.on '--force', key: :mode do :force end
|
|
127
|
+
# without this method, passing `--interactive` would just set `:mode` to `true`.
|
|
128
|
+
#
|
|
129
|
+
# This only happens if no block exists, and the argument does not take an arg.
|
|
130
|
+
def set_switch_name_possibly_block_value(val)
|
|
131
|
+
if @block.nil? && @arg.nil?
|
|
132
|
+
old_switch_name = switch_name.to_sym
|
|
133
|
+
@block = proc { old_switch_name }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
self.switch_name = val
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Default values of switches are used when the switch is never passed in.
|
|
140
|
+
# If the `value` that's provided doesn't respond to `.call`, it's converted to a proc.
|
|
141
|
+
# If `bypass` is truthy, then the default value is never passed to the block's proc (if any)
|
|
142
|
+
def set_default(value, description, bypass)
|
|
143
|
+
if @arg.nil? && value != true && !bypass
|
|
144
|
+
raise ArgumentError, "Cannot supply a non-true default value to a flag which takes no arguments", caller(4)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
if defined? value.call
|
|
148
|
+
@default_proc = value
|
|
149
|
+
else
|
|
150
|
+
@default_proc = proc { |_switch_name| value }
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
@default_description = description
|
|
154
|
+
@default_bypass = bypass
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Calls the default proc to figure out what the default value is for this switch
|
|
158
|
+
def default_bypass? = @default_bypass
|
|
159
|
+
def default? = defined?(@default_proc)
|
|
160
|
+
def default = @default_proc&.call(switch_name)
|
|
161
|
+
|
|
162
|
+
def default_description = @default_description || default.inspect
|
|
163
|
+
def desc
|
|
164
|
+
return super unless defined? @default
|
|
165
|
+
x = super
|
|
166
|
+
x << '' if x.empty?
|
|
167
|
+
x[-1] += " [default: #{default_description}]"
|
|
168
|
+
x
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
data/lib/optparse2/version.rb
CHANGED
data/lib/optparse2.rb
CHANGED
|
@@ -6,6 +6,8 @@ OptionParser2 = OptParse2 # Alias
|
|
|
6
6
|
|
|
7
7
|
require_relative "optparse2/version"
|
|
8
8
|
require_relative "optparse2/fixes"
|
|
9
|
+
require_relative "optparse2/switch-helpers"
|
|
10
|
+
require_relative "optparse2/context"
|
|
9
11
|
|
|
10
12
|
class OptParse2
|
|
11
13
|
class << self
|
|
@@ -18,54 +20,26 @@ class OptParse2
|
|
|
18
20
|
@positional = []
|
|
19
21
|
@required = Set[]
|
|
20
22
|
@rest = nil
|
|
23
|
+
@group = nil
|
|
21
24
|
self.pos_set_banner = OptParse2.pos_set_banner
|
|
22
25
|
super
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def set_hidden
|
|
28
|
-
def self.summarize(*) end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
attr_writer :switch_name
|
|
32
|
-
def switch_name; defined?(@switch_name) ? @switch_name : super end
|
|
33
|
-
|
|
34
|
-
def set_switch_name_possibly_block_value(val)
|
|
35
|
-
if @block.nil? && @arg.nil?
|
|
36
|
-
q = switch_name.to_sym
|
|
37
|
-
@block = proc { q }
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
self.switch_name = val
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# requires `switch_name`, `desc` to work
|
|
45
|
-
def set_default(value, description)
|
|
46
|
-
if defined? value.call
|
|
47
|
-
@default = value
|
|
48
|
-
else
|
|
49
|
-
@default = proc { value }
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
@default_description = description
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def default = @default.call(switch_name)
|
|
56
|
-
def default_description = @default_description || default.inspect
|
|
57
|
-
def desc
|
|
58
|
-
return super unless defined? @default
|
|
59
|
-
x = super
|
|
60
|
-
x << '' if x.empty?
|
|
61
|
-
x[-1] += " [default: #{default_description}]"
|
|
62
|
-
x
|
|
63
|
-
end
|
|
64
|
-
end
|
|
28
|
+
# A constant that, when returned, will not actually assign objects inside `into:`s.
|
|
29
|
+
DONT_ASSIGN = Object.new.freeze
|
|
65
30
|
|
|
66
31
|
# Update `make_switch` to support OptParse2's keyword arguments
|
|
67
|
-
def make_switch(
|
|
68
|
-
|
|
32
|
+
def make_switch(
|
|
33
|
+
opts,
|
|
34
|
+
block,
|
|
35
|
+
hidden: false,
|
|
36
|
+
key: @group,
|
|
37
|
+
default: nodefault=true,
|
|
38
|
+
default_bypass: false,
|
|
39
|
+
default_description: nil,
|
|
40
|
+
required: false,
|
|
41
|
+
multiple: nil
|
|
42
|
+
)
|
|
69
43
|
sw, *rest = super(opts, block)
|
|
70
44
|
|
|
71
45
|
sw.extend Helpers
|
|
@@ -73,6 +47,7 @@ class OptParse2
|
|
|
73
47
|
sw.set_switch_name_possibly_block_value key
|
|
74
48
|
end
|
|
75
49
|
sw.set_hidden if hidden
|
|
50
|
+
sw.set_multiple multiple if multiple
|
|
76
51
|
|
|
77
52
|
if (not_style = rest[2])
|
|
78
53
|
not_style.extend Helpers
|
|
@@ -89,8 +64,10 @@ class OptParse2
|
|
|
89
64
|
|
|
90
65
|
if nodefault && default_description != nil
|
|
91
66
|
raise ArgumentError, "default: not supplied, but default_description: given"
|
|
67
|
+
elsif nodefault && default_bypass
|
|
68
|
+
raise ArgumentError, "default: not supplied, but default_bypass: given"
|
|
92
69
|
elsif not nodefault
|
|
93
|
-
sw.set_default(default, default_description)
|
|
70
|
+
sw.set_default(default, default_description, default_bypass)
|
|
94
71
|
@defaults << sw
|
|
95
72
|
end
|
|
96
73
|
|
|
@@ -102,26 +79,31 @@ class OptParse2
|
|
|
102
79
|
on_tail("\n" + msg)
|
|
103
80
|
end
|
|
104
81
|
|
|
105
|
-
def
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
already_done.define_singleton_method(:[]=) do |key, value|
|
|
112
|
-
super(key, value)
|
|
113
|
-
into[key] = value
|
|
82
|
+
def group(name, default: nodefault=true)
|
|
83
|
+
old_group, @group = @group, name
|
|
84
|
+
yield
|
|
85
|
+
if !nodefault && !@defaults.any? { |x| x.switch_name.to_sym == name }
|
|
86
|
+
(orig_default = default; default = proc { orig_default }) unless default.respond_to?(:call)
|
|
87
|
+
@defaults << Struct.new(:switch_name, :default_){ def default = default_.() }.new(name, default) # TODO: This should probably be extracted out into a class lol
|
|
114
88
|
end
|
|
89
|
+
ensure
|
|
90
|
+
@group = old_group
|
|
91
|
+
end
|
|
115
92
|
|
|
116
|
-
|
|
93
|
+
alias _super_order! order!
|
|
117
94
|
|
|
118
|
-
|
|
95
|
+
# Parses all positional arguments from `argv` into `into`. Replaces `argv` with non-positional
|
|
96
|
+
# arguments when it's done.
|
|
97
|
+
private def parse_positional_arguments!(argv, context, keywords)
|
|
98
|
+
return if argv.empty? || @positional.empty?
|
|
119
99
|
|
|
120
|
-
|
|
100
|
+
# Prepend argument number to the argument array
|
|
101
|
+
argv.replace argv.each_with_index.flat_map { |value, idx| ["--*-positional-#{idx}", value] }
|
|
121
102
|
|
|
103
|
+
# Fetch all positional arguments using the same option parsing code
|
|
122
104
|
old_raise, self.raise_unknown = self.raise_unknown, false
|
|
123
105
|
begin
|
|
124
|
-
|
|
106
|
+
p _super_order!(argv, into: context, **keywords)
|
|
125
107
|
rescue OptParse::InvalidArgument => err
|
|
126
108
|
err.args[0] = @positional[err.args[0][/\d+/].to_i].name
|
|
127
109
|
raise
|
|
@@ -129,33 +111,74 @@ class OptParse2
|
|
|
129
111
|
self.raise_unknown = old_raise
|
|
130
112
|
end
|
|
131
113
|
|
|
132
|
-
|
|
114
|
+
# Delete any non-matching arguments. TODO: Can this be the return value of `_super_order!` ?
|
|
115
|
+
argv.replace argv.each_slice(2).map { |_flag_name, value| value }
|
|
116
|
+
end
|
|
133
117
|
|
|
118
|
+
# If a "rest" parameter was given, populates it. Also raises a ParseError exception for unexepcted
|
|
119
|
+
# positionals if no `.rest` parameter is present, `self.raise_unknown` is set, and at least one `.pos`
|
|
120
|
+
# positional argument was supplied
|
|
121
|
+
private def parse_rest_argument!(argv, context)
|
|
134
122
|
if @rest
|
|
135
|
-
if
|
|
136
|
-
raise ParseError, "at least #{@rest[:required]} trailing arguments required (only got #{
|
|
123
|
+
if argv.length < @rest.fetch(:required, 0)
|
|
124
|
+
raise ParseError, "at least #{@rest[:required]} trailing arguments required (only got #{argv.length})", caller(1)
|
|
137
125
|
end
|
|
138
126
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
elsif !
|
|
143
|
-
raise ParseError, "got unexpected positional argument: #{
|
|
144
|
-
else
|
|
145
|
-
argv2.each(&nonopt)
|
|
127
|
+
argv = @rest[:block] ? @rest[:block].call(argv) : argv
|
|
128
|
+
context[@rest[:key]] = argv.dup if @rest[:key]
|
|
129
|
+
argv.clear
|
|
130
|
+
elsif !argv.empty? && self.raise_unknown && !@positional.empty?
|
|
131
|
+
raise ParseError, "got unexpected positional argument: #{argv.first}", caller(1)
|
|
146
132
|
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Goes thru every default option, and calls
|
|
136
|
+
private def assign_defaults!(context)
|
|
137
|
+
visit :each_option do |sw|
|
|
138
|
+
next if !sw.default? || context.key?(key = sw.switch_name.to_sym)
|
|
147
139
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
140
|
+
if sw.default_bypass?
|
|
141
|
+
context[key] = sw.default
|
|
142
|
+
else
|
|
143
|
+
flag = sw.short.first || sw.long.first || raise("<INTERNAL ERROR: CAN THIS EVER HAPPEN?>")
|
|
144
|
+
_super_order! [flag, sw.default], into: context
|
|
145
|
+
end
|
|
152
146
|
end
|
|
147
|
+
end
|
|
153
148
|
|
|
149
|
+
private def ensure_all_required_arguments_were_supplied!(context)
|
|
154
150
|
@required.each do |key|
|
|
155
|
-
raise ParseError, "required option '#{key}' not provided" unless
|
|
151
|
+
raise ParseError, "required option '#{key}' not provided" unless context.key? key.to_sym
|
|
156
152
|
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def order!(argv = default_argv, into: nil, **keywords, &nonopt)
|
|
156
|
+
Context.with_context into:, nonopt: do |context|
|
|
157
|
+
|
|
158
|
+
# Parse all normal options in the command line
|
|
159
|
+
non_options = []
|
|
160
|
+
trailing_options = super(argv, into: context, **keywords, &non_options.method(:<<))
|
|
161
|
+
not_matched_options = non_options + trailing_options
|
|
162
|
+
|
|
163
|
+
# Now parse positional arguments and the "rest" argument
|
|
164
|
+
parse_positional_arguments!(not_matched_options, context, keywords)
|
|
165
|
+
parse_rest_argument!(not_matched_options, context)
|
|
166
|
+
|
|
167
|
+
context.handle_deferred!
|
|
157
168
|
|
|
158
|
-
|
|
169
|
+
# Now handle defaults---anything with a default that hasn't been assigned so far is set
|
|
170
|
+
assign_defaults!(context)
|
|
171
|
+
|
|
172
|
+
# Now that all arguments are parsed, and the defaults have been handled, check to make sure
|
|
173
|
+
# that all required arguments are handled.
|
|
174
|
+
ensure_all_required_arguments_were_supplied!(context)
|
|
175
|
+
|
|
176
|
+
# For each non-option argument, call the `nonopt` block
|
|
177
|
+
not_matched_options.each(&nonopt)
|
|
178
|
+
|
|
179
|
+
# Replace the original argv with the resulting options
|
|
180
|
+
argv.replace not_matched_options
|
|
181
|
+
end
|
|
159
182
|
end
|
|
160
183
|
|
|
161
184
|
module Positional
|
|
@@ -236,10 +259,56 @@ class OptParse2
|
|
|
236
259
|
title += " (#{required} arg minimum)" if required > 0
|
|
237
260
|
|
|
238
261
|
on sprintf "%s%-*s %s", summary_indent, summary_width, title, description.first
|
|
239
|
-
description[1..]
|
|
262
|
+
description[1..]&.each do |descr|
|
|
240
263
|
on sprintf "%s%-*s %s", summary_indent, summary_width, '', descr
|
|
241
264
|
end
|
|
242
265
|
|
|
243
266
|
@rest = { name:, key:, required: required || 0, block: }
|
|
244
267
|
end
|
|
245
268
|
end
|
|
269
|
+
|
|
270
|
+
__END__
|
|
271
|
+
OptParse2.new do |op|
|
|
272
|
+
op.on '--foo=FOO', multiple: :first! do puts "FOO: #{it}"; it end
|
|
273
|
+
op.on '--bar=BAR' do puts "BAR: #{it}"; it end
|
|
274
|
+
|
|
275
|
+
op.on '-v', '--verbose[=X]', Integer, multiple: :count
|
|
276
|
+
|
|
277
|
+
# op.on '-v', '--verbose[=X]', Integer, multiple: :count! do
|
|
278
|
+
# puts "verbose is: #{it}"
|
|
279
|
+
# it
|
|
280
|
+
# end
|
|
281
|
+
|
|
282
|
+
op.on '-aF', Integer, multiple: [:collect, :succ.to_proc] do |x|
|
|
283
|
+
p x
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
op.parse! %w[ -vvv --foo=abc --bar=123 --foo=xyz -a3 -a4 -a5 ], into: opts={}
|
|
287
|
+
p opts
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# OptParse.new do |op|
|
|
291
|
+
# op.on '--foo=bar', /(.)(.)/ do |x| p x end
|
|
292
|
+
# op.parse! %w[ --foo=34 ]
|
|
293
|
+
# end
|
|
294
|
+
__END__
|
|
295
|
+
OptionParser2.new do |op|
|
|
296
|
+
op.on '-e', default: true
|
|
297
|
+
op.on '--bar1=ALL', default: 'hello', &:upcase
|
|
298
|
+
op.on '--doit=WHAT', /(.)(.)/, key: :A, default: 'xu' do
|
|
299
|
+
p [_1, _2, 'both!']
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
op.pos 'foo', required: true do 3 end
|
|
303
|
+
op.pos 'bar', required: true
|
|
304
|
+
op.pos 'baz', required: false
|
|
305
|
+
op.pos 'quux', required: false
|
|
306
|
+
# op.rest 'files'
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
rest = op.order!(argv = %w[ --doit 3q a b ] , into: opts={})
|
|
310
|
+
|
|
311
|
+
puts "rest=#{rest}"
|
|
312
|
+
puts "argv=#{argv}"
|
|
313
|
+
puts "opts=#{opts}"
|
|
314
|
+
end
|
data/publish
CHANGED
|
@@ -78,4 +78,7 @@ update_version unless $version.nil?
|
|
|
78
78
|
####################################################################################################
|
|
79
79
|
|
|
80
80
|
system('gem', 'build', exception: true)
|
|
81
|
-
|
|
81
|
+
unless $dry
|
|
82
|
+
system('gem', 'push', "#$gem-#$version.gem", exception: true)
|
|
83
|
+
system('gem', 'install', $gem, exception: true)
|
|
84
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: optparse2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SamW
|
|
@@ -19,8 +19,10 @@ files:
|
|
|
19
19
|
- README.md
|
|
20
20
|
- Rakefile
|
|
21
21
|
- lib/optparse2.rb
|
|
22
|
+
- lib/optparse2/context.rb
|
|
22
23
|
- lib/optparse2/fixes.rb
|
|
23
24
|
- lib/optparse2/pathname.rb
|
|
25
|
+
- lib/optparse2/switch-helpers.rb
|
|
24
26
|
- lib/optparse2/version.rb
|
|
25
27
|
- publish
|
|
26
28
|
- sig/optparse2.rbs
|