help_parser 8.1.221206 → 8.2.230210

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: 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.