l43_opt_parser 0.0.1 → 0.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/lib/l43/opt_parser/description.rb +62 -0
- data/lib/l43/opt_parser/flag.rb +14 -20
- data/lib/l43/opt_parser/keyword.rb +48 -28
- data/lib/l43/opt_parser/memos.rb +24 -0
- data/lib/l43/opt_parser/meta.rb +24 -0
- data/lib/l43/opt_parser/version.rb +1 -1
- data/lib/l43/opt_parser.rb +185 -64
- metadata +49 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 960127bd5fe3d57920703c562c1eb31335d8e1c3abef182ff4e673ee1479e70d
|
|
4
|
+
data.tar.gz: ba5380ffe585fd5dd198cc11eddedfad056c2d17667e8f446fdaccd34a0fea4d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4da0f00b58bb29dbb69f511e8404a5cb03664ba38ef03933ce7e4ff3e4e4963178d0b9716e0efc79e22534fc081c00ca6d5fe7de127356c2c35f7d7cdd2ce28d
|
|
7
|
+
data.tar.gz: 20062237a066a5d7eb15da190a36aa5dd74e1a415dab6ffc96dd8a9287374afc11ab125727030f7628b74acd98ec53df6fac6dbbb6c35401b9ba4c565b5f20f0
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'l43/core/none'
|
|
4
|
+
module L43
|
|
5
|
+
class OptParser
|
|
6
|
+
class Description
|
|
7
|
+
|
|
8
|
+
def add_desc(*chunks, indent: 5)
|
|
9
|
+
self << [indent, *chunks]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def add_flag(flag, indent: 3, color: :cyan)
|
|
13
|
+
return unless flag.desc
|
|
14
|
+
short = flag.short ? ":#{flag.short}|" : ""
|
|
15
|
+
self << [indent, color, short, ":", flag.name.to_s, :reset, 1, flag.desc ]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def add_kwd(kwd, indent: 3, color: :cyan, vcolor: [:bold,:blue])
|
|
19
|
+
return unless kwd.desc
|
|
20
|
+
short = kwd.short ? "#{kwd.short}:|" : ""
|
|
21
|
+
default = kwd.default == Core::None ? [] : [1, :dim, "defaults to: ", :bold, kwd.default.inspect]
|
|
22
|
+
self << [indent, color, short, kwd.name.to_s, ": ", vcolor, "<value>", :reset, 1, kwd.desc, *default]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_line(*chunks)
|
|
26
|
+
self << chunks
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def add_section(text, indent: 1, color: [:bold, :green])
|
|
30
|
+
self << [nil, indent, color, text]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add_usage(name, options:, args:)
|
|
34
|
+
options = "options" if options == true
|
|
35
|
+
args = "args" if args == true
|
|
36
|
+
@__lines__ = [[:bold, name, " ", *_args(options, [:bold, :cyan]), ' ', *_args(args, [:bold, :blue], "...")], *_lines]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def lines = _lines.dup.freeze
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
def _args(args, cols, pfx='')
|
|
43
|
+
case args
|
|
44
|
+
when nil
|
|
45
|
+
[]
|
|
46
|
+
when String
|
|
47
|
+
[cols, pfx, "[", args, "]", :reset]
|
|
48
|
+
else
|
|
49
|
+
args
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def _lines = @__lines__ ||= []
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def <<(*line)
|
|
57
|
+
_lines << [nil, *line.flatten, :reset]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
data/lib/l43/opt_parser/flag.rb
CHANGED
|
@@ -1,32 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'l43/open_object'
|
|
2
4
|
module L43
|
|
3
5
|
class OptParser
|
|
4
6
|
class Flag
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def on_multiple(&blk)
|
|
8
|
-
@on_multiple = blk
|
|
9
|
-
self
|
|
10
|
-
end
|
|
7
|
+
extend L43::OpenObject
|
|
8
|
+
attributes :name, arg_count: 0, as: nil, desc: nil, value: false, short: nil, stop: false
|
|
11
9
|
|
|
12
|
-
def
|
|
13
|
-
if
|
|
14
|
-
|
|
15
|
-
elsif multiple
|
|
16
|
-
[:ok, @on_multiple.(old_value, value)]
|
|
10
|
+
def count_ok
|
|
11
|
+
if arg_count.zero?
|
|
12
|
+
:ok
|
|
17
13
|
else
|
|
18
|
-
[:
|
|
14
|
+
[:error, "flag #{name} cannot be set multiple times"]
|
|
19
15
|
end
|
|
20
16
|
end
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
end
|
|
18
|
+
# def on_multiple(&blk)
|
|
19
|
+
# @on_multiple = blk
|
|
20
|
+
# self
|
|
21
|
+
# end
|
|
22
|
+
|
|
23
|
+
def real_name = as || name
|
|
30
24
|
end
|
|
31
25
|
end
|
|
32
26
|
end
|
|
@@ -1,44 +1,64 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'l43/core/enum/hash'
|
|
4
|
+
require 'l43/core/enum/set'
|
|
5
|
+
require 'l43/core/result'
|
|
6
|
+
require 'l43/open_object'
|
|
7
|
+
|
|
8
|
+
|
|
3
9
|
module L43
|
|
10
|
+
module Core::Result
|
|
11
|
+
def if_error(&blk)
|
|
12
|
+
return if ok?
|
|
13
|
+
blk.(self)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
4
17
|
class OptParser
|
|
5
18
|
class Keyword
|
|
6
|
-
|
|
19
|
+
Result = Core::Result
|
|
7
20
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
extend L43::OpenObject
|
|
22
|
+
attributes :name,
|
|
23
|
+
arg_count: 0,
|
|
24
|
+
as: nil,
|
|
25
|
+
default: nil,
|
|
26
|
+
desc: nil,
|
|
27
|
+
init: nil,
|
|
28
|
+
multiple: false,
|
|
29
|
+
set: nil,
|
|
30
|
+
short: nil,
|
|
31
|
+
value: nil
|
|
12
32
|
|
|
13
|
-
def
|
|
14
|
-
if
|
|
15
|
-
|
|
16
|
-
elsif old_value
|
|
17
|
-
value = make_value(value)
|
|
18
|
-
[:ok, @on_multiple.(old_value, value)]
|
|
19
|
-
elsif multiple
|
|
20
|
-
[:ok, [make_value(value)]]
|
|
21
|
-
else
|
|
22
|
-
[:ok, make_value(value)]
|
|
33
|
+
def assign_value(value)
|
|
34
|
+
if arg_count > 0 && !multiple
|
|
35
|
+
return Resut.error("must not assign multiple values to keyword #{name}")
|
|
23
36
|
end
|
|
37
|
+
|
|
38
|
+
assign_from_set(value).if_error { return it }
|
|
39
|
+
|
|
40
|
+
value = init.(value) if init
|
|
41
|
+
Result.ok(
|
|
42
|
+
update_attribute(:arg_count, &:succ)
|
|
43
|
+
.update_attribute(:value, simple_or_multiple(value))
|
|
44
|
+
)
|
|
24
45
|
end
|
|
25
46
|
|
|
47
|
+
def real_name = as || name
|
|
48
|
+
|
|
26
49
|
private
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
old ? [*old, value] : value
|
|
34
|
-
end
|
|
50
|
+
def assign_from_set(value)
|
|
51
|
+
return Result.ok(value) unless set
|
|
52
|
+
set
|
|
53
|
+
.fetch_any(value.to_sym, value.to_s) do
|
|
54
|
+
"bad value for keyword #{name}: #{value} (not in set: #{set.keys.inspect})"
|
|
55
|
+
end
|
|
35
56
|
end
|
|
36
57
|
|
|
37
|
-
def
|
|
38
|
-
value
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
value
|
|
58
|
+
def simple_or_multiple(value)
|
|
59
|
+
return value unless multiple
|
|
60
|
+
|
|
61
|
+
[*Array(self.value), value]
|
|
42
62
|
end
|
|
43
63
|
end
|
|
44
64
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module L43
|
|
4
|
+
class OptParser
|
|
5
|
+
module Memos
|
|
6
|
+
# Compile Time
|
|
7
|
+
# ------------
|
|
8
|
+
def aliases = @__aliases__ ||= {}
|
|
9
|
+
def checks = @__checks__ ||= []
|
|
10
|
+
def defaults = @__defaults__ ||= {}
|
|
11
|
+
def errors = @__errors__ ||= []
|
|
12
|
+
def flags = @__flags__ ||= {}
|
|
13
|
+
def hooks = @__hooks__ ||= []
|
|
14
|
+
def keywords = @__keywords__ ||= {}
|
|
15
|
+
|
|
16
|
+
# Result
|
|
17
|
+
# ------
|
|
18
|
+
def args = @__args__ ||= []
|
|
19
|
+
def keywords_values = @__keywords_values__ ||= {}
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'l43/open_object'
|
|
4
|
+
require 'l43/core/none'
|
|
5
|
+
module L43
|
|
6
|
+
class OptParser
|
|
7
|
+
module Meta
|
|
8
|
+
def make_open_object
|
|
9
|
+
OpenObject.def_class(*undefaulted_kwd_names, **defaulted_kwds_and_flags)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
def undefaulted_kwd_names
|
|
14
|
+
keywords.values.filter_map { it.default == Core::None && it.name }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def defaulted_kwds_and_flags
|
|
18
|
+
flag_defaults = flags.keys.map { [it, false] }.to_h
|
|
19
|
+
flag_defaults.merge(defaults)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
data/lib/l43/opt_parser.rb
CHANGED
|
@@ -1,45 +1,144 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require '
|
|
3
|
+
require 'l43/color/colorschemes'
|
|
4
|
+
require 'l43/color/output'
|
|
5
|
+
require 'l43/core/none'
|
|
6
|
+
require 'l43/open_struct'
|
|
7
|
+
require 'l43/open_object'
|
|
8
|
+
|
|
9
|
+
require_relative 'opt_parser/description'
|
|
4
10
|
require_relative 'opt_parser/errors'
|
|
5
11
|
require_relative 'opt_parser/flag'
|
|
6
12
|
require_relative 'opt_parser/keyword'
|
|
13
|
+
require_relative 'opt_parser/memos'
|
|
14
|
+
require_relative 'opt_parser/meta'
|
|
7
15
|
|
|
8
16
|
module L43
|
|
9
17
|
class OptParser
|
|
10
18
|
|
|
19
|
+
include Color::Output
|
|
20
|
+
include Core
|
|
21
|
+
include Memos
|
|
22
|
+
include Meta
|
|
23
|
+
|
|
24
|
+
BadFormat = Class.new(RuntimeError)
|
|
25
|
+
DuplicateFlagDefinition = Class.new(RuntimeError)
|
|
26
|
+
DuplicateKwdDefinition = Class.new(RuntimeError)
|
|
27
|
+
FailedCheck = Class.new(RuntimeError)
|
|
28
|
+
MissingValue = Class.new(RuntimeError)
|
|
29
|
+
UndefinedFlag = Class.new(RuntimeError)
|
|
30
|
+
UndefinedKwd = Class.new(RuntimeError)
|
|
31
|
+
|
|
11
32
|
FlagRgx = /\A:(.*)/
|
|
12
33
|
KeywordRgx = /(.*):\z/
|
|
34
|
+
ShortFlagRgx = /\A\-(.*)/
|
|
35
|
+
|
|
36
|
+
attr_reader :arguments, :constrained, :description, :kwds_name
|
|
13
37
|
|
|
14
38
|
# Constraints
|
|
15
39
|
# -----------
|
|
16
|
-
def flag(name,
|
|
17
|
-
|
|
40
|
+
def flag(name, short=nil, **kwds)
|
|
41
|
+
f = Flag.new(name:, short:, **kwds)
|
|
42
|
+
flags.merge!(name => f) { |*|
|
|
18
43
|
raise DuplicateFlagDefinition, "flag :#{name} is already defined"
|
|
19
44
|
}
|
|
45
|
+
if short
|
|
46
|
+
aliases.merge!(short => f) {|*|
|
|
47
|
+
raise DuplicateFlagDefinition, "flag :#{short} is already defined"
|
|
48
|
+
}
|
|
49
|
+
end
|
|
20
50
|
@constrained = true
|
|
51
|
+
description.add_flag(f)
|
|
21
52
|
self
|
|
22
53
|
end
|
|
23
54
|
|
|
24
|
-
|
|
25
|
-
|
|
55
|
+
|
|
56
|
+
def keyword(name, short=nil, as: nil, default: Core::None, **ks, &init)
|
|
57
|
+
k = Keyword.new(name:, short:, init:, default:, as:, **ks)
|
|
58
|
+
keywords.merge!(name => k) { |*|
|
|
26
59
|
raise DuplicateKeywordDefinition, "keyword :#{name} is already defined"
|
|
27
60
|
}
|
|
61
|
+
if short
|
|
62
|
+
aliases.merge!(short => k) {|*|
|
|
63
|
+
raise DuplicateKwdDefinition, "keyword :#{short} is already defined"
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
if default != Core::None
|
|
67
|
+
defaults.merge!((as||name) => default)
|
|
68
|
+
elsif k.multiple
|
|
69
|
+
defaults.merge!((as||name) => [])
|
|
70
|
+
end
|
|
28
71
|
@constrained = true
|
|
72
|
+
description.add_kwd(k)
|
|
29
73
|
self
|
|
30
74
|
end
|
|
31
75
|
|
|
76
|
+
# Documentation
|
|
77
|
+
# -------------
|
|
78
|
+
def add_br
|
|
79
|
+
description.add_line
|
|
80
|
+
self
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def add_desc(*chunks)
|
|
84
|
+
description.add_desc(*chunks)
|
|
85
|
+
self
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def section(line, indent: 1, color: [:bold, :green])
|
|
89
|
+
description.add_section(line, indent:, color:)
|
|
90
|
+
self
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Services
|
|
94
|
+
# --------
|
|
95
|
+
|
|
96
|
+
def descriptions = description.lines
|
|
97
|
+
def help(device: $stderr) = cs_put(descriptions, device:)
|
|
98
|
+
|
|
99
|
+
|
|
32
100
|
# Business Logic
|
|
33
101
|
# --------------
|
|
34
102
|
def parse(arguments)
|
|
35
|
-
reset_data!
|
|
36
103
|
@arguments = arguments
|
|
37
104
|
parse_arguments
|
|
38
105
|
|
|
39
|
-
|
|
106
|
+
return Result.error(errors) unless errors.empty?
|
|
107
|
+
if constrained
|
|
108
|
+
mo = make_open_object
|
|
109
|
+
kwds = mo.new(**defaults.merge(keywords_values))
|
|
110
|
+
post_checks!(kwds)
|
|
111
|
+
kwds = run_hooks(kwds)
|
|
112
|
+
result = OpenStruct.new(kwds_name => kwds, args:, errors:).freeze
|
|
113
|
+
Result.ok(result)
|
|
114
|
+
else
|
|
115
|
+
Result.ok(OpenStruct.new(args:, errors:, kwds: OpenStruct.new(**keywords_values)).freeze)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def post_hook(&blk)
|
|
120
|
+
hooks << blk
|
|
121
|
+
self
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def post_check(name = nil, &blk)
|
|
125
|
+
checks << [name, blk]
|
|
126
|
+
self
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def usage(name, options: nil, args: nil, nls: 0)
|
|
130
|
+
description.add_usage(name, options:, args:)
|
|
131
|
+
nls.times { add_br }
|
|
40
132
|
end
|
|
41
133
|
|
|
42
134
|
private
|
|
135
|
+
def initialize(with_help: false, kwds_name: :kwds)
|
|
136
|
+
@kwds_name = kwds_name
|
|
137
|
+
@description = Description.new
|
|
138
|
+
if with_help
|
|
139
|
+
flag(:help, :h, desc: "show this help and exit", stop: true)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
43
142
|
# Permissions
|
|
44
143
|
# -----------
|
|
45
144
|
def allowed_flag?(flag)
|
|
@@ -47,31 +146,26 @@ module L43
|
|
|
47
146
|
flags.fetch(flag, false)
|
|
48
147
|
end
|
|
49
148
|
|
|
50
|
-
def allowed_kwd?(kwd)
|
|
51
|
-
return true unless constrained?
|
|
52
|
-
keywords.fetch(kwd, false)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def check_kwd(kwd, value)
|
|
56
|
-
return unless constrained?
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
|
|
60
149
|
# Error Handling
|
|
61
150
|
# --------------
|
|
62
|
-
def add_errors(
|
|
151
|
+
def add_errors(*new_errors)
|
|
152
|
+
errors.push(*new_errors.flatten)
|
|
153
|
+
:error
|
|
154
|
+
end
|
|
63
155
|
|
|
64
156
|
# Business Logic
|
|
65
157
|
# --------------
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
158
|
+
def assign_keyword(kwd_sym, value)
|
|
159
|
+
case get_keyword(kwd_sym)
|
|
160
|
+
in :error
|
|
161
|
+
nil
|
|
162
|
+
in keyword
|
|
163
|
+
case keyword.assign_value(value)
|
|
164
|
+
in :error, error
|
|
165
|
+
nil
|
|
166
|
+
in :ok, keyword
|
|
167
|
+
keywords_values.merge!(keyword.real_name => keyword.value)
|
|
168
|
+
end
|
|
75
169
|
end
|
|
76
170
|
end
|
|
77
171
|
|
|
@@ -79,31 +173,50 @@ module L43
|
|
|
79
173
|
return value unless constrained?
|
|
80
174
|
end
|
|
81
175
|
|
|
82
|
-
def get_flag(
|
|
83
|
-
flags.fetch(
|
|
84
|
-
|
|
176
|
+
def get_flag(flag_sym)
|
|
177
|
+
flags.fetch(flag_sym) do
|
|
178
|
+
aliases.fetch(flag_sym) do
|
|
179
|
+
if constrained?
|
|
180
|
+
add_errors("undefined flag #{flag_sym}")
|
|
181
|
+
else
|
|
182
|
+
flags[flag_sym] = Flag.new(name: flag_sym)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
85
185
|
end
|
|
86
186
|
end
|
|
87
187
|
|
|
88
|
-
def get_keyword(
|
|
89
|
-
keywords.fetch(
|
|
90
|
-
|
|
188
|
+
def get_keyword(name)
|
|
189
|
+
keywords.fetch(name) do
|
|
190
|
+
aliases.fetch(name) do
|
|
191
|
+
if constrained
|
|
192
|
+
add_errors("undefined keyword: '#{name}'")
|
|
193
|
+
else
|
|
194
|
+
keywords[name] = Keyword.new(name:)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
91
197
|
end
|
|
92
198
|
end
|
|
93
199
|
|
|
200
|
+
def parse_all_flags(flags)
|
|
201
|
+
flags.grapheme_clusters.each { parse_flag(it.to_sym) }
|
|
202
|
+
1
|
|
203
|
+
end
|
|
204
|
+
|
|
94
205
|
def parse_argument
|
|
95
|
-
case
|
|
206
|
+
case arguments.first
|
|
96
207
|
when nil
|
|
97
208
|
return
|
|
98
209
|
when '::'
|
|
99
|
-
args.push(
|
|
210
|
+
args.push(*arguments.drop(1))
|
|
100
211
|
return
|
|
212
|
+
when ShortFlagRgx
|
|
213
|
+
parse_all_flags($1)
|
|
101
214
|
when FlagRgx
|
|
102
215
|
parse_flag($1.to_sym)
|
|
103
216
|
when KeywordRgx
|
|
104
217
|
parse_kwd($1.to_sym)
|
|
105
218
|
else
|
|
106
|
-
args <<
|
|
219
|
+
args << arguments.first
|
|
107
220
|
1
|
|
108
221
|
end
|
|
109
222
|
end
|
|
@@ -111,51 +224,59 @@ module L43
|
|
|
111
224
|
def parse_arguments
|
|
112
225
|
loop do
|
|
113
226
|
count = parse_argument
|
|
227
|
+
# p(args:, arguments:)
|
|
114
228
|
return unless count
|
|
115
229
|
@arguments = @arguments.drop(count)
|
|
116
230
|
end
|
|
117
231
|
end
|
|
118
232
|
|
|
119
|
-
def parse_flag(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
233
|
+
def parse_flag(flag_sym)
|
|
234
|
+
case get_flag(flag_sym)
|
|
235
|
+
in :error
|
|
236
|
+
nil
|
|
237
|
+
in flag
|
|
238
|
+
case flag.count_ok
|
|
239
|
+
in :ok
|
|
240
|
+
flag = flag
|
|
241
|
+
.update_attribute(:arg_count, &:succ)
|
|
242
|
+
.update(value: true)
|
|
243
|
+
keywords_values.merge!(flag.real_name => true)
|
|
244
|
+
in :error, error
|
|
245
|
+
add_errors(error)
|
|
246
|
+
end
|
|
128
247
|
end
|
|
129
248
|
1
|
|
130
249
|
end
|
|
131
250
|
|
|
132
|
-
def parse_kwd(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
end
|
|
251
|
+
def parse_kwd(kwd_sym)
|
|
252
|
+
case @arguments
|
|
253
|
+
in [_]
|
|
254
|
+
add_errors("keyword #{kwd_sym}: requires value but none was given, make sure there is an argument after '#{kwd_sym}:'")
|
|
255
|
+
in [_, value, *]
|
|
256
|
+
assign_keyword(kwd_sym, value)
|
|
257
|
+
end
|
|
140
258
|
2
|
|
141
259
|
end
|
|
142
260
|
|
|
261
|
+
def post_checks!(keywords)
|
|
262
|
+
checks.each do |name, check|
|
|
263
|
+
next if check.(keywords)
|
|
264
|
+
|
|
265
|
+
raise FailedCheck, "in postcheck #{name||check.source_location.join(":")}"
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def run_hooks(keywords)
|
|
270
|
+
hooks.inject keywords do |k, hook|
|
|
271
|
+
hook.(k)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
143
275
|
def symbolize(name) = name.to_s.gsub("-", "_").to_sym
|
|
144
276
|
|
|
145
277
|
# Data
|
|
146
278
|
# ----
|
|
147
|
-
def args = @__args__ ||= []
|
|
148
279
|
def constrained? = @constrained
|
|
149
|
-
def errors = @__errors__ ||= []
|
|
150
|
-
def kwds = @__kwds__ ||= {}
|
|
151
|
-
def flags = @__flags__ ||= {}
|
|
152
|
-
def keywords = @__keywords__ ||= {}
|
|
153
|
-
|
|
154
|
-
def reset_data!
|
|
155
|
-
@__args__ = []
|
|
156
|
-
@__errors__ = []
|
|
157
|
-
@__kwds__ = {}
|
|
158
|
-
end
|
|
159
280
|
|
|
160
281
|
end
|
|
161
282
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: l43_opt_parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Dober
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-04-26 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: ostruct
|
|
@@ -23,6 +23,48 @@ dependencies:
|
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: 0.6.3
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: l43_color
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 0.2.1
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 0.2.1
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: l43_core
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.2.8
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.2.8
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: l43_open_object
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 0.2.9
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 0.2.9
|
|
26
68
|
description: |
|
|
27
69
|
A highly customizable option parser, allowing for different
|
|
28
70
|
option syntax and returning custom classes' instances depending on
|
|
@@ -33,9 +75,12 @@ extensions: []
|
|
|
33
75
|
extra_rdoc_files: []
|
|
34
76
|
files:
|
|
35
77
|
- lib/l43/opt_parser.rb
|
|
78
|
+
- lib/l43/opt_parser/description.rb
|
|
36
79
|
- lib/l43/opt_parser/errors.rb
|
|
37
80
|
- lib/l43/opt_parser/flag.rb
|
|
38
81
|
- lib/l43/opt_parser/keyword.rb
|
|
82
|
+
- lib/l43/opt_parser/memos.rb
|
|
83
|
+
- lib/l43/opt_parser/meta.rb
|
|
39
84
|
- lib/l43/opt_parser/version.rb
|
|
40
85
|
homepage: https://codeberg.org/lab419/l43_opt_parser
|
|
41
86
|
licenses:
|
|
@@ -48,14 +93,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
48
93
|
requirements:
|
|
49
94
|
- - ">="
|
|
50
95
|
- !ruby/object:Gem::Version
|
|
51
|
-
version: 4.0.
|
|
96
|
+
version: 4.0.1
|
|
52
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
98
|
requirements:
|
|
54
99
|
- - ">="
|
|
55
100
|
- !ruby/object:Gem::Version
|
|
56
101
|
version: '0'
|
|
57
102
|
requirements: []
|
|
58
|
-
rubygems_version: 4.0.
|
|
103
|
+
rubygems_version: 4.0.10
|
|
59
104
|
specification_version: 4
|
|
60
105
|
summary: Extract Specs from Markdown
|
|
61
106
|
test_files: []
|