help_parser 6.4.1 → 8.0.210917

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: 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: []