l43_opt_parser 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 63be9d1fa069240f7ef6fdd36805bb3af88c50519543465170bfb15dcd1af069
4
+ data.tar.gz: f54d8f9209b79139f896e8453e78010de27dd3bdd00c0aa6aa6db3f0713c8e4a
5
+ SHA512:
6
+ metadata.gz: fb4bf372fe886ef383b136b964499dbfc861fc6c67b7b58343eb63651b0ecf1b4235e66aacf865d0465f807386c4d330b844463af9c414351f598bf839a4072c
7
+ data.tar.gz: c332e0cb1dda8032e5636d9c96b5fc99d43f9c588140e3561ac48f0e7ebe7d6d7128bea88b67b968f90dc1a585c48574ad0dc77a1eedf4388adaec5833cce99e
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OptParser
4
+ DuplicateFlagDefinition = Class.new(RuntimeError)
5
+ DuplicateKeywordDefinition = Class.new(RuntimeError)
6
+ end
7
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ module L43
3
+ class OptParser
4
+ class Flag
5
+ attr_reader :multiple, :name
6
+
7
+ def on_multiple(&blk)
8
+ @on_multiple = blk
9
+ self
10
+ end
11
+
12
+ def update(value, old_value)
13
+ if old_value && !multiple
14
+ [:error, "flag :#{name} has already been specified but is not a multiple flag"]
15
+ elsif multiple
16
+ [:ok, @on_multiple.(old_value, value)]
17
+ else
18
+ [:ok, true]
19
+ end
20
+ end
21
+
22
+ private
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
30
+ end
31
+ end
32
+ end
33
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ class OptParser
5
+ class Keyword
6
+ attr_reader :initializer, :multiple, :name, :type
7
+
8
+ def on_multiple(&blk)
9
+ @on_multiple = blk
10
+ self
11
+ end
12
+
13
+ def update(value, old_value)
14
+ if old_value && !multiple
15
+ [:error, "keyword #{name} has already been specified but is not a multiple keyword"]
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)]
23
+ end
24
+ end
25
+
26
+ private
27
+ def initialize(name, multiple: false, type: String, &initializer)
28
+ @initializer = initializer
29
+ @name = name
30
+ @multiple = multiple
31
+ @type = type
32
+ on_multiple do |old, value|
33
+ old ? [*old, value] : value
34
+ end
35
+ end
36
+
37
+ def make_value(value)
38
+ value = type.new(value)
39
+ value = initializer.(value) if initializer
40
+ multiple
41
+ value
42
+ end
43
+ end
44
+ end
45
+ end
46
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ class OptParser
5
+ VERSION = '0.0.1'
6
+ end
7
+ end
8
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+ require_relative 'opt_parser/errors'
5
+ require_relative 'opt_parser/flag'
6
+ require_relative 'opt_parser/keyword'
7
+
8
+ module L43
9
+ class OptParser
10
+
11
+ FlagRgx = /\A:(.*)/
12
+ KeywordRgx = /(.*):\z/
13
+
14
+ # Constraints
15
+ # -----------
16
+ def flag(name, multiple: false)
17
+ flags.merge!(symbolize(name) => Flag.new(symbolize(name), multiple:)) { |*|
18
+ raise DuplicateFlagDefinition, "flag :#{name} is already defined"
19
+ }
20
+ @constrained = true
21
+ self
22
+ end
23
+
24
+ def keyword(name, multiple: false, type: String, &initializer)
25
+ keywords.merge!(name => Keyword.new(name, multiple:, type:, &initializer)) { |*|
26
+ raise DuplicateKeywordDefinition, "keyword :#{name} is already defined"
27
+ }
28
+ @constrained = true
29
+ self
30
+ end
31
+
32
+ # Business Logic
33
+ # --------------
34
+ def parse(arguments)
35
+ reset_data!
36
+ @arguments = arguments
37
+ parse_arguments
38
+
39
+ OpenStruct.new(args:, errors:, kwds:, ok?: errors.empty?).freeze
40
+ end
41
+
42
+ private
43
+ # Permissions
44
+ # -----------
45
+ def allowed_flag?(flag)
46
+ return true unless constrained?
47
+ flags.fetch(flag, false)
48
+ end
49
+
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
+ # Error Handling
61
+ # --------------
62
+ def add_errors(new_errors) = errors.push(*new_errors)
63
+
64
+ # Business Logic
65
+ # --------------
66
+ def assign_kwd(kwd, value)
67
+ error = check_kwd(kwd, value)
68
+ return add_errors(error) if error
69
+ keyword = get_keyword(kwd)
70
+ case keyword.update(value, kwds[kwd])
71
+ in :ok, value
72
+ kwds.merge!(kwd => value)
73
+ in :error, message
74
+ add_errors(message)
75
+ end
76
+ end
77
+
78
+ def cast_value(_kwd, value)
79
+ return value unless constrained?
80
+ end
81
+
82
+ def get_flag(flag)
83
+ flags.fetch(flag) do
84
+ flags[flag] = Flag.new(flag, multiple: true)
85
+ end
86
+ end
87
+
88
+ def get_keyword(kwd)
89
+ keywords.fetch(kwd) do
90
+ keywords[kwd] = Keyword.new(kwd, multiple: true)
91
+ end
92
+ end
93
+
94
+ def parse_argument
95
+ case @arguments.first
96
+ when nil
97
+ return
98
+ when '::'
99
+ args.push(*@arguments.drop(1))
100
+ return
101
+ when FlagRgx
102
+ parse_flag($1.to_sym)
103
+ when KeywordRgx
104
+ parse_kwd($1.to_sym)
105
+ else
106
+ args << @arguments.first
107
+ 1
108
+ end
109
+ end
110
+
111
+ def parse_arguments
112
+ loop do
113
+ count = parse_argument
114
+ return unless count
115
+ @arguments = @arguments.drop(count)
116
+ end
117
+ end
118
+
119
+ def parse_flag(flag)
120
+ add_errors("undefined flag: :#{flag}") unless allowed_flag?(flag)
121
+
122
+ defined_flag = get_flag(flag)
123
+ case defined_flag.update(1, kwds[flag])
124
+ in :ok, value
125
+ kwds.merge!(flag => value)
126
+ in :error, message
127
+ add_errors(message)
128
+ end
129
+ 1
130
+ end
131
+
132
+ def parse_kwd(kwd)
133
+ add_errors("undefined keyword: #{kwd}:") unless allowed_kwd?(kwd)
134
+ case @arguments
135
+ in [_]
136
+ add_errors("keyword #{kwd}: requires value but none was given, make sure there is an argument after '#{kwd}:'")
137
+ in [_, value, *]
138
+ assign_kwd(kwd, value)
139
+ end
140
+ 2
141
+ end
142
+
143
+ def symbolize(name) = name.to_s.gsub("-", "_").to_sym
144
+
145
+ # Data
146
+ # ----
147
+ def args = @__args__ ||= []
148
+ 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
+
160
+ end
161
+ end
162
+ # SPDX-License-Identifier: AGPL-3.0-or-later
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: l43_opt_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robert Dober
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-02-10 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ostruct
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.6.3
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.6.3
26
+ description: |
27
+ A highly customizable option parser, allowing for different
28
+ option syntax and returning custom classes' instances depending on
29
+ the configured options
30
+ email: robert.dober@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - lib/l43/opt_parser.rb
36
+ - lib/l43/opt_parser/errors.rb
37
+ - lib/l43/opt_parser/flag.rb
38
+ - lib/l43/opt_parser/keyword.rb
39
+ - lib/l43/opt_parser/version.rb
40
+ homepage: https://codeberg.org/lab419/l43_opt_parser
41
+ licenses:
42
+ - AGPL-3.0-or-later
43
+ metadata: {}
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 4.0.0
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubygems_version: 4.0.4
59
+ specification_version: 4
60
+ summary: Extract Specs from Markdown
61
+ test_files: []