lab42_rgxargs 0.1.2 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d995928882bad168df974b923ccb5d725eb86bbd56a694cedd9059ef568e6ad
4
- data.tar.gz: 4e4194883792088934889ebd8f7a6fdcd6126ad55cf1fa3a0eb30249ad938d0a
3
+ metadata.gz: 3879a325fa817a79a35ca494b7d7550aac9d6d6a25702d7ab07efbbf51d2c3d1
4
+ data.tar.gz: 7446e1f864db187211f4327222eb3fad7d6f6e20abd5ebaecdd7a6185039600f
5
5
  SHA512:
6
- metadata.gz: fb3138610aa1d243ed7bc5d7b7b782901b788d5b75b50e227f7cc0d5ba3ca0f524f8f501139bb67ac808a4b697f915afe89312a0c2f3ec4bf4396cce81d75908
7
- data.tar.gz: f662d35d67de38063f978716ca85a9e68548c71dd428867e4354d3706b6d070a3c5efd4fd18e3e55ac375aba9a7b218f5fe5fefe04e63a33e407646fbfd54671
6
+ metadata.gz: 9ac9b5cf9ed52197f16c647c5d5202e0a47efbcc98a5ed5ba89b8bebaa81eb4966f06f9b681ad5b0186939c715c45f1e1c3c14cdb03658724778ab55b614192e
7
+ data.tar.gz: 373b64cf35bd6949585afbbd8123ff309f09239d1ad2090156c211862f8b2159ff07fed9478bb43eabf63a12f978145c1ef064e27c34572a637de2139c0cbaa8
@@ -4,121 +4,151 @@ require 'lab42/enumerable'
4
4
  module Lab42
5
5
 
6
6
  class Rgxargs
7
+ require_relative 'rgxargs/checker'
8
+ require_relative 'rgxargs/constrainer'
7
9
  require_relative 'rgxargs/predefined_matchers'
10
+ require_relative 'rgxargs/argument_matcher'
11
+ require_relative 'rgxargs/syntax_definer'
12
+ include Checker
13
+ include Constrainer
14
+
8
15
  Predefined = PredefinedMatchers
9
16
 
10
17
  extend Forwardable
11
18
  def_delegators Predefined, :list_matcher
12
19
 
13
- attr_reader :args, :conversions, :defined_rules, :errors, :options, :syntaxes
20
+ attr_reader :allowed, :args, :conversions, :defaults, :defined_rules, :errors, :options, :required, :syntaxes
14
21
 
15
22
 
16
- def add_conversion(param, conversion)
23
+ def add_conversion(param, conversion, required=nil, &block)
17
24
  case conversion
18
25
  when Symbol
19
- conversions[param] = Predefined.fetch(conversion, conversion)
26
+ _add_symbolic_conversion(param, conversion, required)
20
27
  else
21
- conversions[param] = conversion
28
+ _add_proc_conversion(param, conversion, block, required)
22
29
  end
23
30
  end
24
31
 
25
32
  def add_syntax(rgx, parser=nil, as: nil)
26
- if parser
27
- syntaxes << [rgx, parser, as]
28
- else
29
- if predef = Predefined.fetch(rgx, as: as)
30
- syntaxes << predef
31
- else
32
- raise ArgumentError, "#{rgx} is not a predefined syntax, use one of the following:\n\t#{Predefined.defined_names}"
33
- end
33
+ case rgx
34
+ when Symbol, Regexp
35
+ syntaxes << ArgumentMatcher.new(rgx, parser, arg_name: as)
36
+ when Array
37
+ rgx.each do |rg1|
38
+ add_syntax( rg1, parser, as: as)
34
39
  end
35
40
  end
41
+ end
36
42
 
37
- def parse argv
38
- until argv.empty?
39
- argv = _parse_next argv
40
- end
41
- [options, args, errors]
43
+ def define_arg name, &blk
44
+ SyntaxDefiner.new(self, name).run(blk)
45
+ end
46
+
47
+ def parse argv
48
+ until argv.empty?
49
+ argv = _parse_next argv
42
50
  end
51
+ _check_required_kwds
52
+ [options, args, errors]
53
+ end
43
54
 
44
55
 
45
- private
56
+ private
46
57
 
