help_parser 8.1.221206 → 8.2.230210

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 157ae793a16a5b92ca1633306080465fcd2e9671aaed67dc01fb47cb318f0824
4
- data.tar.gz: cc72ed9f03c94ef2f5455897807a49ba69e79786ceae5daa3d158d3265e9a931
3
+ metadata.gz: f19d24ec56736d0d1bbcce1e0a847ac45e9d82defc89c7799c7b9c8c7c4ae078
4
+ data.tar.gz: fe92cf2d740771329bee184dd205d59bc72c1265d79ac50af3a6c4d0fa735297
5
5
  SHA512:
6
- metadata.gz: aea35622e25f8fd0cf84cc3115ce15b524440e698f516ebbd89188fa56d30c098dcc8711d61cee4b07aa7b77f935091222c2b0ff71465480d0e9cf76530810f5
7
- data.tar.gz: 88a2613d9487be0b11e0da90bef805abc5fc1a7ca0012a97b32d5aa62540f382cc91e38b6714e4279bdba319475b323126625b4cf092e037742f30ba1c4ee22a
6
+ metadata.gz: f20dad3a1453e625236af9cb176328652352e9f2f35f00da02cc6ab1853671c82ae13d5ec8226247be116cbd82bdbb4aee24490200f04b2ddba79e380822f36b
7
+ data.tar.gz: 0aebde782784afb644dd1047f32af8de07d07af4c53435ec47ed8c8f7e54a3997a6e6a08c372f23e1a38f37c10f6e0604c26afcb5f16b8d7677120891f10ed71
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Help Parser VIII: Helpland
2
2
 
