help_parser 6.4.1 → 8.0.210917

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: 5de4ecf5cd21b847dbc1a490db6a2efdee61aa9119fb6777f3e97d079100c6d0
4
- data.tar.gz: bfad9916f32a6a135fe15c6b88c632495aece7977690cec7c1a1de0268e48be9
3
+ metadata.gz: 89d031ef15e33460fc4f23ccec23cc98f01cb9808fd77bb478c63be6a638f034
4
+ data.tar.gz: 9521262caa0b0a1617fc52bdeec42c4e305a4fc4ce34c5871128c64eecf5aae7
5
5
  SHA512:
6
- metadata.gz: 7d6f037aba6739da35f14f9353d4a76a4f1f0ea7b0434f3f384b5d315b9d34eac9929091a6b7af3a5c44bcfe83e0adc66746da106ca8118c86cf6026d2734a1e
7
- data.tar.gz: 15d9a0683093fc50229984dac9624cacfc513014734a6e062c99b428ece46a108c02f3069ad33afacc6a5c1f4c71e335cb7939d748428b22922d0d50954963f3
6
+ metadata.gz: 4e6c0faa99fd04e8b8e2f289b0f1894538747defaeb557400b36904f7c330961b9cc068aa8bdbe06493f8339af19cd4397cfdca9e1f82bc20ddbf84b91553955
7
+ data.tar.gz: 135b86c92d72faa5b49cdfedd7b6c66a9e568e592ae5b8afc86c612efa23020c828acb45693435d5f5349679f61a963bac81041da6d6bdae9549c1ab2de3214b
data/README.md CHANGED
@@ -1,78 +1,130 @@
1
- # Help Parser VI: Tweeker
1
+ # Help Parser VIII: Helpland
2
2
 