47
- def initialize &blk
48
- @args = []
49
- @conversions = {}
50
- @defined_rules = []
51
- @errors = []
52
- @options = OpenStruct.new
53
- @syntaxes = []
58
+ def initialize &blk
59
+ @args = []
60
+ @allowed = nil
61
+ @conversions = {}
62
+ @defaults = {}
63
+ @defined_rules = []
64
+ @errors = []
65
+ @required = Set.new
66
+ @syntaxes = []
54
67
 
55
- instance_exec(&blk) if blk
56
- end
68
+ instance_exec(&blk) if blk
69
+ @options = OpenStruct.new(defaults)
70
+ end
57
71
 
58
- def _convert(value, name:)
59
- conv = conversions.fetch(name, nil)
60
- case conv
61
- when Symbol
62
- value.send conv
63
- when Proc
64
- conv.(value)
65
- when Array
66
- if (match = conv.first.match(value))
67
- conv[1].(match.captures)
68
- else
69
- errors << [:syntax_error, name, "#{value} does not match #{conv.first}"]
70
- nil
71
- end
72
+ def _convert(value, name:)
73
+ conv = conversions.fetch(name, nil)
74
+ case conv
75
+ when Symbol
76
+ value.send conv
77
+ when Proc
78
+ conv.(value)
79
+ when Array
80
+ if (match = conv.first.match(value))
81
+ conv[1].(*match.captures)
72
82
  else
73
- value
83
+ errors << [:syntax_error, name, "#{value} does not match #{conv.first}"]
84
+ nil
74
85
  end
86
+ else
87
+ value
75
88
  end
89
+ end
76
90
 
77
- def _defined_rules(_arg)
78
- false
91
+ def _add_proc_conversion(param, conversion, block, required)
92
+ Array(param).each do |para|
93
+ @required.add para if required == :required
94
+ conversions[para] = block ? [conversion, block] : conversion
79
95
  end
96
+ end
80
97
 
81
- def _parse_next argv
82
- first, *rest = argv
83
- if _defined_rules(first)
84
- return rest
85
- end
86
- _parse_symbolic first, rest
98
+ def _add_symbolic_conversion(param, conversion, required)
99
+ Array(param).each do |para|
100
+ @required.add para if required == :required
101
+ conversions[para] = Predefined.fetch(conversion, conversion)
87
102
  end
103
+ end
88
104
 
89
- def _parse_symbolic first, rest
90
- case first
91
- when %r{\A:(.*)}
92
- options[$1.gsub('-','_').to_sym]=true
93
- rest
94
- when %r{(.*):\z}
95
- _parse_value $1.gsub('-', '_').to_sym, rest
96
- else
97
- _parse_syntax(first)
98
- rest
99
- end
105
+ def _parse_next argv
106
+ first, *rest = argv
107
+ if first == '--'
108
+ @args += rest
109
+ return []
100
110
  end
111
+ _parse_symbolic first, rest
112
+ end
101
113
 
102
- def _parse_syntax first
103
- value, as = syntaxes.find_value(first) do |(rgx, converter, as)|
104
- (match = rgx.match(first)) && [converter.(match.captures), as]
105
- end
106
- if as
107
- options[as] = value
108
- else
109
- args << value
110
- end
114
+ def _parse_symbolic first, rest
115
+ case first
116
+ when %r{\A:(.*)}
117
+ switch = $1.gsub('-','_').to_sym
118
+ _check_switch(switch)
119
+ options[switch]=true
120
+ rest
121
+ when %r{(.*):\z}
122
+ kwd = $1.gsub('-', '_').to_sym
123
+ _check_kwd(kwd)
124
+ _parse_value kwd, rest
125
+ when %r{\A\\(.*)}
126
+ args << $1
127
+ rest
128
+ else
129
+ _parse_syntax(first)
130
+ rest
111
131
  end
132
+ end
112
133
 
113
- def _parse_value name, rest
114
- value, *rest1 = rest
115
- if value
116
- options[name] = _convert(value, name: name)
117
- return rest1
118
- end
119
- errors << [:missing_required_value, name]
120
- []
134
+ def _parse_syntax first
135
+ value, as = syntaxes.find_value(first){ |matcher| matcher.match(first) }
136
+ if as
137
+ options[as] = value
138
+ else
139
+ args << value
121
140
  end
141
+ end
122
142
 
