l43_opt_parser 0.0.2 → 0.2.1
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/errors.rb +11 -3
- data/lib/l43/opt_parser/flag.rb +9 -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 +178 -64
- metadata +47 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7480fcd5f83ef14a37ccbe58bf3beea44d2ce219a87c686be600051b10879870
|
|
4
|
+
data.tar.gz: faab1f7444bcd6d8a1e479206a6d1a18a40d9b9da901e32cb084663b7ef0ea7a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2f99db96ded13ab47be70b22dc1a89c8fd0e553cfb4d44ec58b79e5c8d596347ea8199e0c639d336a8691156cd9e0e4444e860662d4354f50c8916c596622e8
|
|
7
|
+
data.tar.gz: abfd0ec70ee9b4ebfff30abe8bea87e6c0d2a4f650b63997e12271e18f5d06d174d27d1d50fd7f92f34f55ba555c49db904c652a2994e59c2ef56645f46d9f48
|
|
@@ -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
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
module L43
|
|
4
|
+
class OptParser
|
|
5
|
+
BadFormat = Class.new(RuntimeError)
|
|
6
|
+
DuplicateFlagDefinition = Class.new(RuntimeError)
|
|
7
|
+
DuplicateFlagDefinition = Class.new(RuntimeError)
|
|
8
|
+
DuplicateKeywordDefinition = Class.new(RuntimeError)
|
|
9
|
+
FailedCheck = Class.new(RuntimeError)
|
|
10
|
+
MissingValue = Class.new(RuntimeError)
|
|
11
|
+
UndefinedFlag = Class.new(RuntimeError)
|
|
12
|
+
UndefinedKwd = Class.new(RuntimeError)
|
|
13
|
+
end
|
|
6
14
|
end
|
|
7
15
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
data/lib/l43/opt_parser/flag.rb
CHANGED
|
@@ -1,32 +1,21 @@
|
|
|
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
|
-
def initialize(name, multiple: false)
|
|
24
|
-
@name = name
|
|
25
|
-
@multiple = multiple
|
|
26
|
-
on_multiple do |old, value|
|
|
27
|
-
old ? old.succ : value
|
|
28
|
-
end
|
|
29
|
-
end
|
|
18
|
+
def real_name = as || name
|
|
30
19
|
end
|
|
31
20
|
end
|
|
32
21
|
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,137 @@
|
|
|
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
|
+
|
|
11
25
|
FlagRgx = /\A:(.*)/
|
|
12
26
|
KeywordRgx = /(.*):\z/
|
|
27
|
+
ShortFlagRgx = /\A\-(.*)/
|
|
28
|
+
|
|
29
|
+
attr_reader :arguments, :constrained, :description, :kwds_name
|
|
13
30
|
|
|
14
31
|
# Constraints
|
|
15
32
|
# -----------
|
|
16
|
-
def flag(name,
|
|
17
|
-
|
|
33
|
+
def flag(name, short=nil, **kwds)
|
|
34
|
+
f = Flag.new(name:, short:, **kwds)
|
|
35
|
+
flags.merge!(name => f) { |*|
|
|
18
36
|
raise DuplicateFlagDefinition, "flag :#{name} is already defined"
|
|
19
37
|
}
|
|
38
|
+
if short
|
|
39
|
+
aliases.merge!(short => f) {|*|
|
|
40
|
+
raise DuplicateFlagDefinition, "flag :#{short} is already defined"
|
|
41
|
+
}
|
|
42
|
+
end
|
|
20
43
|
@constrained = true
|
|
44
|
+
description.add_flag(f)
|
|
21
45
|
self
|
|
22
46
|
end
|
|
23
47
|
|
|
24
|
-
|
|
25
|
-
|
|
48
|
+
|
|
49
|
+
def keyword(name, short=nil, as: nil, default: Core::None, **ks, &init)
|
|
50
|
+
k = Keyword.new(name:, short:, init:, default:, as:, **ks)
|
|
51
|
+
keywords.merge!(name => k) { |*|
|
|
26
52
|
raise DuplicateKeywordDefinition, "keyword :#{name} is already defined"
|
|
27
53
|
}
|
|
54
|
+
if short
|
|
55
|
+
aliases.merge!(short => k) {|*|
|
|
56
|
+
raise DuplicateKeywordDefinition, "keyword :#{short} is already defined"
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
if default != Core::None
|
|
60
|
+
defaults.merge!((as||name) => default)
|
|
61
|
+
elsif k.multiple
|
|
62
|
+
defaults.merge!((as||name) => [])
|
|
63
|
+
end
|
|
28
64
|
@constrained = true
|
|
65
|
+
description.add_kwd(k)
|
|
29
66
|
self
|
|
30
67
|
end
|
|
31
68
|
|
|
69
|
+
# Documentation
|
|
70
|
+
# -------------
|
|
71
|
+
def add_br
|
|
72
|
+
description.add_line
|
|
73
|
+
self
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def add_desc(*chunks)
|
|
77
|
+
description.add_desc(*chunks)
|
|
78
|
+
self
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def section(line, indent: 1, color: [:bold, :green])
|
|
82
|
+
description.add_section(line, indent:, color:)
|
|
83
|
+
self
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Services
|
|
87
|
+
# --------
|
|
88
|
+
|
|
89
|
+
def descriptions = description.lines
|
|
90
|
+
def help(device: $stderr) = cs_put(descriptions, device:)
|
|
91
|
+
|
|
92
|
+
|
|
32
93
|
# Business Logic
|
|
33
94
|
# --------------
|
|
34
95
|
def parse(arguments)
|
|
35
|
-
reset_data!
|
|
36
96
|
@arguments = arguments
|
|
37
97
|
parse_arguments
|
|
38
98
|
|
|
39
|
-
|
|
99
|
+
return Result.error(errors) unless errors.empty?
|
|
100
|
+
if constrained
|
|
101
|
+
mo = make_open_object
|
|
102
|
+
kwds = mo.new(**defaults.merge(keywords_values))
|
|
103
|
+
post_checks!(kwds)
|
|
104
|
+
kwds = run_hooks(kwds)
|
|
105
|
+
result = OpenStruct.new(kwds_name => kwds, args:, errors:).freeze
|
|
106
|
+
Result.ok(result)
|
|
107
|
+
else
|
|
108
|
+
Result.ok(OpenStruct.new(args:, errors:, kwds: OpenStruct.new(**keywords_values)).freeze)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def post_hook(&blk)
|
|
113
|
+
hooks << blk
|
|
114
|
+
self
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def post_check(name = nil, &blk)
|
|
118
|
+
checks << [name, blk]
|
|
119
|
+
self
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def usage(name, options: nil, args: nil, nls: 0)
|
|
123
|
+
description.add_usage(name, options:, args:)
|
|
124
|
+
nls.times { add_br }
|
|
40
125
|
end
|
|
41
126
|
|
|
42
127
|
private
|
|
128
|
+
def initialize(with_help: false, kwds_name: :kwds)
|
|
129
|
+
@kwds_name = kwds_name
|
|
130
|
+
@description = Description.new
|
|
131
|
+
if with_help
|
|
132
|
+
flag(:help, :h, desc: "show this help and exit", stop: true)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
43
135
|
# Permissions
|
|
44
136
|
# -----------
|
|
45
137
|
def allowed_flag?(flag)
|
|
@@ -47,31 +139,26 @@ module L43
|
|
|
47
139
|
flags.fetch(flag, false)
|
|
48
140
|
end
|
|
49
141
|
|
|
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
142
|
# Error Handling
|
|
61
143
|
# --------------
|
|
62
|
-
def add_errors(
|
|
144
|
+
def add_errors(*new_errors)
|
|
145
|
+
errors.push(*new_errors.flatten)
|
|
146
|
+
:error
|
|
147
|
+
end
|
|
63
148
|
|
|
64
149
|
# Business Logic
|
|
65
150
|
# --------------
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
151
|
+
def assign_keyword(kwd_sym, value)
|
|
152
|
+
case get_keyword(kwd_sym)
|
|
153
|
+
in :error
|
|
154
|
+
nil
|
|
155
|
+
in keyword
|
|
156
|
+
case keyword.assign_value(value)
|
|
157
|
+
in :error, error
|
|
158
|
+
nil
|
|
159
|
+
in :ok, keyword
|
|
160
|
+
keywords_values.merge!(keyword.real_name => keyword.value)
|
|
161
|
+
end
|
|
75
162
|
end
|
|
76
163
|
end
|
|
77
164
|
|
|
@@ -79,31 +166,50 @@ module L43
|
|
|
79
166
|
return value unless constrained?
|
|
80
167
|
end
|
|
81
168
|
|
|
82
|
-
def get_flag(
|
|
83
|
-
flags.fetch(
|
|
84
|
-
|
|
169
|
+
def get_flag(flag_sym)
|
|
170
|
+
flags.fetch(flag_sym) do
|
|
171
|
+
aliases.fetch(flag_sym) do
|
|
172
|
+
if constrained?
|
|
173
|
+
add_errors("undefined flag #{flag_sym}")
|
|
174
|
+
else
|
|
175
|
+
flags[flag_sym] = Flag.new(name: flag_sym)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
85
178
|
end
|
|
86
179
|
end
|
|
87
180
|
|
|
88
|
-
def get_keyword(
|
|
89
|
-
keywords.fetch(
|
|
90
|
-
|
|
181
|
+
def get_keyword(name)
|
|
182
|
+
keywords.fetch(name) do
|
|
183
|
+
aliases.fetch(name) do
|
|
184
|
+
if constrained
|
|
185
|
+
add_errors("undefined keyword: '#{name}'")
|
|
186
|
+
else
|
|
187
|
+
keywords[name] = Keyword.new(name:)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
91
190
|
end
|
|
92
191
|
end
|
|
93
192
|
|
|
193
|
+
def parse_all_flags(flags)
|
|
194
|
+
flags.grapheme_clusters.each { parse_flag(it.to_sym) }
|
|
195
|
+
1
|
|
196
|
+
end
|
|
197
|
+
|
|
94
198
|
def parse_argument
|
|
95
|
-
case
|
|
199
|
+
case arguments.first
|
|
96
200
|
when nil
|
|
97
201
|
return
|
|
98
202
|
when '::'
|
|
99
|
-
args.push(
|
|
203
|
+
args.push(*arguments.drop(1))
|
|
100
204
|
return
|
|
205
|
+
when ShortFlagRgx
|
|
206
|
+
parse_all_flags($1)
|
|
101
207
|
when FlagRgx
|
|
102
208
|
parse_flag($1.to_sym)
|
|
103
209
|
when KeywordRgx
|
|
104
210
|
parse_kwd($1.to_sym)
|
|
105
211
|
else
|
|
106
|
-
args <<
|
|
212
|
+
args << arguments.first
|
|
107
213
|
1
|
|
108
214
|
end
|
|
109
215
|
end
|
|
@@ -111,51 +217,59 @@ module L43
|
|
|
111
217
|
def parse_arguments
|
|
112
218
|
loop do
|
|
113
219
|
count = parse_argument
|
|
220
|
+
# p(args:, arguments:)
|
|
114
221
|
return unless count
|
|
115
222
|
@arguments = @arguments.drop(count)
|
|
116
223
|
end
|
|
117
224
|
end
|
|
118
225
|
|
|
119
|
-
def parse_flag(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
226
|
+
def parse_flag(flag_sym)
|
|
227
|
+
case get_flag(flag_sym)
|
|
228
|
+
in :error
|
|
229
|
+
nil
|
|
230
|
+
in flag
|
|
231
|
+
case flag.count_ok
|
|
232
|
+
in :ok
|
|
233
|
+
flag = flag
|
|
234
|
+
.update_attribute(:arg_count, &:succ)
|
|
235
|
+
.update(value: true)
|
|
236
|
+
keywords_values.merge!(flag.real_name => true)
|
|
237
|
+
in :error, error
|
|
238
|
+
add_errors(error)
|
|
239
|
+
end
|
|
128
240
|
end
|
|
129
241
|
1
|
|
130
242
|
end
|
|
131
243
|
|
|
132
|
-
def parse_kwd(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
end
|
|
244
|
+
def parse_kwd(kwd_sym)
|
|
245
|
+
case @arguments
|
|
246
|
+
in [_]
|
|
247
|
+
add_errors("keyword #{kwd_sym}: requires value but none was given, make sure there is an argument after '#{kwd_sym}:'")
|
|
248
|
+
in [_, value, *]
|
|
249
|
+
assign_keyword(kwd_sym, value)
|
|
250
|
+
end
|
|
140
251
|
2
|
|
141
252
|
end
|
|
142
253
|
|
|
254
|
+
def post_checks!(keywords)
|
|
255
|
+
checks.each do |name, check|
|
|
256
|
+
next if check.(keywords)
|
|
257
|
+
|
|
258
|
+
raise FailedCheck, "in postcheck #{name||check.source_location.join(":")}"
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def run_hooks(keywords)
|
|
263
|
+
hooks.inject keywords do |k, hook|
|
|
264
|
+
hook.(k)
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
143
268
|
def symbolize(name) = name.to_s.gsub("-", "_").to_sym
|
|
144
269
|
|
|
145
270
|
# Data
|
|
146
271
|
# ----
|
|
147
|
-
def args = @__args__ ||= []
|
|
148
272
|
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
273
|
|
|
160
274
|
end
|
|
161
275
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: l43_opt_parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Dober
|
|
@@ -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,7 +93,7 @@ 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
|
- - ">="
|