3
- * [github](https://www.github.com/carlosjhr64/Ruby-HelpParser)
3
+ * [VERSION 8.0.210917](https://github.com/carlosjhr64/help_parser/releases)
4
+ * [github](https://www.github.com/carlosjhr64/help_parser)
4
5
  * [rubygems](https://rubygems.org/gems/help_parser)
5
6
 
6
7
  ## DESCRIPTION:
7
- Welcome to the best Help Parser of all!
8
- Tweeker!
9
- Which do you find most helpful?
10
- Hard?
11
- I prefer easy.
12
8
 
13
- ## SYNOPSIS:
14
-
15
- require "pp"
16
- require "help_parser"
17
-
18
- HELP = <<-HELP
19
- # <= Hash here, parser skips
20
- # The Awesome Command.
21
- Usage:
22
- awesome [:options+] <args>+
23
- awesome :alternate <arg=NAME>
24
- Options:
25
- -v --version \t Give version and quit
26
- -h --help \t Give help and quit
27
- -s --long \t Short long synonyms
28
- --name=NAME \t Typed
29
- --number 5 \t Defaulted
30
- --value=FLOAT 1.23 \t Typed and Defaulted
31
- -a --all=YN y \t Short, long, typed, and defaulted
32
- Alternate:
33
- -V \t Just short
34
- Types:
35
- NAME /^[A-Z][a-z]+$/
36
- FLOAT /^\\d+\\.\\d+$/
37
- YN /^[YNyn]$/
38
- Exclusive:
39
- version help \t Tells parser these are exclusive keys
40
- # <= Hash here, parser breaks out
41
- # Notes #
42
- Blah blah blah
43
- HELP
44
-
45
- VERSION = "6.4.1"
46
-
47
- # Macros:
48
- HelpParser.string(name) # for options.name : String
49
- HelpParser.strings(args) # for options.args : Array(String)
50
- HelpParser.float(value) # for options.value : Float
51
- HelpParser.int?(number) # for options.number? : Int32 | Nil
52
-
53
- HelpParser.run(VERSION, HELP) do |options|
54
- hash = options._hash
55
- pp hash # to inspect the hash
56
-
57
- pp options.name if hash["name"]?
58
- pp options.args if hash["args"]?
59
- pp options.value if hash["value"]?
60
- pp options.number?
61
- end
62
-
63
- Well, what do you think?
64
- PERFECT!
65
-
66
- ## New for 6.4.0:
67
-
68
- * Automates $VERBOSE=true on --verbose
69
- * Reports typos you may have on options usage
70
-
71
- ## New for 6.1.0:
72
-
73
- Running your `awesome` command with the `--help` flag will also check your help text for errors,
74
- on top of giving the help text. Otherwise, the parser no longer checks for help text errors.
9
+ Welcome to Help Parser!
10
+ Do you have your help text?
11
+ Let's parse!
75
12
 
76
13
  ## INSTALL:
77
14
 
78
- $ sudo gem install help_parser
15
+ ```console
16
+ $ gem install help_parser
17
+ ```
18
+
19
+ ## SYNOPSIS:
20
+ <!-- The following PREVIEW has been approved for ALL PROGRAMMERS by CarlosJHR64.
21
+ For the README validator that checks against me lying....
22
+ ```ruby
23
+ unless File.basename($PROGRAM_NAME) == 'party'
24
+ # For example's sake say
25
+ $PROGRAM_NAME = 'party'
26
+ # and ARGV is
27
+ ARGV.concat ["-\-age", "-\-date=2020-09-07", 'touch', 'that']
28
+ # and proceed as if run as:
29
+ # awesome -\-name=Doe -\-value a b c
30
+ end
31
+ ```
32
+ The following gem has been rated
33
+ | M | Mature |
34
+ -->
35
+
36
+ ```ruby
37
+ require "help_parser"
38
+
39
+ HELP = <<-HELP
40
+ # <= Hash here, parser skips
41
+ # HelpParser: Party command example #
42
+ Usage:
43
+ party :options+ [<args>+]
44
+ party [:alternate] <arg=FLOAT>
45
+ party literal <arg1=WORD> <arg2=WORD>
46
+ Options:
47
+ -v --version \t Give version and quit
48
+ -h --help \t Give help and quit
49
+ -s --long \t Short long synonyms
50
+ --touch that \t Defaulted
51
+ --date=DATE \t Typed
52
+ --age=INTEGER 80 \t Typed and Defaulted
53
+ -a --all=YN y \t Short, long, typed, and defaulted
54
+ --to_be
55
+ --not_to_be
56
+ --rain
57
+ --water
58
+ --wet
59
+ Exclusive:
60
+ to_be not_to_be \t Tells parser these are mutually exclusive keys
61
+ Inclusive:
62
+ date age \t Tells parser any of these must include all of these
63
+ Conditional:
64
+ rain water wet \t Tells parser if first then all
65
+ Alternate:
66
+ --invoke
67
+ --wut
68
+ Types:
69
+ WORD /^[A-Za-z]+$/
70
+ DATE /^\\d\\d\\d\\d-\\d\\d-\\d\\d$/
71
+ INTEGER /^\\d+$/
72
+ FLOAT /^\\d+\\.\\d+$/
73
+ YN /^[YNyn]$/
74
+ # <= Hash here, parser breaks out
75
+ # Notes #
76
+ I wouldn't touch that!
77
+ HELP
78
+
79
+ VERSION = "1.2.3"
80
+
81
+ OPTIONS = HelpParser[VERSION, HELP] #~> HelpParser
82
+
83
+ # Macros:
84
+ HelpParser.strings?(:args) # for OPTIONS.args : Array(String) | Nil
85
+ HelpParser.int?(:age) # for OPTIONS.age? : Integer | Nil
86
+ HelpParser.float(:arg) # for options.arg : Float
87
+ HelpParser.string(:arg1, :arg2, :arg3) # for OPTIONS.arg1, etc : String
88
+ #=> [:arg1, :arg2, :arg3]
89
+
90
+ ## If run as:
91
+ ## party --age --date=2020-09-07 touch that
92
+ OPTIONS.age? #=> 80
93
+ OPTIONS.age?.class #=> Integer
94
+ OPTIONS.args? #=> ["touch", "that"]
95
+ OPTIONS.args?.class #=> Array
96
+ OPTIONS.arg? and OPTIONS.arg #=> false
97
+ OPTIONS.arg?.class #=> FalseClass
98
+ ```
99
+
100
+ ## Features
101
+
102
+ * `$DEBUG=true` on --debug
103
+ * `$VERBOSE=true` on --verbose
104
+ * -h and --help simultaneously will check help string for errors
105
+ * `HelpParser::REDTTY[msg]` will red color output `msg` to `STDERR`.
106
+
107
+ ## LICENSE:
108
+
109
+ (The MIT License)
110
+
111
+ Copyright (c) 2021 CarlosJHR64
112
+
113
+ Permission is hereby granted, free of charge, to any person obtaining
114
+ a copy of this software and associated documentation files (the
115
+ 'Software'), to deal in the Software without restriction, including
116
+ without limitation the rights to use, copy, modify, merge, publish,
117
+ distribute, sublicense, and/or sell copies of the Software, and to
118
+ permit persons to whom the Software is furnished to do so, subject to
119
+ the following conditions:
120
+
121
+ The above copyright notice and this permission notice shall be
122
+ included in all copies or substantial portions of the Software.
123
+
124
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
125
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
126
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
127
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
128
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
129
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
130
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -3,29 +3,34 @@ module HelpParser
3
3
  def initialize(hash, specs)
4
4
  @hash,@specs = hash,specs
5
5
  @cache = NoDupHash.new
6
- usage if @specs.has_key?(USAGE)
6
+ usage or diagnose if @specs.has_key?(USAGE)
7
7
  pad
8
- types
8
+ types if @specs.has_key?(TYPES)
9
9
  end
10
10
 
11
+ # Which usage does the user's command options match?
11
12
  def usage
12
13
  @specs[USAGE].each do |cmd|
13
14
  begin
14
15
  i = matches(cmd)
15
16
  raise NoMatch unless @hash.size==i
16
17
  @cache.each{|k,v|@hash[k]=v} # Variables
17
- return
18
+ return true # Good! Found matching usage.
18
19
  rescue NoMatch
19
20
  next
20
21
  ensure
21
22
  @cache.clear
22
23
  end
23
24
  end
25
+ return false # Bad! Did not match any of the expected usage.
26
+ end
24
27
 
28
+ # Diagnose user's usage.
29
+ def diagnose
25
30
  dict = {}
26
31
  @specs.each do |k,v|
27
- next if [USAGE,TYPES,EXCLUSIVE].include? k
28
- v.flatten.map{|_|_.scan(/\w+/).first}.each{|_|dict[_]=true}
32
+ next if RESERVED.include? k
33
+ v.flatten.map{_1.scan(/\w+/).first}.each{dict[_1]=true}
29
34
  end
30
35
  typos = @hash.keys.select{|k|k.is_a? String and not dict[k]}
31
36
  raise UsageError, MSG[UNRECOGNIZED, typos] unless typos.empty?
@@ -34,22 +39,25 @@ module HelpParser
34
39
  end
35
40
 
36
41
  def types
37
- if t2r = HelpParser.t2r(@specs)
38
- k2t = HelpParser.k2t(@specs)
39
- @hash.each do |key,value|
40
- next unless key.is_a?(String)
41
- if type = k2t[key]
42
- regex = t2r[type]
43
- case value
44
- when String
45
- raise UsageError, "--#{key}=#{value} !~ #{type}=#{regex.inspect}" unless value=~regex
46
- when Array
47
- value.each do |string|
48
- raise UsageError, "--#{key}=#{string} !~ #{type}=#{regex.inspect}" unless string=~regex
42
+ t2r,k2t = HelpParser.t2r(@specs),HelpParser.k2t(@specs)
43
+ @hash.each do |key,value|
44
+ next unless key.is_a?(String)
45
+ if type = k2t[key]
46
+ regex = t2r[type]
47
+ case value
48
+ when String
49
+ unless value=~regex
50
+ raise UsageError, "--#{key}=#{value} !~ #{type}=#{regex.inspect}"
51
+ end
52
+ when Array
53
+ value.each do |string|
54
+ unless string=~regex
55
+ raise UsageError,
56
+ "--#{key}=#{string} !~ #{type}=#{regex.inspect}"
49
57
  end
50
- else
51
- raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
52
58
  end
59
+ else
60
+ raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
53
61
  end
54
62
  end
55
63
  end
@@ -74,7 +82,7 @@ module HelpParser
74
82
  elsif value = @hash[long]
75
83
  @hash[short] = true
76
84
  if value==true && !default.nil?
77
- @hash.delete(long)
85
+ @hash.delete(long) # ArgvHash reset
78
86
  @hash[long]=default
79
87
  end
80
88
  end
@@ -83,7 +91,7 @@ module HelpParser
83
91
  long,default = first[2..(i-1)],second
84
92
  value = @hash[long]
85
93
  if value==true
86
- @hash.delete(long)
94
+ @hash.delete(long) # ArgvHash reset
87
95
  @hash[long] = default
88
96
  end
89
97
  end
@@ -103,7 +111,7 @@ module HelpParser
103
111
  end
104
112
  next
105
113
  elsif m=FLAG_GROUP.match(token)
106
- group,plus = m['k'],m['p']
114
+ group,plus = m[:k],m[:p]
107
115
  key = keys[i]
108
116
  raise NoMatch if key.nil? || key.is_a?(Integer)
109
117
  list = @specs[group].flatten.select{|f|f[0]=='-'}.map{|f| F2K[f]}
@@ -118,7 +126,7 @@ module HelpParser
118
126
  elsif m=VARIABLE.match(token)
119
127
  key = keys[i]
120
128
  raise NoMatch unless key.is_a?(Integer)
121
- variable,plus = m['k'],m['p']
129
+ variable,plus = m[:k],m[:p]
122
130
  if plus.nil?
123
131
  @cache[variable] = @hash[key]
124
132
  else
@@ -1,15 +1,19 @@
1
1
  module HelpParser
2
- @@validate = false
3
- def self.validate!
4
- @@validate = true
5
- end
6
- def self.validate?
7
- @@validate
8
- end
2
+ V,VSN = 'v','version'
3
+ H,HLP = 'h','help'
4
+ VRBS,DBG = 'verbose','debug'
9
5
 
6
+ # reserved name
10
7
  USAGE = 'usage'
11
8
  TYPES = 'types'
12
9
  EXCLUSIVE = 'exclusive'
10
+ INCLUSIVE = 'inclusive'
11
+ CONDITIONAL = 'conditional'
12
+ FLAG_CLUMPS = [EXCLUSIVE,INCLUSIVE,CONDITIONAL]
13
+ RESERVED = [USAGE,TYPES,EXCLUSIVE,INCLUSIVE,CONDITIONAL]
14
+
15
+ # sections
16
+ SECTION_NAME = /^[A-Z]\w+:$/
13
17
 
14
18
  # usage
15
19
  FLAG = /^[-][-]?(?<k>\w+)$/
@@ -23,13 +27,14 @@ module HelpParser
23
27
 
24
28
  # spec -w,? --w+
25
29
  SHORT_LONG = /^[-](?<s>\w),?\s+[-][-](?<k>\w+)$/
26
- SHORT_LONG_DEFAULT = /^[-](?<s>\w),?\s+[-][-](?<k>\w+)(=(?<t>[A-Z]+))?,?\s+(?<d>[^-\s]\S*)$/
30
+ SHORT_LONG_DEFAULT =
31
+ /^[-](?<s>\w),?\s+[-][-](?<k>\w+)(=(?<t>[A-Z]+))?,?\s+(?<d>[^-\s]\S*)$/
27
32
 
28
33
  # spec W+ /~/
29
34
  TYPE_DEF = /^(?<t>[A-Z]+),?\s+\/(?<r>\S+)\/$/
30
35
 
31
36
  # spec w+( w+)+
32
- X_DEF = /^\w+( +\w+)+$/
37
+ X_DEF = /^\w+( +\w+)+$/ # for both exclusive and inclusive specs
33
38
 
34
39
  CSV = /,?\s+/
35
40
 
@@ -42,17 +47,19 @@ module HelpParser
42
47
  DUP_KEY = 'Duplicate key'
43
48
  DUP_WORD = 'Duplicate word'
44
49
  DUP_FLAG = 'Duplicate flag'
45
- DUP_X = 'Duplicate exclusive spec'
50
+ DUP_X = 'Duplicate exclusive/inclusive spec'
46
51
  UNSEEN_FLAG = 'Undefined flag'
47
52
  INCONSISTENT = 'Inconsistent use of variable'
48
53
  UNEXPECTED = 'Unexpected string in help text'
49
54
  BAD_REGEX = 'Bad regex'
50
55
  REDUNDANT = 'Redundant'
51
56
  EXCLUSIVE_KEYS = 'Exclusive keys'
57
+ INCLUSIVE_KEYS = 'Inclusive keys'
58
+ CONDITIONAL_KEYS = 'Conditional keys'
52
59
  UNBALANCED = 'Unbalanced brackets'
53
60
  UNRECOGNIZED_TOKEN = 'Unrecognized usage token'
54
61
  UNRECOGNIZED_TYPE = 'Unrecognized type spec'
55
- UNRECOGNIZED_X = 'Unrecognized exclusive spec'
62
+ UNRECOGNIZED_X = 'Unrecognized exclusive/inclusive spec'
56
63
  UNRECOGNIZED_OPTION = 'Unrecognized option spec'
57
64
  UNRECOGNIZED = 'Unrecognized'
58
65
  UNDEFINED_SECTION = 'Section not defined'
@@ -72,7 +79,9 @@ module HelpParser
72
79
  EXTRANEOUS_SPACES = 'Extraneous spaces in help.'
73
80
 
74
81
  # lambda utilities
75
- MSG = lambda{|msg,*keys| "\033[0;31m#{msg}: #{keys.join(' ')}\033[0m"}
82
+ MSG = lambda{|msg,*keys| "#{msg}: #{keys.join(' ')}"}
76
83
  F2K = lambda{|f| f[1]=='-' ? f[2..((f.index('=')||0)-1)] : f[1]}
77
- RESERVED = lambda{|k| [USAGE,TYPES,EXCLUSIVE].include?(k)} # reserved
84
+ REDTTY = lambda{|msg,out=$stderr|
85
+ out.tty? ? out.puts("\033[0;31m#{msg}\033[0m"): out.puts(msg)
86
+ }
78
87
  end
@@ -10,9 +10,9 @@ module HelpParser
10
10
 
11
11
  def exit
12
12
  if @code > 0
13
- STDERR.puts self.message
13
+ REDTTY[self.message]
14
14
  else
15
- puts self.message
15
+ $stdout.puts self.message
16
16
  end
17
17
  Kernel.exit @code
18
18
  end
@@ -36,10 +36,10 @@ module HelpParser
36
36
  end
37
37
 
38
38
  class NoMatch < HelpParserException
39
- # used to shortcircuit out
39
+ # used to short-circuit out
40
40
  def _init; @code = EX_SOFTWARE; end
41
41
 
42
- # Forces it's owm message
42
+ # Forces it's own message
43
43
  def initialize
44
44
  super(NO_MATCH)
45
45
  end
@@ -1,12 +1,16 @@
1
1
  module HelpParser
2
2
  def self.k2t(specs)
3
3
  k2t = NoDupHash.new
4
- tokens = specs.select{|k,v| !(k==TYPES)}.values.flatten.select{|v|v.include?('=')}
4
+ tokens = specs.select{|k,v| !(k==TYPES)}.values.flatten
5
+ .select{|v|v.include?('=')}
5
6
  tokens.each do |token|
6
7
  if match = VARIABLE.match(token) || LONG.match(token)
7
- name, type = match['k'], match['t']
8
- k2t[name] = type if !k2t.has_key?(name)
9
- raise HelpError, MSG[INCONSISTENT,name,type,k2t[name]] if !(type==k2t[name])
8
+ name, type = match[:k], match[:t]
9
+ if _=k2t[name]
10
+ raise HelpError, MSG[INCONSISTENT,name,type,_] unless type==_
11
+ else
12
+ k2t[name] = type
13
+ end
10
14
  else
11
15
  # Expected these to be caught earlier...
12
16
  raise SoftwareError, MSG[UNEXPECTED,token]
@@ -20,7 +20,8 @@ module HelpParser
20
20
  class Options
21
21
  def #{name}?
22
22
  s = @hash['#{name}']
23
- raise UsageError, MSG[NOT_STRING,'#{name}'] unless s.nil? || s.is_a?(String)
23
+ raise UsageError, MSG[NOT_STRING,'#{name}'] unless s.nil? ||
24
+ s.is_a?(String)
24
25
  return s
25
26
  end
26
27
  end
@@ -50,7 +51,8 @@ module HelpParser
50
51
  class Options
51
52
  def #{name}?
52
53
  a = @hash['#{name}']
53
- raise UsageError, MSG[NOT_STRINGS,'#{name}'] unless a.nil? || a.is_a?(Array)
54
+ raise UsageError, MSG[NOT_STRINGS,'#{name}'] unless a.nil? ||
55
+ a.is_a?(Array)
54
56
  return a
55
57
  end
56
58
  end
@@ -100,7 +102,7 @@ module HelpParser
100
102
  def #{name}
101
103
  f = @hash['#{name}']
102
104
  raise unless f.is_a?(Array)
103
- f.map{|_|_.to_f}
105
+ f.map{_1.to_f}
104
106
  rescue
105
107
  raise UsageError, MSG[#{NOT_FLOATS},'#{name}']
106
108
  end
@@ -118,7 +120,7 @@ module HelpParser
118
120
  f = @hash['#{name}']
119
121
  return nil unless f
120
122
  raise unless f.is_a?(Array)
121
- f.map{|_|_.to_f}
123
+ f.map{_1.to_f}
122
124
  rescue
123
125
  raise UsageError, MSG[NOT_FLOATS,'#{name}']
124
126
  end
@@ -169,7 +171,7 @@ module HelpParser
169
171
  def #{name}
170
172
  f = @hash['#{name}']
171
173
  raise unless f.is_a?(Array)
172
- f.map{|_|_.to_i}
174
+ f.map{_1.to_i}
173
175
  rescue
174
176
  raise UsageError, MSG[NOT_INTEGERS,'#{name}']
175
177
  end
@@ -187,7 +189,7 @@ module HelpParser
187
189
  f = @hash['#{name}']
188
190
  return nil unless f
189
191
  raise unless f.is_a?(Array)
190
- f.map{|_|_.to_i}
192
+ f.map{_1.to_i}
191
193
  rescue
192
194
  raise UsageError, MSG[NOT_INTEGERS,'#{name}']
193
195
  end
@@ -2,31 +2,45 @@ module HelpParser
2
2
  class Options
3
3
  def initialize(version, help, argv)
4
4
  @hash = HelpParser.parsea(argv)
5
- if version && (@hash.has_key?('v') || @hash.has_key?('version'))
5
+ if version && (@hash.has_key?(V) || @hash.has_key?(VSN))
6
6
  # -v or --version
7
7
  raise VersionException, version
8
8
  end
9
9
  if help
10
- # -h or --help
11
- if @hash.has_key?('h') || _=@hash.has_key?('help')
12
- begin
13
- # validates help
14
- HelpParser.parseh(help, true)
15
- rescue HelpError
16
- $stderr.puts $!
17
- end if _
10
+ h = [H, HLP]
11
+ if h.any?{@hash.key? _1}
12
+ HelpParser.parseh(help, validate: true) if h.all?{@hash.key? _1}
18
13
  raise HelpException, help
19
14
  end
20
- specs = HelpParser.parseh(help, HelpParser.validate?)
15
+ specs = HelpParser.parseh(help)
21
16
  Completion.new(@hash, specs)
22
17
  if exclusive=specs[EXCLUSIVE]
23
- exclusive.each{|xs| raise HelpParser::UsageError, MSG[EXCLUSIVE_KEYS,*xs] if @hash.keys.count{|k|xs.include?(k)}>1}
18
+ exclusive.each do |x|
19
+ count = x.count{@hash.key? _1}
20
+ raise HelpParser::UsageError, MSG[EXCLUSIVE_KEYS,*x] if count > 1
21
+ end
22
+ end
23
+ if inclusive=specs[INCLUSIVE]
24
+ inclusive.each do |i|
25
+ count = i.count{@hash.key? _1}
26
+ unless count==0 or count==i.length
27
+ raise HelpParser::UsageError, MSG[INCLUSIVE_KEYS,*i]
28
+ end
29
+ end
30
+ end
31
+ if conditional=specs[CONDITIONAL]
32
+ conditional.each do |c|
33
+ if @hash.key? c[0] and not c.all?{@hash.key? _1}
34
+ raise HelpParser::UsageError, MSG[CONDITIONAL_KEYS,*c]
35
+ end
36
+ end
24
37
  end
25
38
  end
26
- $VERBOSE = true if @hash['verbose']==true
39
+ $VERBOSE = true if @hash[VRBS]==true
40
+ $DEBUG = true if @hash[DBG]==true
27
41
  end
28
42
 
29
- def _hash
43
+ def to_h
30
44
  @hash
31
45
  end
32
46
 
@@ -1,10 +1,10 @@
1
1
  module HelpParser
2
- def self.parseh(help, validate=true)
2
+ def self.parseh(help, validate: false)
3
3
  specs,name = NoDupHash.new,''
4
4
  help.each_line do |line|
5
5
  line.chomp!
6
6
  next if line==''
7
- if line=~/^[A-Z]\w+:$/
7
+ if line=~SECTION_NAME
8
8
  name = line[0..-2].downcase
9
9
  specs[name] = []
10
10
  else
@@ -15,29 +15,32 @@ module HelpParser
15
15
  raise HelpError, EXTRANEOUS_SPACES if validate and spec==''
16
16
  case name
17
17
  when USAGE
18
- HelpParser.validate_line_chars(spec.chars) if validate
18
+ Validate.line_chars(spec.chars) if validate
19
19
  tokens = HelpParser.parseu(spec.chars)
20
- HelpParser.validate_usage_tokens(tokens) if validate
21
- specs[name].push tokens
20
+ Validate.usage_tokens(tokens) if validate
21
+ specs[USAGE].push tokens
22
22
  when TYPES
23
- raise HelpError, MSG[UNRECOGNIZED_TYPE,spec] if validate and not spec=~TYPE_DEF
24
- specs[name].push spec.split(CSV)
25
- when EXCLUSIVE
26
- raise HelpError, MSG[UNRECOGNIZED_X,spec] if validate and not spec=~X_DEF
23
+ if validate and not spec=~TYPE_DEF
24
+ raise HelpError, MSG[UNRECOGNIZED_TYPE,spec]
25
+ end
26
+ specs[TYPES].push spec.split(CSV)
27
+ when *FLAG_CLUMPS # EXCLUSIVE,INCLUSIVE,CONDITIONAL,...
28
+ if validate and not spec=~X_DEF
29
+ raise HelpError, MSG[UNRECOGNIZED_X,spec]
30
+ end
27
31
  specs[name].push spec.split(CSV)
28
32
  else
29
- if validate and not [SHORT, LONG, SHORT_LONG, SHORT_LONG_DEFAULT].any?{|_|_=~spec}
30
- raise HelpError, MSG[UNRECOGNIZED_OPTION,spec]
31
- end
33
+ raise HelpError, MSG[UNRECOGNIZED_OPTION,spec] if validate and
34
+ not [SHORT, LONG, SHORT_LONG, SHORT_LONG_DEFAULT].any?{_1=~spec}
32
35
  specs[name].push spec.split(CSV)
33
36
  end
34
37
  end
35
38
  end
36
39
  if validate
37
- HelpParser.validate_usage_specs(specs)
40
+ Validate.usage_specs(specs)
38
41
  if t2r = HelpParser.t2r(specs)
39
42
  k2t = HelpParser.k2t(specs)
40
- HelpParser.validate_k2t2r(specs, k2t, t2r)
43
+ Validate.k2t2r(specs, k2t, t2r)
41
44
  end
42
45
  end
43
46
  return specs
@@ -1,5 +1,6 @@
1
1
  module HelpParser
2
- def self.validate_line_chars(chars)
2
+ module Validate
3
+ def self.line_chars(chars)
3
4
  count = 0
4
5
  chars.each do |c|
5
6
  if c=='['
@@ -12,7 +13,7 @@ module HelpParser
12
13
  raise HelpError, MSG[UNBALANCED,chars.join] unless count==0
13
14
  end
14
15
 
15
- def self.validate_usage_tokens(tokens)
16
+ def self.usage_tokens(tokens)
16
17
  words = []
17
18
  tokens.flatten.each do |token|
18
19
  match = token.match(FLAG) ||
@@ -20,24 +21,28 @@ module HelpParser
20
21
  token.match(VARIABLE) ||
21
22
  token.match(FLAG_GROUP)
22
23
  raise HelpError, MSG[UNRECOGNIZED_TOKEN,token] unless match
23
- words.push match['k'] # key
24
+ words.push match[:k] # key
24
25
  end
25
26
  words.each_with_index do |word,i|
26
27
  raise HelpError, MSG[DUP_WORD,word] unless i==words.rindex(word)
27
28
  end
28
29
  end
29
30
 
30
- def self.validate_usage_specs(specs)
31
- option_specs = specs.select{|a,b| !RESERVED[a]}
31
+ def self.usage_specs(specs)
32
+ option_specs = specs.select{|a,b| not RESERVED.include? a}
32
33
  flags = option_specs.values.flatten.select{|f|f[0]=='-'}.map{|f| F2K[f]}
33
- if exclusive=specs[EXCLUSIVE]
34
- seen = {}
35
- exclusive.each do |xs|
36
- k = xs.sort.join(' ').to_sym
37
- raise HelpError, MSG[DUP_X,k] if seen[k]
38
- seen[k] = true
39
- xs.each do |x|
40
- raise HelpError, MSG[UNSEEN_FLAG, x] unless flags.include?(x)
34
+ FLAG_CLUMPS.each do |k|
35
+ if a=specs[k]
36
+ seen = {}
37
+ a.each do |xs|
38
+ k = xs.sort.join(' ').to_sym
39
+ if seen[k] or not xs.length==xs.uniq.length
40
+ raise HelpError, MSG[DUP_X,k]
41
+ end
42
+ seen[k] = true
43
+ xs.each do |x|
44
+ raise HelpError, MSG[UNSEEN_FLAG, x] unless flags.include?(x)
45
+ end
41
46
  end
42
47
  end
43
48
  end
@@ -49,7 +54,7 @@ module HelpParser
49
54
  unless specs_usage.nil?
50
55
  specs_usage.flatten.each do |token|
51
56
  if match = token.match(FLAG_GROUP)
52
- key = match['k']
57
+ key = match[:k]
53
58
  raise HelpError, MSG[UNDEFINED_SECTION,key] unless specs[key]
54
59
  group.push(key)
55
60
  end
@@ -57,12 +62,12 @@ module HelpParser
57
62
  end
58
63
  specs.each do |key,tokens|
59
64
  raise HelpError, MSG[MISSING_CASES,key] unless tokens.size>0
60
- next if specs_usage.nil? or RESERVED[key]
65
+ next if specs_usage.nil? or RESERVED.include? key
61
66
  raise HelpError, MSG[MISSING_USAGE,key] unless group.include?(key)
62
67
  end
63
68
  end
64
69
 
65
- def self.validate_k2t2r(specs, k2t, t2r)
70
+ def self.k2t2r(specs, k2t, t2r)
66
71
  a,b = k2t.values.uniq.sort,t2r.keys.sort
67
72
  unless a==b
68
73
  c = (a+b).uniq.select{|x|!(a.include?(x) && b.include?(x))}
@@ -80,8 +85,11 @@ module HelpParser
80
85
  long = long_type[2..(i-1)]
81
86
  type = long_type[(i+1)..-1]
82
87
  regex = t2r[type]
83
- raise HelpError, MSG[BAD_DEFAULT,long,default,type,regex.inspect] unless regex=~default
88
+ unless regex=~default
89
+ raise HelpError, MSG[BAD_DEFAULT,long,default,type,regex.inspect]
90
+ end
84
91
  end
85
92
  end
86
93
  end
87
94
  end
95
+ end
data/lib/help_parser.rb CHANGED
@@ -1,17 +1,17 @@
1
- require_relative './help_parser/constants'
2
- require_relative './help_parser/exceptions'
3
- require_relative './help_parser/aliases'
4
- require_relative './help_parser/parsea'
5
- require_relative './help_parser/validations'
6
- require_relative './help_parser/parseu'
7
- require_relative './help_parser/parseh'
8
- require_relative './help_parser/k2t2r'
9
- require_relative './help_parser/completion'
10
- require_relative './help_parser/options'
11
- require_relative './help_parser/macros'
1
+ require_relative 'help_parser/constants'
2
+ require_relative 'help_parser/exceptions'
3
+ require_relative 'help_parser/aliases'
4
+ require_relative 'help_parser/parsea'
5
+ require_relative 'help_parser/parseu'
6
+ require_relative 'help_parser/parseh'
7
+ require_relative 'help_parser/k2t2r'
8
+ require_relative 'help_parser/completion'
9
+ require_relative 'help_parser/options'
10
+ require_relative 'help_parser/macros'
12
11
 
13
12
  module HelpParser
14
- VERSION = '6.4.1'
13
+ VERSION = '8.0.210917'
14
+ autoload :Validate, 'help_parser/validate'
15
15
 
16
16
  def self.[](
17
17
  version = nil,
@@ -21,16 +21,6 @@ module HelpParser
21
21
  rescue HelpParserException => exception
22
22
  exception.exit
23
23
  end
24
-
25
- def self.run(
26
- version = nil,
27
- help = nil,
28
- argv = [File.basename($0)]+ARGV)
29
- options = Options.new(version, help, argv)
30
- yield options
31
- rescue HelpParserException => exception
32
- exception.exit
33
- end
34
24
  end
35
25
 
36
26
  # Requires:
metadata CHANGED
@@ -1,21 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: help_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.4.1
4
+ version: 8.0.210917
5
5
  platform: ruby
6
6
  authors:
7
- - carlosjhr64
8
- autorequire:
7
+ - CarlosJHR64
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-09 00:00:00.000000000 Z
11
+ date: 2021-09-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: |
14
- Welcome to the best Help Parser of all!
15
- Tweeker!
16
- Which do you find most helpful?
17
- Hard?
18
- I prefer easy.
13
+ description: "Welcome to Help Parser! \nDo you have your help text? \nLet's parse!\n"
19
14
  email: carlosjhr64@gmail.com
20
15
  executables: []
21
16
  extensions: []
@@ -34,12 +29,12 @@ files:
34
29
  - lib/help_parser/parsea.rb
35
30
  - lib/help_parser/parseh.rb
36
31
  - lib/help_parser/parseu.rb
37
- - lib/help_parser/validations.rb
38
- homepage: https://github.com/carlosjhr64/Ruby-HelpParser
32
+ - lib/help_parser/validate.rb
33
+ homepage: https://github.com/carlosjhr64/help_parser
39
34
  licenses:
40
35
  - MIT
41
36
  metadata: {}
42
- post_install_message:
37
+ post_install_message:
43
38
  rdoc_options: []
44
39
  require_paths:
45
40
  - lib
@@ -54,11 +49,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
49
  - !ruby/object:Gem::Version
55
50
  version: '0'
56
51
  requirements:
57
- - 'ruby: ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]'
58
- rubyforge_project:
59
- rubygems_version: 2.7.7
60
- signing_key:
52
+ - 'ruby: ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]'
53
+ rubygems_version: 3.2.22
54
+ signing_key:
61
55
  specification_version: 4
62
- summary: Welcome to the best Help Parser of all! Tweeker! Which do you find most helpful?
63
- Hard? I prefer easy.
56
+ summary: Welcome to Help Parser! Do you have your help text? Let's parse!
64
57
  test_files: []