3
- * [VERSION 8.1.221206](https://github.com/carlosjhr64/help_parser/releases)
3
+ * [VERSION 8.2.230210](https://github.com/carlosjhr64/help_parser/releases)
4
4
  * [github](https://www.github.com/carlosjhr64/help_parser)
5
5
  * [rubygems](https://rubygems.org/gems/help_parser)
6
6
 
@@ -11,11 +11,9 @@ Do you have your help text?
11
11
  Let's parse!
12
12
 
13
13
  ## INSTALL:
14
-
15
14
  ```console
16
15
  $ gem install help_parser
17
16
  ```
18
-
19
17
  ## SYNOPSIS:
20
18
  <!-- The following PREVIEW has been approved for ALL PROGRAMMERS by CarlosJHR64.
21
19
  For the README validator that checks against me lying....
@@ -32,7 +30,6 @@ end
32
30
  The following gem has been rated
33
31
  | M | Mature |
34
32
  -->
35
-
36
33
  ```ruby
37
34
  require "help_parser"
38
35
 
@@ -96,9 +93,9 @@ OPTIONS.args?.class #=> Array
96
93
  OPTIONS.arg? and OPTIONS.arg #=> false
97
94
  OPTIONS.arg?.class #=> FalseClass
98
95
  ```
99
-
100
96
  ## Features
101
97
 
98
+ * `ARGV` setup for `ARGF` when one of the "Types:" given is "ARGF"
102
99
  * `$DEBUG=true` on --debug
103
100
  * `$VERBOSE=true` on --verbose
104
101
  * -h and --help simultaneously will check help string for errors
@@ -108,7 +105,7 @@ OPTIONS.arg?.class #=> FalseClass
108
105
 
109
106
  (The MIT License)
110
107
 
111
- Copyright (c) 2022 CarlosJHR64
108
+ Copyright (c) 2023 CarlosJHR64
112
109
 
113
110
  Permission is hereby granted, free of charge, to any person obtaining
114
111
  a copy of this software and associated documentation files (the
@@ -1,14 +1,14 @@
1
1
  module HelpParser
2
2
  class NoDupHash < Hash
3
3
  def []=(k,v)
4
- raise HelpError, MSG[DUP_KEY,k] if self.has_key?(k)
4
+ raise HelpError, MSG[DUP_KEY,k] if key?(k)
5
5
  super
6
6
  end
7
7
  end
8
8
 
9
9
  class ArgvHash < Hash
10
10
  def []=(k,v)
11
- raise UsageError, MSG[DUP_KEY,k] if self.has_key?(k)
11
+ raise UsageError, MSG[DUP_KEY,k] if key?(k)
12
12
  super
13
13
  end
14
14
  end
@@ -3,26 +3,35 @@ module HelpParser
3
3
  def initialize(hash, specs)
4
4
  @hash,@specs = hash,specs
5
5
  @cache = NoDupHash.new
6
- usage or diagnose if @specs.has_key?(USAGE)
6
+ usage or diagnose if @specs.key?(USAGE)
7
7
  pad
8
- types if @specs.has_key?(TYPES)
8
+ if @specs.key?(TYPES)
9
+ k2t = types
10
+ handle_argf(k2t) if k2t.detect{|_,v|v=='ARGF'}
11
+ end
12
+ end
13
+
14
+ # Prepare ARGV for ARGF.
15
+ def handle_argf(k2t)
16
+ files = @hash.select{|k,_|k2t[k]=='ARGF'}.map{|_,v|v}.flatten
17
+ e = files.reject{File.exist?_1}.join(', ')
18
+ raise UsageError, MSG[NOT_EXIST, e] unless e.empty?
19
+ ARGV.replace files
9
20
  end
10
21
 
11
22
  # Which usage does the user's command options match?
12
23
  def usage
13
24
  @specs[USAGE].each do |cmd|
14
- begin
15
- i = matches(cmd)
16
- raise NoMatch unless @hash.size==i
17
- @cache.each{|k,v|@hash[k]=v} # Variables
18
- return true # Good! Found matching usage.
19
- rescue NoMatch
20
- next
21
- ensure
22
- @cache.clear
23
- end
25
+ i = matches(cmd)
26
+ raise NoMatch unless @hash.size==i
27
+ @cache.each{|k,v|@hash[k]=v} # Variables
28
+ return true # Good! Found matching usage.
29
+ rescue NoMatch
30
+ next
31
+ ensure
32
+ @cache.clear
24
33
  end
25
- return false # Bad! Did not match any of the expected usage.
34
+ false # Bad! Did not match any of the expected usage.
26
35
  end
27
36
 
28
37
  # Diagnose user's usage.
@@ -37,7 +46,7 @@ module HelpParser
37
46
  end
38
47
  end
39
48
  end
40
- typos = @hash.keys.select{|k|k.is_a? String and not dict[k]}
49
+ typos = @hash.keys.select{_1.is_a?(String) && !dict[_1]}
41
50
  raise UsageError, MSG[UNRECOGNIZED, typos] unless typos.empty?
42
51
 
43
52
  raise UsageError, MATCH_USAGE
@@ -46,26 +55,25 @@ module HelpParser
46
55
  def types
47
56
  t2r,k2t = HelpParser.t2r(@specs),HelpParser.k2t(@specs)
48
57
  @hash.each do |key,value|
49
- next unless key.is_a?(String)
50
- if type = k2t[key]
51
- regex = t2r[type]
52
- case value
53
- when String
54
- unless value=~regex
55
- raise UsageError, "--#{key}=#{value} !~ #{type}=#{regex.inspect}"
56
- end
57
- when Array
58
- value.each do |string|
59
- unless string=~regex
60
- raise UsageError,
61
- "--#{key}=#{string} !~ #{type}=#{regex.inspect}"
62
- end
58
+ next unless key.is_a?(String) && (type=k2t[key])
59
+ regex = t2r[type]
60
+ case value
61
+ when String
62
+ unless value=~regex
63
+ raise UsageError, "--#{key}=#{value} !~ #{type}=#{regex.inspect}"
64
+ end
65
+ when Array
66
+ value.each do |string|
67
+ unless string=~regex
68
+ raise UsageError,
69
+ "--#{key}=#{string} !~ #{type}=#{regex.inspect}"
63
70
  end
64
- else
65
- raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
66
71
  end
72
+ else
73
+ raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
67
74
  end
68
75
  end
76
+ k2t
69
77
  end
70
78
 
71
79
  def pad
@@ -79,12 +87,12 @@ module HelpParser
79
87
  if second[0]=='-'
80
88
  i = second.index('=') || 0
81
89
  short,long = first[1],second[2..(i-1)]
82
- if @hash.has_key?(short)
83
- if @hash.has_key?(long)
90
+ if @hash.key?(short)
91
+ if @hash.key?(long)
84
92
  raise UsageError, MSG[REDUNDANT, short, long]
85
93
  end
86
- @hash[long] = (default.nil?) ? true : default
87
- elsif value = @hash[long]
94
+ @hash[long] = default.nil? ? true : default
95
+ elsif (value=@hash[long])
88
96
  @hash[short] = true
89
97
  if value==true && !default.nil?
90
98
  @hash.delete(long) # ArgvHash reset
@@ -117,7 +125,7 @@ module HelpParser
117
125
  # OK, NEVERMIND!
118
126
  end
119
127
  next
120
- elsif m=FLAG_GROUP.match(token)
128
+ elsif (m=FLAG_GROUP.match token)
121
129
  group,plus = m[:k],m[:p]
122
130
  key = keys[i]
123
131
  raise NoMatch unless key.is_a? String
@@ -126,11 +134,11 @@ module HelpParser
126
134
  unless plus.nil?
127
135
  loop do
128
136
  key = keys[i+1]
129
- break unless key.is_a?(String) and list.include?(key)
137
+ break unless key.is_a?(String) && list.include?(key)
130
138
  i+=1
131
139
  end
132
140
  end
133
- elsif m=VARIABLE.match(token)
141
+ elsif (m=VARIABLE.match(token))
134
142
  key = keys[i]
135
143
  raise NoMatch unless key.is_a?(Integer)
136
144
  variable,plus = m[:k],m[:p]
@@ -153,7 +161,7 @@ module HelpParser
153
161
  end
154
162
  i += 1
155
163
  end
156
- return i
164
+ i
157
165
  end
158
166
  end
159
167
  end
@@ -1,6 +1,6 @@
1
1
  module HelpParser
2
- VSN = ['v','version']
3
- HLP = ['h','help']
2
+ VSN = %w[v version]
3
+ HLP = %w[h help]
4
4
  VRBS,DBG = 'verbose','debug'
5
5
 
6
6
  # reserved name
@@ -16,19 +16,19 @@ module HelpParser
16
16
  SECTION_NAME = /^(?<name>[A-Z]\w+):$/
17
17
 
18
18
  # usage
19
- FLAG = /^[-][-]?(?<k>\w+)$/
19
+ FLAG = /^--?(?<k>\w+)$/
20
20
  LITERAL = /^(?<k>\w[\w.-]*:?)$/
21
21
  VARIABLE = /^<(?<k>\w+)(=(?<t>[A-Z]+))?>(?<p>[+])?$/
22
22
  FLAG_GROUP = /^:(?<k>\w+)(?<p>[+])?$/
23
23
 
24
24
  # spec --?w+
25
- SHORT = /^[-](?<s>\w)$/
26
- LONG = /^[-][-](?<k>\w+)(=(?<t>[A-Z]+))?(,?\s+(?<d>[^-\s]\S*))?$/
25
+ SHORT = /^-(?<s>\w)$/
26
+ LONG = /^--(?<k>\w+)(=(?<t>[A-Z]+))?(,?\s+(?<d>[^-\s]\S*))?$/
27
27
 
28
28
  # spec -w,? --w+
29
- SHORT_LONG = /^[-](?<s>\w),?\s+[-][-](?<k>\w+)$/
29
+ SHORT_LONG = /^-(?<s>\w),?\s+--(?<k>\w+)$/
30
30
  SHORT_LONG_DEFAULT =
31
- /^[-](?<s>\w),?\s+[-][-](?<k>\w+)(=(?<t>[A-Z]+))?,?\s+(?<d>\S*)$/
31
+ /^-(?<s>\w),?\s+--(?<k>\w+)(=(?<t>[A-Z]+))?,?\s+(?<d>\S*)$/
32
32
 
33
33
  # spec W+ /~/
34
34
  TYPE_DEF = /^(?<t>[A-Z]+),?\s+\/(?<r>\S+)\/$/
@@ -73,15 +73,16 @@ module HelpParser
73
73
  NOT_FLOATS = 'Not all Floats'
74
74
  NOT_INTEGER = 'Not an Integer'
75
75
  NOT_INTEGERS = 'Not all Integers'
76
+ NOT_EXIST = 'Does not exist'
76
77
  # error messages, full:
77
78
  NO_MATCH = 'Software Error: NoMatch was not caught by HelpParser.'
78
79
  MATCH_USAGE = 'Please match usage.'
79
80
  EXTRANEOUS_SPACES = 'Extraneous spaces in help.'
80
81
 
81
82
  # lambda utilities
82
- MSG = lambda{|msg,*keys| "#{msg}: #{keys.join(' ')}"}
83
- F2K = lambda{|f| f[1]=='-' ? f[2..((f.index('=')||0)-1)] : f[1]}
84
- REDTTY = lambda{|msg,out=$stderr|
83
+ MSG = ->(msg,*keys){"#{msg}: #{keys.join(' ')}"}
84
+ F2K = ->(f){f[1]=='-' ? f[2..((f.index('=')||0)-1)] : f[1]}
85
+ REDTTY = lambda do |msg,out=$stderr|
85
86
  out.tty? ? out.puts("\033[0;31m#{msg}\033[0m"): out.puts(msg)
86
- }
87
+ end
87
88
  end
@@ -1,6 +1,8 @@
1
1
  module HelpParser
2
2
  class HelpParserException < Exception
3
- def _init; @code = 1; end
3
+ def _init
4
+ @code = 1
5
+ end
4
6
 
5
7
  # Must give message
6
8
  def initialize(message)
@@ -9,35 +11,45 @@ module HelpParser
9
11
  end
10
12
 
11
13
  def exit
12
- if @code > 0
13
- REDTTY[self.message]
14
+ if @code.positive?
15
+ REDTTY[message]
14
16
  else
15
- $stdout.puts self.message
17
+ $stdout.puts message
16
18
  end
17
19
  Kernel.exit @code
18
20
  end
19
21
  end
20
22
 
21
23
  class VersionException < HelpParserException
22
- def _init; @code = 0; end
24
+ def _init
25
+ @code = 0
26
+ end
23
27
  end
24
28
 
25
29
  class HelpException < HelpParserException
26
- def _init; @code = 0; end
30
+ def _init
31
+ @code = 0
32
+ end
27
33
  end
28
34
 
29
35
  class UsageError < HelpParserException
30
- def _init; @code = EX_USAGE; end
36
+ def _init
37
+ @code = EX_USAGE
38
+ end
31
39
  end
32
40
 
33
41
  class SoftwareError < HelpParserException
34
42
  # Stuff that should not happen
35
- def _init; @code = EX_SOFTWARE; end
43
+ def _init
44
+ @code = EX_SOFTWARE
45
+ end
36
46
  end
37
47
 
38
48
  class NoMatch < HelpParserException
39
49
  # used to short-circuit out
40
- def _init; @code = EX_SOFTWARE; end
50
+ def _init
51
+ @code = EX_SOFTWARE
52
+ end
41
53
 
42
54
  # Forces it's own message
43
55
  def initialize
@@ -46,6 +58,8 @@ module HelpParser
46
58
  end
47
59
 
48
60
  class HelpError < HelpParserException
49
- def _init; @code = EX_CONFIG; end
61
+ def _init
62
+ @code = EX_CONFIG
63
+ end
50
64
  end
51
65
  end
@@ -3,14 +3,14 @@ module HelpParser
3
3
  def self.k2t(specs)
4
4
  k2t = NoDupHash.new
5
5
  # If specs section is not a RESERVED section, it's an options list.
6
- tokens = specs.select{|k,v| k==USAGE or not RESERVED.include?(k)}
6
+ tokens = specs.select{|k,_| k==USAGE or !RESERVED.include?(k)}
7
7
  # Tokens associating a key to a type.
8
8
  .values.flatten.select{|v|v.include?('=')}
9
9
  tokens.each do |token|
10
- if match = VARIABLE.match(token) || LONG.match(token)
10
+ if (match = VARIABLE.match(token) || LONG.match(token))
11
11
  name, type = match[:k], match[:t]
12
- if _=k2t[name]
13
- raise HelpError, MSG[INCONSISTENT,name,type,_] unless type==_
12
+ if (_=k2t[name])
13
+ raise HelpError, MSG[INCONSISTENT,name,type,_] unless type==_
14
14
  else
15
15
  k2t[name] = type
16
16
  end
@@ -19,12 +19,12 @@ module HelpParser
19
19
  raise SoftwareError, MSG[UNEXPECTED,token]
20
20
  end
21
21
  end
22
- return k2t
22
+ k2t
23
23
  end
24
24
 
25
25
  # t2r is an acronym for "type to regexp"
26
26
  def self.t2r(specs)
27
- if types = specs[TYPES]
27
+ if (types=specs[TYPES])
28
28
  t2r = NoDupHash.new
29
29
  types.each do |pair|
30
30
  type, pattern = *pair
@@ -36,6 +36,6 @@ module HelpParser
36
36
  end
37
37
  return t2r
38
38
  end
39
- return nil
39
+ nil
40
40
  end
41
41
  end
@@ -1,183 +1,145 @@
1
1
  module HelpParser
2
2
  def self.string(*names)
3
3
  names.each do |name|
4
- code = <<-CODE
5
- class Options
6
- def #{name}
7
- s = @hash['#{name}']
8
- raise UsageError, MSG[NOT_STRING,'#{name}'] unless s.is_a?(String)
9
- return s
10
- end
11
- end
12
- CODE
13
- eval code
4
+ Options.instance_eval do
5
+ define_method(name) do
6
+ s = @hash[name.to_s]
7
+ raise UsageError, MSG[NOT_STRING,name] unless s.is_a?(String)
8
+ s
9
+ end
10
+ end
14
11
  end
15
12
  end
16
13
 
17
14
  def self.string?(*names)
18
15
  names.each do |name|
19
- code = <<-CODE
20
- class Options
21
- def #{name}?
22
- s = @hash['#{name}']
23
- raise UsageError, MSG[NOT_STRING,'#{name}'] unless s.nil? ||
24
- s.is_a?(String)
25
- return s
26
- end
27
- end
28
- CODE
29
- eval code
16
+ Options.instance_eval do
17
+ define_method("#{name}?") do
18
+ s = @hash[name.to_s]
19
+ raise UsageError,MSG[NOT_STRING,name] unless s.nil? || s.is_a?(String)
20
+ s
21
+ end
22
+ end
30
23
  end
31
24
  end
32
25
 
33
26
  def self.strings(*names)
34
27
  names.each do |name|
35
- code = <<-CODE
36
- class Options
37
- def #{name}
38
- a = @hash['#{name}']
39
- raise UsageError, MSG[NOT_STRINGS,'#{name}'] unless a.is_a?(Array)
40
- return a
41
- end
42
- end
43
- CODE
44
- eval code
28
+ Options.instance_eval do
29
+ define_method(name) do
30
+ a = @hash[name.to_s]
31
+ raise UsageError, MSG[NOT_STRINGS,name] unless a.is_a?(Array)
32
+ a
33
+ end
34
+ end
45
35
  end
46
36
  end
47
37
 
48
38
  def self.strings?(*names)
49
39
  names.each do |name|
50
- code = <<-CODE
51
- class Options
52
- def #{name}?
53
- a = @hash['#{name}']
54
- raise UsageError, MSG[NOT_STRINGS,'#{name}'] unless a.nil? ||
55
- a.is_a?(Array)
56
- return a
57
- end
58
- end
59
- CODE
60
- eval code
40
+ Options.instance_eval do
41
+ define_method("#{name}?") do
42
+ a = @hash[name.to_s]
43
+ raise UsageError,MSG[NOT_STRINGS,name] unless a.nil? || a.is_a?(Array)
44
+ a
45
+ end
46
+ end
61
47
  end
62
48
  end
63
49
 
64
50
  def self.float(*names)
65
51
  names.each do |name|
66
- code = <<-CODE
67
- class Options
68
- def #{name}
69
- @hash['#{name}']&.to_f or raise
70
- rescue
71
- raise UsageError, MSG[NOT_FLOAT,'#{name}']
72
- end
73
- end
74
- CODE
75
- eval code
52
+ Options.instance_eval do
53
+ define_method(name) do
54
+ @hash[name.to_s]&.to_f or raise
55
+ rescue
56
+ raise UsageError, MSG[NOT_FLOAT,name]
57
+ end
58
+ end
76
59
  end
77
60
  end
78
61
 
79
62
  def self.float?(*names)
80
63
  names.each do |name|
81
- code = <<-CODE
82
- class Options
83
- def #{name}?
84
- @hash['#{name}']&.to_f
85
- rescue
86
- raise UsageError, MSG[NOT_FLOAT,'#{name}']
87
- end
88
- end
89
- CODE
90
- eval code
64
+ Options.instance_eval do
65
+ define_method("#{name}?") do
66
+ @hash[name.to_s]&.to_f
67
+ rescue
68
+ raise UsageError, MSG[NOT_FLOAT,name]
69
+ end
70
+ end
91
71
  end
92
72
  end
93
73
 
94
74
  def self.floats(*names)
95
75
  names.each do |name|
96
- code = <<-CODE
97
- class Options
98
- def #{name}
99
- @hash['#{name}'].map{_1.to_f}
100
- rescue
101
- raise UsageError, MSG[#{NOT_FLOATS},'#{name}']
102
- end
103
- end
104
- CODE
105
- eval code
76
+ Options.instance_eval do
77
+ define_method(name) do
78
+ @hash[name.to_s].map(&:to_f)
79
+ rescue
80
+ raise UsageError, MSG[NOT_FLOATS,name]
81
+ end
82
+ end
106
83
  end
107
84
  end
108
85
 
109
86
  def self.floats?(*names)
110
87
  names.each do |name|
111
- code = <<-CODE
112
- class Options
113
- def #{name}?
114
- @hash['#{name}']&.map{_1.to_f}
115
- rescue
116
- raise UsageError, MSG[NOT_FLOATS,'#{name}']
117
- end
118
- end
119
- CODE
120
- eval code
88
+ Options.instance_eval do
89
+ define_method("#{name}?") do
90
+ @hash[name.to_s]&.map(&:to_f)
91
+ rescue
92
+ raise UsageError, MSG[NOT_FLOATS,name]
93
+ end
94
+ end
121
95
  end
122
96
  end
123
97
 
124
98
  def self.int(*names)
125
99
  names.each do |name|
126
- code = <<-CODE
127
- class Options
128
- def #{name}
129
- @hash['#{name}']&.to_i or raise
130
- rescue
131
- raise UsageError, MSG[NOT_INTEGER,'#{name}']
132
- end
133
- end
134
- CODE
135
- eval code
100
+ Options.instance_eval do
101
+ define_method(name) do
102
+ @hash[name.to_s]&.to_i or raise
103
+ rescue
104
+ raise UsageError, MSG[NOT_INTEGER,name]
105
+ end
106
+ end
136
107
  end
137
108
  end
138
109
 
139
110
  def self.int?(*names)
140
111
  names.each do |name|
141
- code = <<-CODE
142
- class Options
143
- def #{name}?
144
- @hash['#{name}']&.to_i
145
- rescue
146
- raise UsageError, MSG[NOT_INTEGER,'#{name}']
147
- end
148
- end
149
- CODE
150
- eval code
112
+ Options.instance_eval do
113
+ define_method("#{name}?") do
114
+ @hash[name.to_s]&.to_i
115
+ rescue
116
+ raise UsageError, MSG[NOT_INTEGER,name]
117
+ end
118
+ end
151
119
  end
152
120
  end
153
121
 
154
122
  def self.ints(*names)
155
123
  names.each do |name|
156
- code = <<-CODE
157
- class Options
158
- def #{name}
159
- @hash['#{name}'].map{_1.to_i}
160
- rescue
161
- raise UsageError, MSG[NOT_INTEGERS,'#{name}']
162
- end
163
- end
164
- CODE
165
- eval code
124
+ Options.instance_eval do
125
+ define_method(name) do
126
+ @hash[name.to_s].map(&:to_i)
127
+ rescue
128
+ raise UsageError, MSG[NOT_INTEGERS,name]
129
+ end
130
+ end
166
131
  end
167
132
  end
168
133
 
169
134
  def self.ints?(*names)
170
135
  names.each do |name|
171
- code = <<-CODE
172
- class Options
173
- def #{name}?
174
- @hash['#{name}']&.map{_1.to_i}
175
- rescue
176
- raise UsageError, MSG[NOT_INTEGERS,'#{name}']
177
- end
178
- end
179
- CODE
180
- eval code
136
+ Options.instance_eval do
137
+ define_method("#{name}?") do
138
+ @hash[name.to_s]&.map(&:to_i)
139
+ rescue
140
+ raise UsageError, MSG[NOT_INTEGERS,name]
141
+ end
142
+ end
181
143
  end
182
144
  end
183
145
  end
@@ -2,34 +2,35 @@ module HelpParser
2
2
  class Options
3
3
  def initialize(version, help, argv)
4
4
  @hash = HelpParser.parsea(argv)
5
- if version && VSN.any?{@hash.has_key? _1}
5
+ if version && VSN.any?{@hash.key? _1}
6
6
  # -v or --version
7
- raise VersionException, version
7
+ raise VersionException, String(version)
8
8
  end
9
9
  if help
10
+ help = String(help)
10
11
  if HLP.any?{@hash.key? _1}
11
- HelpParser.parseh(help, validate: true) if HLP.all?{@hash.key? _1}
12
+ HelpParser.parseh(help, validate: true) if HLP.all?{@hash.key? _1}
12
13
  raise HelpException, help
13
14
  end
14
15
  specs = HelpParser.parseh(help)
15
16
  Completion.new(@hash, specs)
16
- if exclusive=specs[EXCLUSIVE]
17
+ if (exclusive=specs[EXCLUSIVE])
17
18
  exclusive.each do |x|
18
19
  count = x.count{@hash.key? _1}
19
20
  raise HelpParser::UsageError, MSG[EXCLUSIVE_KEYS,*x] if count > 1
20
21
  end
21
22
  end
22
- if inclusive=specs[INCLUSIVE]
23
+ if (inclusive=specs[INCLUSIVE])
23
24
  inclusive.each do |i|
24
25
  count = i.count{@hash.key? _1}
25
- unless count==0 or count==i.length
26
+ unless count.zero? || count==i.length
26
27
  raise HelpParser::UsageError, MSG[INCLUSIVE_KEYS,*i]
27
28
  end
28
29
  end
29
30
  end
30
- if conditional=specs[CONDITIONAL]
31
+ if (conditional=specs[CONDITIONAL])
31
32
  conditional.each do |c|
32
- if @hash.key? c[0] and not c.all?{@hash.key? _1}
33
+ if @hash.key?(c[0]) && !c.all?{@hash.key? _1}
33
34
  raise HelpParser::UsageError, MSG[CONDITIONAL_KEYS,*c]
34
35
  end
35
36
  end
@@ -47,17 +48,16 @@ module HelpParser
47
48
  @hash[k]
48
49
  end
49
50
 
50
- def method_missing(mthd, *args, &block)
51
- super if block or args.length > 0
52
- m = mthd.to_s
53
- case m[-1]
54
- when '?'
55
- @hash.key? m[0..-2]
56
- when '!'
57
- super
58
- else
59
- @hash[m]
51
+ def respond_to_missing?(m, include_all=false)
52
+ m[-1]=='!' ? super : true
53
+ end
54
+
55
+ def method_missing(m, *args, &block)
56
+ super unless respond_to_missing?(m)
57
+ unless args.empty? && block.nil?
58
+ raise ArgumentError, 'expected neither args nor block'
60
59
  end
60
+ m[-1]=='?' ? @hash.key?(m[0..-2].to_s) : @hash[m.to_s]
61
61
  end
62
62
  end
63
63
  end
@@ -7,7 +7,7 @@ module HelpParser
7
7
  break if a.size==1 # '-' quits argv processing
8
8
  if a[1]=='-'
9
9
  break if a.size==2 # '--' also quits argv processing
10
- s = a[2..-1]
10
+ s = a[2..]
11
11
  if s.include?('=')
12
12
  k,v = s.split('=',2)
13
13
  hsh[k] = v
@@ -15,7 +15,7 @@ module HelpParser
15
15
  hsh[s] = true
16
16
  end
17
17
  else
18
- a.chars[1..-1].each do |c|
18
+ a.chars[1..].each do |c|
19
19
  hsh[c] = true
20
20
  end
21
21
  end
@@ -24,6 +24,6 @@ module HelpParser
24
24
  n += 1
25
25
  end
26
26
  end
27
- return hsh
27
+ hsh
28
28
  end
29
29
  end
@@ -4,15 +4,15 @@ module HelpParser
4
4
  help.each_line do |line|
5
5
  line.chomp!
6
6
  next if line==''
7
- if md = SECTION_NAME.match(line)
7
+ if (md=SECTION_NAME.match(line))
8
8
  name = md[:name].downcase
9
9
  specs[name] = []
10
10
  else
11
11
  next if name==''
12
12
  break if line[0]=='#'
13
- next if !(line[0]==' ')
13
+ next unless line[0]==' '
14
14
  spec = (index=line.rindex("\t"))? line[0,index].strip : line.strip
15
- raise HelpError, EXTRANEOUS_SPACES if validate and spec==''
15
+ raise HelpError, EXTRANEOUS_SPACES if validate && spec.empty?
16
16
  case name
17
17
  when USAGE
18
18
  Validate.balanced_brackets(spec.chars) if validate
@@ -20,29 +20,31 @@ module HelpParser
20
20
  Validate.usage_tokens(tokens) if validate
21
21
  specs[USAGE].push tokens
22
22
  when TYPES
23
- if validate and not spec=~TYPE_DEF
23
+ if validate && !TYPE_DEF.match?(spec)
24
24
  raise HelpError, MSG[UNRECOGNIZED_TYPE,spec]
25
25
  end
26
26
  specs[TYPES].push spec.split(CSV)
27
27
  when *FLAG_CLUMPS # EXCLUSIVE,INCLUSIVE,CONDITIONAL,...
28
- if validate and not spec=~X_DEF
28
+ if validate && !X_DEF.match?(spec)
29
29
  raise HelpError, MSG[UNRECOGNIZED_X,spec]
30
30
  end
31
31
  specs[name].push spec.split(CSV)
32
32
  else
33
- raise HelpError, MSG[UNRECOGNIZED_OPTION,spec] if validate and
34
- not [SHORT, LONG, SHORT_LONG, SHORT_LONG_DEFAULT].any?{_1=~spec}
33
+ if validate &&
34
+ [SHORT, LONG, SHORT_LONG, SHORT_LONG_DEFAULT].none?{_1=~spec}
35
+ raise HelpError, MSG[UNRECOGNIZED_OPTION,spec]
36
+ end
35
37
  specs[name].push spec.split(CSV)
36
38
  end
37
39
  end
38
40
  end
39
41
  if validate
40
42
  Validate.usage_specs(specs)
41
- if t2r = HelpParser.t2r(specs)
43
+ if (t2r=HelpParser.t2r(specs))
42
44
  k2t = HelpParser.k2t(specs)
43
45
  Validate.k2t2r(specs, k2t, t2r)
44
46
  end
45
47
  end
46
- return specs
48
+ specs
47
49
  end
48
50
  end
@@ -5,7 +5,7 @@ module HelpParser
5
5
  # Tokens := Array(Token|Tokens)
6
6
  def self.parseu(chars)
7
7
  tokens,token = [],''
8
- while c = chars.shift
8
+ while (c=chars.shift)
9
9
  case c
10
10
  when ' ','[',']'
11
11
  unless token==''
@@ -19,6 +19,6 @@ module HelpParser
19
19
  end
20
20
  end
21
21
  tokens.push(token) unless token==''
22
- return tokens
22
+ tokens
23
23
  end
24
24
  end
@@ -3,14 +3,10 @@ module Validate
3
3
  def self.balanced_brackets(chars)
4
4
  count = 0
5
5
  chars.each do |c|
6
- if c=='['
7
- count += 1
8
- elsif c==']'
9
- count -= 1
10
- end
11
- break if count<0
6
+ c=='[' && (count+=1) or c==']' && (count-=1)
7
+ break if count.negative?
12
8
  end
13
- raise HelpError, MSG[UNBALANCED,chars.join] unless count==0
9
+ raise HelpError, MSG[UNBALANCED,chars.join] unless count.zero?
14
10
  end
15
11
 
16
12
  def self.usage_tokens(tokens)
@@ -18,7 +14,7 @@ module Validate
18
14
  tokens.flatten.each do |token|
19
15
  raise HelpError, MSG[UNRECOGNIZED_TOKEN,token] unless
20
16
  [FLAG,LITERAL,VARIABLE,FLAG_GROUP]
21
- .detect{_=token.match(_1) and words.push(_[:k])}
17
+ .detect{(_=token.match _1) && words.push(_[:k])}
22
18
  end
23
19
  words.each_with_index do |word,i|
24
20
  raise HelpError, MSG[DUP_WORD,word] unless i==words.rindex(word)
@@ -26,40 +22,37 @@ module Validate
26
22
  end
27
23
 
28
24
  def self.usage_specs(specs)
29
- flags = specs.select{|a,b| not RESERVED.include? a}.values.flatten
30
- .select{|f|f[0]=='-'}.map{|f| F2K[f]}
25
+ flags = specs.except(*RESERVED).values.flatten
26
+ .select{_1[0]=='-'}.map{F2K[_1]}
31
27
  FLAG_CLUMPS.each do |k|
32
- if a=specs[k]
33
- seen = {}
34
- a.each do |xs|
35
- k = xs.sort.join(' ').to_sym
36
- if seen[k] or not xs.length==xs.uniq.length
37
- raise HelpError, MSG[DUP_X,k]
38
- end
39
- seen[k] = true
40
- xs.each do |x|
41
- raise HelpError, MSG[UNSEEN_FLAG, x] unless flags.include?(x)
42
- end
28
+ next unless (a=specs[k])
29
+ seen = {}
30
+ a.each do |xs|
31
+ k = xs.sort.join(' ').to_sym
32
+ if seen[k] || xs.length!=xs.uniq.length
33
+ raise HelpError, MSG[DUP_X,k]
34
+ end
35
+ seen[k] = true
36
+ xs.each do |x|
37
+ raise HelpError, MSG[UNSEEN_FLAG, x] unless flags.include?(x)
43
38
  end
44
39
  end
45
40
  end
46
41
  flags.each_with_index do |flag,i|
47
42
  raise HelpError, MSG[DUP_FLAG,flag] unless i==flags.rindex(flag)
48
- end
43
+ end
49
44
  group = []
50
45
  specs_usage = specs[USAGE]
51
- unless specs_usage.nil?
52
- specs_usage.flatten.each do |token|
53
- if match = token.match(FLAG_GROUP)
54
- key = match[:k]
55
- raise HelpError, MSG[UNDEFINED_SECTION,key] unless specs[key]
56
- group.push(key)
57
- end
46
+ specs_usage&.flatten&.each do |token|
47
+ if (match=token.match FLAG_GROUP)
48
+ key = match[:k]
49
+ raise HelpError, MSG[UNDEFINED_SECTION,key] unless specs[key]
50
+ group.push(key)
58
51
  end
59
52
  end
60
53
  specs.each do |key,tokens|
61
- raise HelpError, MSG[MISSING_CASES,key] unless tokens.size>0
62
- next if specs_usage.nil? or RESERVED.include? key
54
+ raise HelpError, MSG[MISSING_CASES,key] if tokens.empty?
55
+ next if specs_usage.nil? || RESERVED.include?(key)
63
56
  raise HelpError, MSG[MISSING_USAGE,key] unless group.include?(key)
64
57
  end
65
58
  end
@@ -67,7 +60,7 @@ module Validate
67
60
  def self.k2t2r(specs, k2t, t2r)
68
61
  a,b = k2t.values.uniq.sort,t2r.keys.sort
69
62
  unless a==b
70
- c = (a+b).uniq.select{|x|!(a.include?(x) && b.include?(x))}
63
+ c = (a+b).uniq.reject{|x|a.include?(x) && b.include?(x)}
71
64
  raise HelpError, MSG[UNCOMPLETED_TYPES,c.join(',')]
72
65
  end
73
66
  specs.each do |section,tokens|
@@ -80,7 +73,7 @@ module Validate
80
73
  i = long_type.index('=')
81
74
  next if i.nil?
82
75
  long = long_type[2..(i-1)]
83
- type = long_type[(i+1)..-1]
76
+ type = long_type[(i+1)..]
84
77
  regex = t2r[type]
85
78
  unless regex=~default
86
79
  raise HelpError, MSG[BAD_DEFAULT,long,default,type,regex.inspect]
data/lib/help_parser.rb CHANGED
@@ -10,7 +10,7 @@ require_relative 'help_parser/options'
10
10
  require_relative 'help_parser/macros'
11
11
 
12
12
  module HelpParser
13
- VERSION = '8.1.221206'
13
+ VERSION = '8.2.230210'
14
14
  autoload :Validate, 'help_parser/validate'
15
15
 
16
16
  def self.[](
@@ -18,10 +18,10 @@ module HelpParser
18
18
  help = nil,
19
19
  argv = [File.basename($0)]+ARGV)
20
20
  Options.new(version, help, argv)
21
- rescue HelpParserException => exception
22
- exception.exit
21
+ rescue HelpParserException => e
22
+ e.exit
23
23
  end
24
24
  end
25
25
 
26
26
  # Requires:
27
- #`ruby`
27
+ # `ruby`
metadata CHANGED
@@ -1,22 +1,81 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: help_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.221206
4
+ version: 8.2.230210
5
5
  platform: ruby
6
6
  authors:
7
7
  - CarlosJHR64
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-06 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.8.1
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.8.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: parser
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.2.0
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.2.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: test-unit
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.5'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.5.7
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.5'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.5.7
13
73
  description: "Welcome to Help Parser! \nDo you have your help text? \nLet's parse!\n"
14
74
  email: carlosjhr64@gmail.com
15
75
  executables: []
16
76
  extensions: []
17
77
  extra_rdoc_files: []
18
78
  files:
19
- - LICENSE
20
79
  - README.md
21
80
  - lib/help_parser.rb
22
81
  - lib/help_parser/aliases.rb
@@ -49,8 +108,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
108
  - !ruby/object:Gem::Version
50
109
  version: '0'
51
110
  requirements:
52
- - 'ruby: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [aarch64-linux]'
53
- rubygems_version: 3.3.7
111
+ - 'git: 2.30'
112
+ rubygems_version: 3.4.6
54
113
  signing_key:
55
114
  specification_version: 4
56
115
  summary: Welcome to Help Parser! Do you have your help text? Let's parse!
data/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2017 carlosjhr64
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.