143
+ def _parse_value name, rest
144
+ value, *rest1 = rest
145
+ if value
146
+ options[name] = _convert(value, name: name)
147
+ return rest1
148
+ end
149
+ errors << [:missing_required_value, name]
150
+ []
123
151
  end
152
+
124
153
  end
154
+ end
@@ -0,0 +1,35 @@
1
+ class Lab42::Rgxargs::ArgumentMatcher
2
+ require_relative './error'
3
+ require_relative './predefined_matchers'
4
+
5
+ Predefined = Lab42::Rgxargs::PredefinedMatchers
6
+ Error = Lab42::Rgxargs::Error
7
+
8
+ attr_reader :arg_name, :converter, :matcher
9
+
10
+
11
+
12
+ def match value
13
+ case matcher
14
+ when Regexp
15
+ match = matcher.match(value)
16
+ match && [converter.(*match.captures), arg_name]
17
+ else
18
+ matcher.to_s == value && [converter.(), arg_name]
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def initialize(matcher, converter, arg_name: nil)
25
+ @arg_name = arg_name
26
+ @matcher = matcher
27
+ @converter = converter || _get_predefined
28
+ end
29
+
30
+ def _get_predefined
31
+ @matcher, converter = Predefined.fetch(matcher) { raise Error, "undefined syntax #{matcher}" }
32
+ converter
33
+ end
34
+
35
+ end
@@ -0,0 +1,33 @@
1
+ module Lab42
2
+ class Rgxargs
3
+ module Checker
4
+
5
+ private
6
+
7
+ def _check_kwd(kwd)
8
+ return if allowed.nil?
9
+ return if allowed.member? kwd
10
+ return if required.member? kwd
11
+ errors << [:unauthorized_kwd, kwd]
12
+ end
13
+
14
+ def _check_required_kwds
15
+ missing = required - options.to_h.keys
16
+ @errors += missing.map(&_mk_pair(:required_kwd_missing))
17
+ end
18
+
19
+
20
+ def _mk_pair(prefix)
21
+ -> element do
22
+ [prefix, element]
23
+ end
24
+ end
25
+
26
+ def _check_switch(_)
27
+
28
+ end
29
+
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ module Lab42
2
+ class Rgxargs
3
+ module Constrainer
4
+
5
+ def allow_kwds(*kwds)
6
+ @allowed = (allowed||Set.new).union(Set.new(kwds.flatten))
7
+ end
8
+
9
+ def require_kwds(*kwds)
10
+ @required = (required||Set.new).union(Set.new(kwds.flatten))
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,2 @@
1
+ class Lab42::Rgxargs::Error < RuntimeError
2
+ end
@@ -1,27 +1,27 @@
1
1
  module Lab42::Rgxargs::PredefinedMatchers extend self
2
2
  PREDEFINED = {
3
- int_list: [%r{\A(-?\d+(?:,-?\d+)*)\z}, ->(groups){ groups.first.split(",").map(&:to_i)}],
4
- int_range: [%r{\A(-?\d+)(?:-|\.\.)(-?\d+)\z}, ->((f, l)){ Range.new(f.to_i, l.to_i) }],
5
- list: [%r{(\w+)(?:,(\w+))*}, ->(groups){ groups.compact }],
6
- range: [%r{\A(\d+)\.\.(\d+)\z}, ->(groups){ Range.new(*groups.map(&:to_i)) }]
3
+ int: [%r{\A([-+]?\d+)\z}, :to_i.to_proc],
4
+ int_list: [%r{\A(-?\d+(?:,-?\d+)*)\z}, ->(*groups){ groups.first.split(",").map(&:to_i)}],
5
+ int_range: [%r{\A(-?\d+)(?:-|\.\.)(-?\d+)\z}, ->(f, l){ Range.new(f.to_i, l.to_i) }],
6
+ list: [%r{(\w+)(?:,(\w+))*}, ->(*groups){ groups.compact }],
7
+ range: [%r{\A(\d+)\.\.(\d+)\z}, ->(*groups){ Range.new(*groups.map(&:to_i)) }]
7
8
  }
8
9
 
9
10
  def defined_names
10
11
  @__defined_names__ ||= PREDEFINED.keys.join("\n\t")
11
12
  end
12
13
 
