flex_args 0.1.1 → 0.1.2
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/.rdoc_options +27 -0
- data/lib/flex_args/constraint.rb +150 -0
- data/lib/flex_args/enumerable.rb +18 -0
- data/lib/flex_args/parser.rb +125 -0
- data/lib/flex_args/version.rb +1 -1
- data/lib/flex_args.rb +131 -69
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5700aa1d881f51e7f2f44d30075e68367202e010ec71779193042f7efea70d95
|
4
|
+
data.tar.gz: aa46d04734fed4cf7776c3fe0c18c8fad391f5dc66a446c4fc664b8284deec79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc38f0a24e8d3589adacadabfeac2e1dfa7ce84ec2bd7b9def3fa6d2ef5bc2159ac1856136da273ea8a0f34c072ecfbb7008925544f9c27dec93edbf37206791
|
7
|
+
data.tar.gz: c349ad91b2f10bb6b463d88388cd34c7f48fba0c736de18754545b88f6aa0f02f5ec60e39ea685537046cf6629bae9188b12531935a98f2bd7db37b8902223da
|
data/.rdoc_options
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
encoding: UTF-8
|
3
|
+
static_path: []
|
4
|
+
rdoc_include: []
|
5
|
+
page_dir:
|
6
|
+
apply_default_exclude: true
|
7
|
+
autolink_excluded_words: []
|
8
|
+
charset: UTF-8
|
9
|
+
class_module_path_prefix:
|
10
|
+
embed_mixins: false
|
11
|
+
exclude: [tmp/*]
|
12
|
+
file_path_prefix:
|
13
|
+
hyperlink_all: false
|
14
|
+
line_numbers: false
|
15
|
+
locale_dir: locale
|
16
|
+
locale_name:
|
17
|
+
main_page:
|
18
|
+
markup: markdown
|
19
|
+
output_decoration: true
|
20
|
+
show_hash: false
|
21
|
+
skip_tests: true
|
22
|
+
tab_width: 8
|
23
|
+
template_stylesheets: []
|
24
|
+
title:
|
25
|
+
visibility: :protected
|
26
|
+
warn_missing_rdoc_ref: true
|
27
|
+
webcvs:
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FlexArgs
|
4
|
+
class Constraint
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
##
|
9
|
+
# ## Creates a new constraint for the value argument named `name`
|
10
|
+
#
|
11
|
+
# Constraints can be many, which is indicated by the first element
|
12
|
+
# in the `constraints` list, or a constraint can be indicated by
|
13
|
+
# a custom made block.
|
14
|
+
#
|
15
|
+
# The available constraints are:
|
16
|
+
#
|
17
|
+
# ### `Regexp` constraint
|
18
|
+
#
|
19
|
+
# These rdoc_specs show the interface that the `FlexArgs::Parser` uses
|
20
|
+
# to validate constraints, the class is therefore part of the public
|
21
|
+
# API and can be used in isolation where it serves.
|
22
|
+
#
|
23
|
+
# ```spec # regexp
|
24
|
+
# new(:for_some_value, %r{x}).("x") => [:ok, "x"]
|
25
|
+
# new(:for_some_value, %r{x}).("y") => [:error, "regexp constraint for_some_value: (?-mix:x) violated by value \"y\""]
|
26
|
+
# ```
|
27
|
+
#
|
28
|
+
# ### `Range` constraint
|
29
|
+
#
|
30
|
+
# ```spec # range
|
31
|
+
# new(:for_some_int, 1..9).("1") => [:ok, 1]
|
32
|
+
# new(:for_some_int, 1..9).("0") => [:error, "range constraint for_some_int: 1..9 violated by value \"0\""]
|
33
|
+
# new(:for_some_int, 1..9).("y") => [:error, "range constraint for_some_int: 1..9 violated by value \"y\""]
|
34
|
+
#
|
35
|
+
# ```
|
36
|
+
# ### Custom constraint
|
37
|
+
#
|
38
|
+
# This is easily implemented by passing a block which will return a pair as described above, but also note
|
39
|
+
# two more features of the custom constraint
|
40
|
+
#
|
41
|
+
# - exceptions will be caught and transformed into an error, thusly simplyfing the code block:
|
42
|
+
# - and values can be transformed
|
43
|
+
#
|
44
|
+
# ```spec # custom
|
45
|
+
# constraint = new :even do
|
46
|
+
# value = Integer(it)
|
47
|
+
# value.even? ? [:ok, value / 2] : [:error, "not even"]
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# expect(constraint.("84")).to eq([:ok, 42])
|
51
|
+
# expect(constraint.("21")).to eq([:error, "custom constraint even: violated by value \"21\" with message: \"not even\""])
|
52
|
+
#
|
53
|
+
# exception_message = '"invalid value for Integer(): \\"abc\\" (ArgumentError)"'
|
54
|
+
# complete_message = "custom constraint even: violated by value \"abc\" with message: #{exception_message}"
|
55
|
+
# expect(constraint.("abc")).to eq([:error, complete_message])
|
56
|
+
# ```
|
57
|
+
#
|
58
|
+
# Also note that the correct format of the block's return value is important
|
59
|
+
#
|
60
|
+
# ```spec # enforce correct format of custom constraint's block
|
61
|
+
# constraint = new(:bad) { 42 }
|
62
|
+
#
|
63
|
+
# expect { constraint.(nil) }
|
64
|
+
# .to raise_error(ArgumentError, "badly formatted custom block for custom constraint bad returned 42, needed [:ok|:error, value_or_message]")
|
65
|
+
# ```
|
66
|
+
#
|
67
|
+
def initialize(name, *constraints, &block)
|
68
|
+
@name = name
|
69
|
+
case constraints
|
70
|
+
in [Regexp => constraint]
|
71
|
+
_init_regexp(name, constraint)
|
72
|
+
in [Range => range]
|
73
|
+
_init_range(name, range)
|
74
|
+
else
|
75
|
+
raise ArgumentError,
|
76
|
+
"illegal constraint spec #{constraints.inspect} for value #{name}" unless block
|
77
|
+
_init_custom(name, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def call(value)
|
82
|
+
@constrainer.(value)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def _init_custom(name, &block)
|
88
|
+
bad_format = false
|
89
|
+
@constrainer = -> value do
|
90
|
+
case block.(value)
|
91
|
+
in [:error, message]
|
92
|
+
_make_error(:custom, name, nil, value, message)
|
93
|
+
in [:ok, _] => result
|
94
|
+
result
|
95
|
+
in result
|
96
|
+
bad_format = true
|
97
|
+
raise ArgumentError, "badly formatted custom block for custom constraint #{name} returned #{result.inspect}, needed [:ok|:error, value_or_message]"
|
98
|
+
end
|
99
|
+
rescue Exception => e
|
100
|
+
raise if bad_format
|
101
|
+
_make_error(:custom, name, nil, value, "#{e.message} (#{e.class})")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def _init_range(name, range)
|
106
|
+
@constrainer = -> value do
|
107
|
+
case _to_int(value)
|
108
|
+
in [:ok, int_val]
|
109
|
+
if range === int_val
|
110
|
+
[:ok, int_val]
|
111
|
+
else
|
112
|
+
_make_error(:range, name, range, value)
|
113
|
+
end
|
114
|
+
else
|
115
|
+
_make_error(:range, name, range, value)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def _init_regexp(name, constraint)
|
121
|
+
@constrainer = -> value do
|
122
|
+
if constraint.match?(value)
|
123
|
+
[:ok, value]
|
124
|
+
else
|
125
|
+
[:error, "regexp constraint #{name}: #{constraint} violated by value #{value.inspect}"]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def _make_error(type, name, constraint_desc, value, message = nil)
|
131
|
+
message = [
|
132
|
+
type,
|
133
|
+
"constraint",
|
134
|
+
"#{name}:",
|
135
|
+
constraint_desc,
|
136
|
+
"violated by value",
|
137
|
+
value.inspect,
|
138
|
+
(message ? "with message: #{message.inspect}" : nil)
|
139
|
+
].compact.join(" ")
|
140
|
+
[:error, message]
|
141
|
+
end
|
142
|
+
|
143
|
+
def _to_int(value)
|
144
|
+
[:ok, Integer(value)]
|
145
|
+
rescue ArgumentError
|
146
|
+
:error
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerable
|
4
|
+
def reduce_while(init, tag=nil, &block)
|
5
|
+
result =
|
6
|
+
reduce(init) do |i, e|
|
7
|
+
case block.(i, e)
|
8
|
+
in [:halt, value]
|
9
|
+
return value
|
10
|
+
in [:cont, value]
|
11
|
+
value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
tag ? [tag, result] : result
|
16
|
+
end
|
17
|
+
end
|
18
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'enumerable'
|
4
|
+
|
5
|
+
class FlexArgs
|
6
|
+
class Parser
|
7
|
+
attr_reader :args, :errors, :flags, :flex_args, :positionals, :values_from_args
|
8
|
+
|
9
|
+
ESCAPED_COMMA = "a4ey8NGnXIVhsV"
|
10
|
+
DIGITS = %r{\A [-+]? \d+ \z}x
|
11
|
+
MANY_FLAGS = %r{\A - (.*) \z}x
|
12
|
+
RANGE = %r{\A [-+]? \d+ \.\. [-+]? \d+ \z}x
|
13
|
+
SINGLE_FLAG = %r{\A -- (.*) \z}x
|
14
|
+
VALUE = %r{\A ([[:alpha:]][[:alnum:]_]*) : (.*) \z}x
|
15
|
+
|
16
|
+
def parse(args)
|
17
|
+
init_values
|
18
|
+
args.each { parse_arg it }
|
19
|
+
return [:ok, result] if errors.empty?
|
20
|
+
|
21
|
+
[:error, errors]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def initialize(flex_args)
|
26
|
+
@flex_args = flex_args
|
27
|
+
init_values
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_flags(shorts)
|
31
|
+
shorts.each do
|
32
|
+
flag = flex_args.alias_definitions.fetch(it, it)
|
33
|
+
flags << flag.to_sym
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_value(matches)
|
38
|
+
matches => [key, value]
|
39
|
+
key = key.to_sym
|
40
|
+
check_allowed!(key)
|
41
|
+
case check_constraints!(key, value)
|
42
|
+
in [:error, message]
|
43
|
+
errors << message
|
44
|
+
in [:ok, value]
|
45
|
+
values_from_args
|
46
|
+
.update(key => cast_all(value)) do |k, o, n|
|
47
|
+
Array(o) << n
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def cast(value)
|
53
|
+
case value
|
54
|
+
when RANGE
|
55
|
+
Range.new(*value.split("..").map(&:to_i))
|
56
|
+
when DIGITS
|
57
|
+
value.to_i
|
58
|
+
else
|
59
|
+
value.gsub(ESCAPED_COMMA, ",")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def cast_all(value)
|
64
|
+
return value unless String === value
|
65
|
+
value = value.gsub(",,", ESCAPED_COMMA)
|
66
|
+
values =
|
67
|
+
value
|
68
|
+
.split(",")
|
69
|
+
.map { cast it }
|
70
|
+
values.one? ? values.first : values
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_allowed!(key)
|
74
|
+
errors << "unallowed value arg #{key}:" unless flex_args.allowed?(key)
|
75
|
+
end
|
76
|
+
|
77
|
+
def check_constraints!(key, value)
|
78
|
+
constraints = flex_args.constraints(key)
|
79
|
+
constraints.reduce_while(value, :ok) do |v, constraint|
|
80
|
+
case constraint.(v)
|
81
|
+
in [:ok, val]
|
82
|
+
[:cont, val]
|
83
|
+
in [:error, message]
|
84
|
+
[:halt, [:error, message]]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def init_values
|
90
|
+
@errors = []
|
91
|
+
@flags = Set.new
|
92
|
+
@positionals = []
|
93
|
+
@values_from_args = Hash.new
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_arg(arg)
|
97
|
+
# require "debug"; binding.break
|
98
|
+
case arg
|
99
|
+
when SINGLE_FLAG
|
100
|
+
flags << Regexp.last_match[1].to_sym
|
101
|
+
when MANY_FLAGS
|
102
|
+
add_flags(Regexp.last_match[1].grapheme_clusters)
|
103
|
+
when VALUE
|
104
|
+
add_value(Regexp.last_match)
|
105
|
+
else
|
106
|
+
positionals << arg
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def result
|
111
|
+
OpenStruct.new(
|
112
|
+
positionals: positionals,
|
113
|
+
flags: flags,
|
114
|
+
values: values,
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
def values
|
119
|
+
flex_args
|
120
|
+
.default_values
|
121
|
+
.merge(values_from_args)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
data/lib/flex_args/version.rb
CHANGED
data/lib/flex_args.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'ostruct'
|
4
|
+
require_relative 'flex_args/constraint'
|
5
|
+
require_relative 'flex_args/parser'
|
4
6
|
|
5
7
|
##
|
6
8
|
# ## Abstract
|
@@ -14,11 +16,11 @@ require 'ostruct'
|
|
14
16
|
# ### Positional arguments
|
15
17
|
#
|
16
18
|
# Are all arguments that do not:
|
17
|
-
#
|
19
|
+
#
|
18
20
|
# - start with a `-`
|
19
21
|
# - contain any of the following characters: `:,`
|
20
22
|
# - contain the string `".."`
|
21
|
-
#
|
23
|
+
#
|
22
24
|
# Therefore the following arguments will be parsed as
|
23
25
|
#
|
24
26
|
# ```spec # Only default positional arguments
|
@@ -96,21 +98,19 @@ require 'ostruct'
|
|
96
98
|
#
|
97
99
|
class FlexArgs
|
98
100
|
|
99
|
-
|
100
|
-
DIGITS = %r{\A [-+]? \d+ \z}x
|
101
|
-
MANY_FLAGS = %r{\A - (.*) \z}x
|
102
|
-
RANGE = %r{\A [-+]? \d+ \.\. [-+]? \d+ \z}x
|
103
|
-
SINGLE_FLAG = %r{\A -- (.*) \z}x
|
104
|
-
VALUE = %r{\A ([[:alpha:]][[:alnum:]_]+) : (.*) \z}x
|
105
|
-
|
106
|
-
attr_reader :alias_definitions, :flags, :positionals, :result, :values
|
101
|
+
attr_reader :alias_definitions, :default_values, :result
|
107
102
|
|
108
103
|
def parse(args)
|
109
|
-
|
110
|
-
|
111
|
-
|
104
|
+
result = Parser.new(self).parse(args)
|
105
|
+
case result
|
106
|
+
in [:ok, result1]
|
107
|
+
result1
|
108
|
+
in [:error, errors]
|
109
|
+
raise ArgumentError, errors.join("\n")
|
110
|
+
end
|
112
111
|
end
|
113
112
|
|
113
|
+
|
114
114
|
##
|
115
115
|
#
|
116
116
|
# ## Aliases are defined by passing a hash
|
@@ -136,78 +136,140 @@ class FlexArgs
|
|
136
136
|
self
|
137
137
|
end
|
138
138
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
139
|
+
##
|
140
|
+
# ## Allowed values and flags
|
141
|
+
#
|
142
|
+
# As soon as this method is called the parser will
|
143
|
+
# check that **all** values in args are allowed
|
144
|
+
#
|
145
|
+
# Values are either identified by their name (a `Symbol`)
|
146
|
+
# or by their name and default value (a pair of `Symbol` and
|
147
|
+
# any value
|
148
|
+
#
|
149
|
+
# ```spec
|
150
|
+
# parser = FlexArgs
|
151
|
+
# .new
|
152
|
+
# .allow(:min, [:max, 3])
|
153
|
+
#
|
154
|
+
# expect(parser.parse(%w[min:1]).values)
|
155
|
+
# .to eq(min: 1, max: 3)
|
156
|
+
# ```
|
157
|
+
#
|
158
|
+
# Therefore the following args are illegal and an `ArgumentError`
|
159
|
+
# is raised
|
160
|
+
#
|
161
|
+
# ```spec # Argument Error for unallowed value
|
162
|
+
# expect do
|
163
|
+
# FlexArgs
|
164
|
+
# .new
|
165
|
+
# .allow(:n)
|
166
|
+
# .parse(%w[a:2])
|
167
|
+
# end
|
168
|
+
# .to raise_error(
|
169
|
+
# ArgumentError,
|
170
|
+
# "unallowed value arg a:"
|
171
|
+
# )
|
172
|
+
#
|
173
|
+
# ```
|
174
|
+
#
|
175
|
+
def allow(*values)
|
176
|
+
values.each { allow_value it }
|
177
|
+
self
|
143
178
|
end
|
144
179
|
|
145
|
-
def
|
146
|
-
|
147
|
-
|
148
|
-
flags << flag.to_sym
|
149
|
-
end
|
180
|
+
def allowed?(value)
|
181
|
+
return true unless @allowed_values
|
182
|
+
@allowed_values.member?(value)
|
150
183
|
end
|
151
184
|
|
152
|
-
def
|
153
|
-
matches => [key, value]
|
154
|
-
values
|
155
|
-
.update(key.to_sym => cast_all(value)) do |k, o, n|
|
156
|
-
Array(o) << n
|
157
|
-
end
|
158
|
-
end
|
185
|
+
def constraints(key) = @constraints[key]
|
159
186
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
187
|
+
##
|
188
|
+
# ## Constraints
|
189
|
+
#
|
190
|
+
# Constraints are defined with the `constraint` method.
|
191
|
+
#
|
192
|
+
# **N.B.** defined Constraints **after** allow unless you
|
193
|
+
# want to explicitly add the value arg with `allow`
|
194
|
+
#
|
195
|
+
# ### Simple forms
|
196
|
+
#
|
197
|
+
# #### Regexp constraint
|
198
|
+
#
|
199
|
+
# ```spec # regexp constraints
|
200
|
+
# parser = FlexArgs
|
201
|
+
# .new
|
202
|
+
# .constrain(:n, %r{\A \d+ \z}x)
|
203
|
+
#
|
204
|
+
# expect(parser.parse(%w[n:42]).values).to eq(n: 42)
|
205
|
+
#
|
206
|
+
# expect { parser.parse(%w[n:42a]) }
|
207
|
+
# .to raise_error(ArgumentError, 'regexp constraint n: (?x-mi:\A \d+ \z) violated by value "42a"')
|
208
|
+
#
|
209
|
+
# ```
|
210
|
+
#
|
211
|
+
# #### Range constraints
|
212
|
+
#
|
213
|
+
# ```spec # range constraints
|
214
|
+
# parser = FlexArgs
|
215
|
+
# .new
|
216
|
+
# .constrain(:n, 2..3)
|
217
|
+
#
|
218
|
+
# expect(parser.parse(%w[n:2]).values).to eq(n: 2)
|
219
|
+
#
|
220
|
+
# expect { parser.parse(%w[n:42a]) }
|
221
|
+
# .to raise_error(ArgumentError, 'range constraint n: 2..3 violated by value "42a"')
|
222
|
+
#
|
223
|
+
# expect { parser.parse(%w[n:42]) }
|
224
|
+
# .to raise_error(ArgumentError, 'range constraint n: 2..3 violated by value "42"')
|
225
|
+
#
|
226
|
+
# ```
|
227
|
+
#
|
228
|
+
# Please find the documentation about more constraints [here](Constraint.html)
|
229
|
+
#
|
230
|
+
def constrain(value, *constraints, &block)
|
231
|
+
@allowed_values << value.to_sym if @allowed_values
|
232
|
+
@constraints[value.to_sym] << Constraint.new(value, *constraints, &block)
|
233
|
+
self
|
169
234
|
end
|
170
235
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
236
|
+
##
|
237
|
+
#
|
238
|
+
# Just returns the parsed values, or their default values if
|
239
|
+
# a default was provided and the value was not present in
|
240
|
+
# the provided arguments.
|
241
|
+
def values
|
242
|
+
default_values.merge(values_from_args)
|
178
243
|
end
|
179
244
|
|
180
|
-
|
181
|
-
|
245
|
+
private
|
246
|
+
def initialize
|
247
|
+
@alias_definitions = Hash.new
|
248
|
+
@allowed_values = nil
|
249
|
+
@constraints = Hash.new { |h, k| h[k] = [] }
|
250
|
+
@default_values = Hash.new
|
182
251
|
end
|
183
252
|
|
184
|
-
def
|
185
|
-
|
186
|
-
@flags = Set.new
|
187
|
-
@values = Hash.new
|
253
|
+
def add_default_value(name, value)
|
254
|
+
default_values.update(name => value)
|
188
255
|
end
|
189
256
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
else
|
201
|
-
positionals << arg
|
257
|
+
def allow_value(value_def)
|
258
|
+
@allowed_values ||= Set.new
|
259
|
+
case value_def
|
260
|
+
in Symbol
|
261
|
+
@allowed_values << value_def
|
262
|
+
in [Symbol => value_name, default_value]
|
263
|
+
@allowed_values << value_name
|
264
|
+
add_default_value(value_name, default_value)
|
265
|
+
in _
|
266
|
+
raise ArgumentError, "arg must be of format Symbol or [Symbol, value], but was #{value_def}"
|
202
267
|
end
|
203
268
|
end
|
204
269
|
|
205
|
-
def
|
206
|
-
|
207
|
-
positionals: positionals,
|
208
|
-
flags: flags,
|
209
|
-
values: values,
|
210
|
-
)
|
270
|
+
def define_alias(short, long)
|
271
|
+
alias_definitions.update(short => long)
|
211
272
|
end
|
273
|
+
|
212
274
|
end
|
213
275
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flex_args
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
@@ -31,9 +31,13 @@ executables: []
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
+
- ".rdoc_options"
|
34
35
|
- LICENSE
|
35
36
|
- README.md
|
36
37
|
- lib/flex_args.rb
|
38
|
+
- lib/flex_args/constraint.rb
|
39
|
+
- lib/flex_args/enumerable.rb
|
40
|
+
- lib/flex_args/parser.rb
|
37
41
|
- lib/flex_args/version.rb
|
38
42
|
homepage: https://codeberg.org/lab419/flex_args
|
39
43
|
licenses:
|