l43_rgx 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 16234666a82b0ee1a42c90674890ec10a4ae5e64ae38c067520e51c4bec64796
4
+ data.tar.gz: 2472f2c910a99c485b67c31c43012be28c6516b428c3d3a7dd87ec8754935586
5
+ SHA512:
6
+ metadata.gz: 3d4d321341fa59397399d892a8e224999932534739b91aaa26925e0ee2d3e43aab8734fcb986fa4ceda8ba892d968b70fe80436532424787bb6bd911077b09b8
7
+ data.tar.gz: 916dc34de7fc7589c809ad916eed701798de220efbaf6478993bba32f78a11bcb941f13fefa75c23ef8ef0c17170b7454c17b2126b66a4e59ee5baeec43d5e5f
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../rgx'
4
+ def Rgx(*parts, **options, &callback) = L43::Rgx.new(*parts, **options, &callback)
5
+ Rgx = L43::Rgx
6
+ Result = Rgx::Result
7
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ class Rgx
5
+ module Compile
6
+
7
+ private
8
+ def _a_anchor
9
+ "\\A" if [:begin, :both].member?(anchored)
10
+ end
11
+
12
+ def _capture_rest
13
+ @___capture_rest__ ||= "(.*)\\z" if capture_rest
14
+ end
15
+
16
+ def _compile
17
+ @source = [a_anchor, look_behind, compiled_parts, look_ahead, _capture_rest, z_anchor].join.freeze
18
+ @regexp = Regexp.compile(source).freeze
19
+ end
20
+
21
+ def _compile_part(part, level: 0)
22
+ case part
23
+ in String
24
+ part
25
+ in Symbol
26
+ repr = part.to_s
27
+ if repr.end_with?("s")
28
+ "[[:#{repr[0...-1]}:]]+"
29
+ else
30
+ "[[:#{repr}:]]"
31
+ end
32
+ in Integer
33
+ "{#{part}}"
34
+ in Range
35
+ "{#{part.first},#{part.last}}"
36
+ in Array
37
+ raise CompilationError, "nested groups are not allowed" if level.positive?
38
+ "(#{part.map { _compile_part(it, level: level.succ) }.join})"
39
+ else
40
+ if self.class === part
41
+ raise CompilationError, "part is anchored, only use unanchored instances of #{self.class}" if part.anchored?
42
+ part.source
43
+ else
44
+ raise CompilationError, "part: #{part.inspect} needs to be a string, symbol, integer or range"
45
+ end
46
+ end
47
+ end
48
+
49
+ def _compiled_parts
50
+ parts.map { _compile_part it }.join
51
+ end
52
+
53
+ def _look_ahead
54
+ if followed_by
55
+ followed = self.class.new(*Array(followed_by)).source
56
+ "(?=#{followed})"
57
+ elsif not_followed_by
58
+ followed = self.class.new(*Array(not_followed_by)).source
59
+ "(?!#{followed})"
60
+ end
61
+ end
62
+
63
+ def _look_behind
64
+ if preceded_by
65
+ preceded = self.class.new(*Array(preceded_by)).source
66
+ "(?<=#{preceded})"
67
+ elsif not_preceded_by
68
+ preceded = self.class.new(*Array(not_preceded_by)).source
69
+ "(?<!#{preceded})"
70
+ end
71
+ end
72
+
73
+ def _z_anchor
74
+ "\\z" if [:end, :both].member?(anchored)
75
+ end
76
+
77
+ def a_anchor = @__a_anchor__ ||= _a_anchor
78
+ def compiled_parts = @__compiled_parts__ ||= _compiled_parts
79
+ def look_ahead = @___look_ahead__ ||= _look_ahead
80
+ def look_behind = @___look_behind__ ||= _look_behind
81
+ def z_anchor = @__z_anchor__ ||= _z_anchor
82
+
83
+ end
84
+ end
85
+ end
86
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ class Rgx
5
+ CompilationError = Class.new(RuntimeError)
6
+ end
7
+ end
8
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ class Rgx
5
+ module Methods
6
+
7
+ def or(*parts, **options)
8
+ self.class.new(wrap, "|", self.class.new(*parts, **options).wrap)
9
+ end
10
+
11
+ def many(min: 0)
12
+ inner_part = wrap
13
+ new_source =
14
+ case min
15
+ in 0
16
+ "#{inner_part}*"
17
+ in 1
18
+ "#{inner_part}+"
19
+ else
20
+ "#{inner_part}{#{min},}"
21
+ end
22
+ self.class.new(new_source)
23
+ end
24
+
25
+ def wrap = _wrap(self)
26
+
27
+ private
28
+ def _wrap(part)
29
+ case part
30
+ when String
31
+ "(?:#{part})"
32
+ when Rgx
33
+ "(?:#{part.source})"
34
+ else
35
+ raise ArgumentError, "_wrap needs string or rgx, not #{part.inspect}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ class Rgx
5
+ class Result
6
+
7
+ attr_reader :captures
8
+
9
+ def deconstruct(*) = captures
10
+
11
+ def ==(other)
12
+ self.class === other && captures == other.captures
13
+ end
14
+
15
+ private
16
+ def initialize(captures)
17
+ @captures = captures.freeze
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module L43
4
+ class Rgx
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
8
+ # SPDX-License-Identifier: AGPL-3.0-or-later
data/lib/l43/rgx.rb ADDED
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'rgx/errors'
4
+ require_relative 'rgx/compile'
5
+ require_relative 'rgx/methods'
6
+ require_relative 'rgx/result'
7
+ require 'l43/core/forwarder'
8
+
9
+ module L43
10
+ class Rgx
11
+ extend L43::Core::Forwarder
12
+ include Compile
13
+ include Methods
14
+
15
+ LegalAnchors = [nil, :begin, :both, :end].freeze
16
+
17
+ attr_reader :regexp, :source
18
+ forward :match, to: :regexp
19
+
20
+ def anchored? = anchored || capture_rest
21
+ def anchored_at_begin? = [:begin, :both].member?(anchored)
22
+ def anchored_at_end? = [:end, :both].member?(anchored)
23
+
24
+ def run(subject, include_match: false)
25
+ case regexp.match(subject)
26
+ in nil
27
+ nil
28
+ in md
29
+ if callback
30
+ Result.new(Array(callback.(*md.to_a)))
31
+ else
32
+ include_match ? Result.new(md.to_a) : Result.new(md.captures)
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+ attr_reader \
39
+ :anchored,
40
+ :callback, :capture_rest,
41
+ :followed_by,
42
+ :not_followed_by, :not_preceded_by,
43
+ :parts, :preceded_by
44
+
45
+ def initialize(*parts,
46
+ anchored: nil,
47
+ capture_rest: false,
48
+ followed_by: nil,
49
+ not_followed_by: nil,
50
+ not_preceded_by: nil,
51
+ preceded_by: nil,
52
+ &callback)
53
+
54
+ raise ArgumentError, "must not provide followed_by and not_followed_by at the same time" if followed_by && not_followed_by
55
+ raise ArgumentError, "must not provide preceded_by and not_preceded_by at the same time" if preceded_by && not_preceded_by
56
+ raise ArgumentError, "illegal value for keyword argument capture_rest, must be a boolean, but was #{capture_rest.inspect}" unless
57
+ [false, true].member?(capture_rest)
58
+ raise ArgumentError, "illegal value for keyword argument anchored, must be in #{LegalAnchors.inspect}, but was: #{anchored.inspect}" unless
59
+ LegalAnchors.member?(anchored)
60
+
61
+ @anchored = anchored
62
+ raise ArgumentError, "must not use capture_rest with anchored :end or :both" if anchored_at_end? && capture_rest
63
+ raise ArgumentError, "must not use lookahead assertion (followed_by) with anchored :end or :both" if anchored_at_end? && followed_by
64
+ raise ArgumentError, "must not use negative lookahead assertion (not_followed_by) with anchored :end or :both" if anchored_at_end? && not_followed_by
65
+ raise ArgumentError, "must not use negative lookahead assertion (not_followed_by) with capture_rest" if anchored_at_end? && capture_rest
66
+
67
+ raise ArgumentError, "must not use lookbehind assertion (preceded_by) with anchored :begin or :both" if anchored_at_begin? && preceded_by
68
+ raise ArgumentError, "must not use negative lookbehind assertion (not_preceded_by) with anchored :begin or :both" if anchored_at_begin? && not_preceded_by
69
+
70
+ @anchored = anchored
71
+ @callback = callback
72
+ @capture_rest = capture_rest
73
+ @followed_by = followed_by
74
+ @not_followed_by = not_followed_by
75
+ @not_preceded_by = not_preceded_by
76
+ @parts = parts.freeze
77
+ @preceded_by = preceded_by
78
+
79
+ _compile
80
+ end
81
+
82
+ end
83
+ end
84
+ # SPDX-License-Identifier: AGPL-3.0-or-later
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: l43_rgx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Robert Dober
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-09-08 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
+ - !ruby/object:Gem::Dependency
27
+ name: l43_core
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.2.9
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.9
40
+ description: 'Human Readable Regexp Wrapper and Tools
41
+
42
+ '
43
+ email: robert.dober@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/l43/rgx.rb
49
+ - lib/l43/rgx/all.rb
50
+ - lib/l43/rgx/compile.rb
51
+ - lib/l43/rgx/errors.rb
52
+ - lib/l43/rgx/methods.rb
53
+ - lib/l43/rgx/result.rb
54
+ - lib/l43/rgx/version.rb
55
+ homepage: https://codeberg.org/lab419/l43_rgx
56
+ licenses:
57
+ - AGPL-3.0-or-later
58
+ metadata: {}
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 4.0.2
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubygems_version: 4.0.19
74
+ specification_version: 4
75
+ summary: Human Readable Regexp Wrapper and Tools
76
+ test_files: []