13
- def fetch(key, default=nil, as: nil, &blk)
14
- return PREDEFINED[key] + [as] if PREDEFINED.has_key?(key)
14
+ def fetch(key, default=nil, &blk)
15
+ return PREDEFINED[key] if PREDEFINED.has_key?(key)
15
16
  blk ? blk.(key) : default
16
17
  end
17
18
 
18
19
  def list_matcher values
19
- [%r{\A((?:#{values.join("|")})(?:,(?:#{values.join("|")}))*)\z}, _list_extractor]
20
+ [%r{\A((?:#{values.join("|")})(?:,(?:#{values.join("|")}))*)\z}, method(:_list_extractor)]
20
21
  end
21
22
 
22
23
 
23
- # Memoized
24
- def _list_extractor
25
- @__list_extractor__ ||= ->(groups){ groups.first.split(",") }
24
+ def _list_extractor(*groups)
25
+ groups.first.split(",")
26
26
  end
27
27
  end
@@ -0,0 +1,19 @@
1
+ class Lab42::Rgxargs::Syntax
2
+
3
+ attr_reader :converter, :matcher
4
+
5
+ def matches? value
6
+ if match = matcher.match(value)
7
+ yield converter.(*match.captures)
8
+ true
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def initialize matcher, converter
15
+ @converter = converter
16
+ @matcher = matcher
17
+ end
18
+
19
+ end
@@ -0,0 +1,34 @@
1
+ # Instanciated with an Rgxargs parser it can run a block
2
+ # in its own context so that the block accesses the
3
+ # parser's functionality with syntactic sugar w/o cluttering
4
+ # ther parser itself with too many methods
5
+ # E.g.:
6
+ #
7
+ # ```ruby
8
+ # syntax
9
+ #
10
+ # ```
11
+ class Lab42::Rgxargs::SyntaxDefiner
12
+
13
+
14
+ attr_reader :arg_name, :parser
15
+
16
+ def run code
17
+ instance_exec(&code)
18
+ end
19
+
20
+ def syntax(matcher, value=nil, &blk)
21
+ if value
22
+ parser.add_syntax(matcher, ->(){value}, as: arg_name )
23
+ else
24
+ parser.add_syntax(matcher, blk, as: arg_name)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def initialize(parser, arg_name)
31
+ @arg_name = arg_name
32
+ @parser = parser
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ module Lab42
2
+ class Rgxargs
3
+ VERSION = "0.1.7"
4
+ end
5
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lab42_rgxargs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Dober
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-18 00:00:00.000000000 Z
11
+ date: 2020-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: speculate_about
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.2
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rspec
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,20 @@ dependencies:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '3.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-doc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
41
69
  description: Parse CL args according to regexen
42
70
  email: robert.dober@gmail.com
43
71
  executables: []
@@ -46,12 +74,19 @@ extra_rdoc_files: []
46
74
  files:
47
75
  - lib/lab42/enumerable.rb
48
76
  - lib/lab42/rgxargs.rb
77
+ - lib/lab42/rgxargs/argument_matcher.rb
78
+ - lib/lab42/rgxargs/checker.rb
79
+ - lib/lab42/rgxargs/constrainer.rb
80
+ - lib/lab42/rgxargs/error.rb
49
81
  - lib/lab42/rgxargs/predefined_matchers.rb
82
+ - lib/lab42/rgxargs/syntax.rb
83
+ - lib/lab42/rgxargs/syntax_definer.rb
84
+ - lib/lab42/rgxargs/version.rb
50
85
  homepage: https://github.com/robertdober/lab42_rgxargs
51
86
  licenses:
52
87
  - Apache-2.0
53
88
  metadata: {}
54
- post_install_message:
89
+ post_install_message:
55
90
  rdoc_options: []
56
91
  require_paths:
57
92
  - lib
@@ -59,15 +94,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
59
94
  requirements:
60
95
  - - ">="
61
96
  - !ruby/object:Gem::Version
62
- version: '0'
97
+ version: 2.7.0
63
98
  required_rubygems_version: !ruby/object:Gem::Requirement
64
99
  requirements:
65
100
  - - ">="
66
101
  - !ruby/object:Gem::Version
67
102
  version: '0'
68
103
  requirements: []
69
- rubygems_version: 3.0.6
70
- signing_key:
104
+ rubygems_version: 3.1.2
105
+ signing_key:
71
106
  specification_version: 4
72
107
  summary: Parse CL args according to regexen
73
108
  test_files: []