help_parser 7.0.200907 → 8.1.221206
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 +4 -4
- data/README.md +35 -32
- data/lib/help_parser/completion.rb +22 -10
- data/lib/help_parser/constants.rb +17 -3
- data/lib/help_parser/k2t2r.rb +7 -2
- data/lib/help_parser/macros.rb +12 -28
- data/lib/help_parser/options.rb +18 -10
- data/lib/help_parser/parseh.rb +15 -12
- data/lib/help_parser/parseu.rb +4 -0
- data/lib/help_parser/{validations.rb → validate.rb} +21 -18
- data/lib/help_parser.rb +12 -22
- metadata +9 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 157ae793a16a5b92ca1633306080465fcd2e9671aaed67dc01fb47cb318f0824
|
|
4
|
+
data.tar.gz: cc72ed9f03c94ef2f5455897807a49ba69e79786ceae5daa3d158d3265e9a931
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aea35622e25f8fd0cf84cc3115ce15b524440e698f516ebbd89188fa56d30c098dcc8711d61cee4b07aa7b77f935091222c2b0ff71465480d0e9cf76530810f5
|
|
7
|
+
data.tar.gz: 88a2613d9487be0b11e0da90bef805abc5fc1a7ca0012a97b32d5aa62540f382cc91e38b6714e4279bdba319475b323126625b4cf092e037742f30ba1c4ee22a
|
data/README.md
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
# Help Parser
|
|
1
|
+
# Help Parser VIII: Helpland
|
|
2
2
|
|
|
3
|
-
* [VERSION
|
|
4
|
-
* [github](https://www.github.com/carlosjhr64/
|
|
3
|
+
* [VERSION 8.1.221206](https://github.com/carlosjhr64/help_parser/releases)
|
|
4
|
+
* [github](https://www.github.com/carlosjhr64/help_parser)
|
|
5
5
|
* [rubygems](https://rubygems.org/gems/help_parser)
|
|
6
6
|
|
|
7
7
|
## DESCRIPTION:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
Welcome to Help Parser!
|
|
10
|
+
Do you have your help text?
|
|
11
|
+
Let's parse!
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
## INSTALL:
|
|
14
|
+
|
|
15
|
+
```console
|
|
16
|
+
$ gem install help_parser
|
|
17
|
+
```
|
|
13
18
|
|
|
14
19
|
## SYNOPSIS:
|
|
15
20
|
<!-- The following PREVIEW has been approved for ALL PROGRAMMERS by CarlosJHR64.
|
|
16
21
|
For the README validator that checks against me lying....
|
|
17
22
|
```ruby
|
|
18
|
-
unless File.basename($PROGRAM_NAME) == '
|
|
23
|
+
unless File.basename($PROGRAM_NAME) == 'party'
|
|
19
24
|
# For example's sake say
|
|
20
|
-
$PROGRAM_NAME = '
|
|
25
|
+
$PROGRAM_NAME = 'party'
|
|
21
26
|
# and ARGV is
|
|
22
|
-
ARGV.concat ["-\-age", "-\-date=2020-09-07", '
|
|
27
|
+
ARGV.concat ["-\-age", "-\-date=2020-09-07", 'touch', 'that']
|
|
23
28
|
# and proceed as if run as:
|
|
24
29
|
# awesome -\-name=Doe -\-value a b c
|
|
25
30
|
end
|
|
@@ -28,34 +33,35 @@ The following gem has been rated
|
|
|
28
33
|
| M | Mature |
|
|
29
34
|
-->
|
|
30
35
|
|
|
31
|
-
> Who ever you are, you were meant to find me today...
|
|
32
|
-
> there is no turning back!
|
|
33
|
-
> Above all, don't invoke the command!
|
|
34
|
-
|
|
35
36
|
```ruby
|
|
36
37
|
require "help_parser"
|
|
37
38
|
|
|
38
39
|
HELP = <<-HELP
|
|
39
40
|
# <= Hash here, parser skips
|
|
40
|
-
# HelpParser:
|
|
41
|
+
# HelpParser: Party command example #
|
|
41
42
|
Usage:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
party :options+ [<args>+]
|
|
44
|
+
party [:alternate] <arg=FLOAT>
|
|
45
|
+
party literal <arg1=WORD> <arg2=WORD>
|
|
45
46
|
Options:
|
|
46
47
|
-v --version \t Give version and quit
|
|
47
48
|
-h --help \t Give help and quit
|
|
48
49
|
-s --long \t Short long synonyms
|
|
49
|
-
--
|
|
50
|
+
--touch that \t Defaulted
|
|
50
51
|
--date=DATE \t Typed
|
|
51
52
|
--age=INTEGER 80 \t Typed and Defaulted
|
|
52
53
|
-a --all=YN y \t Short, long, typed, and defaulted
|
|
53
54
|
--to_be
|
|
54
55
|
--not_to_be
|
|
56
|
+
--rain
|
|
57
|
+
--water
|
|
58
|
+
--wet
|
|
55
59
|
Exclusive:
|
|
56
60
|
to_be not_to_be \t Tells parser these are mutually exclusive keys
|
|
57
61
|
Inclusive:
|
|
58
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
|
|
59
65
|
Alternate:
|
|
60
66
|
--invoke
|
|
61
67
|
--wut
|
|
@@ -67,7 +73,7 @@ Types:
|
|
|
67
73
|
YN /^[YNyn]$/
|
|
68
74
|
# <= Hash here, parser breaks out
|
|
69
75
|
# Notes #
|
|
70
|
-
|
|
76
|
+
I wouldn't touch that!
|
|
71
77
|
HELP
|
|
72
78
|
|
|
73
79
|
VERSION = "1.2.3"
|
|
@@ -82,30 +88,27 @@ HelpParser.string(:arg1, :arg2, :arg3) # for OPTIONS.arg1, etc : String
|
|
|
82
88
|
#=> [:arg1, :arg2, :arg3]
|
|
83
89
|
|
|
84
90
|
## If run as:
|
|
85
|
-
##
|
|
86
|
-
OPTIONS.age
|
|
87
|
-
OPTIONS.
|
|
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
|
|
88
96
|
OPTIONS.arg? and OPTIONS.arg #=> false
|
|
97
|
+
OPTIONS.arg?.class #=> FalseClass
|
|
89
98
|
```
|
|
90
99
|
|
|
91
|
-
YOU HAVE INVOKED THE COMMAND...
|
|
92
|
-
YOUR HELP BELONGS TO ME!!!
|
|
93
|
-
|
|
94
100
|
## Features
|
|
95
101
|
|
|
96
|
-
*
|
|
97
|
-
*
|
|
102
|
+
* `$DEBUG=true` on --debug
|
|
103
|
+
* `$VERBOSE=true` on --verbose
|
|
98
104
|
* -h and --help simultaneously will check help string for errors
|
|
99
|
-
|
|
100
|
-
## INSTALL:
|
|
101
|
-
|
|
102
|
-
$ sudo gem install help_parser
|
|
105
|
+
* `HelpParser::REDTTY[msg]` will red color output `msg` to `$stderr`.
|
|
103
106
|
|
|
104
107
|
## LICENSE:
|
|
105
108
|
|
|
106
109
|
(The MIT License)
|
|
107
110
|
|
|
108
|
-
Copyright (c)
|
|
111
|
+
Copyright (c) 2022 CarlosJHR64
|
|
109
112
|
|
|
110
113
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
111
114
|
a copy of this software and associated documentation files (the
|
|
@@ -28,9 +28,14 @@ module HelpParser
|
|
|
28
28
|
# Diagnose user's usage.
|
|
29
29
|
def diagnose
|
|
30
30
|
dict = {}
|
|
31
|
-
@specs.each do |
|
|
32
|
-
next if RESERVED
|
|
33
|
-
|
|
31
|
+
@specs.each do |section,list|
|
|
32
|
+
next if RESERVED.include? section
|
|
33
|
+
list.flatten.select{_1[0]=='-'}.each do |key_type|
|
|
34
|
+
key_type.scan(/\w+/) do |key|
|
|
35
|
+
dict[key]=true
|
|
36
|
+
break
|
|
37
|
+
end
|
|
38
|
+
end
|
|
34
39
|
end
|
|
35
40
|
typos = @hash.keys.select{|k|k.is_a? String and not dict[k]}
|
|
36
41
|
raise UsageError, MSG[UNRECOGNIZED, typos] unless typos.empty?
|
|
@@ -46,10 +51,15 @@ module HelpParser
|
|
|
46
51
|
regex = t2r[type]
|
|
47
52
|
case value
|
|
48
53
|
when String
|
|
49
|
-
|
|
54
|
+
unless value=~regex
|
|
55
|
+
raise UsageError, "--#{key}=#{value} !~ #{type}=#{regex.inspect}"
|
|
56
|
+
end
|
|
50
57
|
when Array
|
|
51
58
|
value.each do |string|
|
|
52
|
-
|
|
59
|
+
unless string=~regex
|
|
60
|
+
raise UsageError,
|
|
61
|
+
"--#{key}=#{string} !~ #{type}=#{regex.inspect}"
|
|
62
|
+
end
|
|
53
63
|
end
|
|
54
64
|
else
|
|
55
65
|
raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
|
|
@@ -61,7 +71,7 @@ module HelpParser
|
|
|
61
71
|
def pad
|
|
62
72
|
# Synonyms and defaults:
|
|
63
73
|
@specs.each do |section,options|
|
|
64
|
-
next if section==
|
|
74
|
+
next if RESERVED.any?{section==_1}
|
|
65
75
|
options.each do |words|
|
|
66
76
|
next unless words.size>1
|
|
67
77
|
first,second,default = words[0],words[1],words[2]
|
|
@@ -90,6 +100,8 @@ module HelpParser
|
|
|
90
100
|
@hash[long] = default
|
|
91
101
|
end
|
|
92
102
|
end
|
|
103
|
+
else
|
|
104
|
+
raise SoftwareError, MSG[UNEXPECTED, words]
|
|
93
105
|
end
|
|
94
106
|
end
|
|
95
107
|
end
|
|
@@ -106,22 +118,22 @@ module HelpParser
|
|
|
106
118
|
end
|
|
107
119
|
next
|
|
108
120
|
elsif m=FLAG_GROUP.match(token)
|
|
109
|
-
group,plus = m[
|
|
121
|
+
group,plus = m[:k],m[:p]
|
|
110
122
|
key = keys[i]
|
|
111
|
-
raise NoMatch
|
|
123
|
+
raise NoMatch unless key.is_a? String
|
|
112
124
|
list = @specs[group].flatten.select{|f|f[0]=='-'}.map{|f| F2K[f]}
|
|
113
125
|
raise NoMatch unless list.include?(key)
|
|
114
126
|
unless plus.nil?
|
|
115
127
|
loop do
|
|
116
128
|
key = keys[i+1]
|
|
117
|
-
break
|
|
129
|
+
break unless key.is_a?(String) and list.include?(key)
|
|
118
130
|
i+=1
|
|
119
131
|
end
|
|
120
132
|
end
|
|
121
133
|
elsif m=VARIABLE.match(token)
|
|
122
134
|
key = keys[i]
|
|
123
135
|
raise NoMatch unless key.is_a?(Integer)
|
|
124
|
-
variable,plus = m[
|
|
136
|
+
variable,plus = m[:k],m[:p]
|
|
125
137
|
if plus.nil?
|
|
126
138
|
@cache[variable] = @hash[key]
|
|
127
139
|
else
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
module HelpParser
|
|
2
|
+
VSN = ['v','version']
|
|
3
|
+
HLP = ['h','help']
|
|
4
|
+
VRBS,DBG = 'verbose','debug'
|
|
5
|
+
|
|
6
|
+
# reserved name
|
|
2
7
|
USAGE = 'usage'
|
|
3
8
|
TYPES = 'types'
|
|
4
9
|
EXCLUSIVE = 'exclusive'
|
|
5
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 = /^(?<name>[A-Z]\w+):$/
|
|
6
17
|
|
|
7
18
|
# usage
|
|
8
19
|
FLAG = /^[-][-]?(?<k>\w+)$/
|
|
@@ -16,7 +27,8 @@ module HelpParser
|
|
|
16
27
|
|
|
17
28
|
# spec -w,? --w+
|
|
18
29
|
SHORT_LONG = /^[-](?<s>\w),?\s+[-][-](?<k>\w+)$/
|
|
19
|
-
SHORT_LONG_DEFAULT =
|
|
30
|
+
SHORT_LONG_DEFAULT =
|
|
31
|
+
/^[-](?<s>\w),?\s+[-][-](?<k>\w+)(=(?<t>[A-Z]+))?,?\s+(?<d>\S*)$/
|
|
20
32
|
|
|
21
33
|
# spec W+ /~/
|
|
22
34
|
TYPE_DEF = /^(?<t>[A-Z]+),?\s+\/(?<r>\S+)\/$/
|
|
@@ -43,6 +55,7 @@ module HelpParser
|
|
|
43
55
|
REDUNDANT = 'Redundant'
|
|
44
56
|
EXCLUSIVE_KEYS = 'Exclusive keys'
|
|
45
57
|
INCLUSIVE_KEYS = 'Inclusive keys'
|
|
58
|
+
CONDITIONAL_KEYS = 'Conditional keys'
|
|
46
59
|
UNBALANCED = 'Unbalanced brackets'
|
|
47
60
|
UNRECOGNIZED_TOKEN = 'Unrecognized usage token'
|
|
48
61
|
UNRECOGNIZED_TYPE = 'Unrecognized type spec'
|
|
@@ -68,6 +81,7 @@ module HelpParser
|
|
|
68
81
|
# lambda utilities
|
|
69
82
|
MSG = lambda{|msg,*keys| "#{msg}: #{keys.join(' ')}"}
|
|
70
83
|
F2K = lambda{|f| f[1]=='-' ? f[2..((f.index('=')||0)-1)] : f[1]}
|
|
71
|
-
|
|
72
|
-
|
|
84
|
+
REDTTY = lambda{|msg,out=$stderr|
|
|
85
|
+
out.tty? ? out.puts("\033[0;31m#{msg}\033[0m"): out.puts(msg)
|
|
86
|
+
}
|
|
73
87
|
end
|
data/lib/help_parser/k2t2r.rb
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
module HelpParser
|
|
2
|
+
# k2t is an acronym for the "key to type" mapping
|
|
2
3
|
def self.k2t(specs)
|
|
3
4
|
k2t = NoDupHash.new
|
|
4
|
-
|
|
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)}
|
|
7
|
+
# Tokens associating a key to a type.
|
|
8
|
+
.values.flatten.select{|v|v.include?('=')}
|
|
5
9
|
tokens.each do |token|
|
|
6
10
|
if match = VARIABLE.match(token) || LONG.match(token)
|
|
7
|
-
name, type = match[
|
|
11
|
+
name, type = match[:k], match[:t]
|
|
8
12
|
if _=k2t[name]
|
|
9
13
|
raise HelpError, MSG[INCONSISTENT,name,type,_] unless type==_
|
|
10
14
|
else
|
|
@@ -18,6 +22,7 @@ module HelpParser
|
|
|
18
22
|
return k2t
|
|
19
23
|
end
|
|
20
24
|
|
|
25
|
+
# t2r is an acronym for "type to regexp"
|
|
21
26
|
def self.t2r(specs)
|
|
22
27
|
if types = specs[TYPES]
|
|
23
28
|
t2r = NoDupHash.new
|
data/lib/help_parser/macros.rb
CHANGED
|
@@ -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? ||
|
|
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? ||
|
|
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
|
|
@@ -64,9 +66,7 @@ module HelpParser
|
|
|
64
66
|
code = <<-CODE
|
|
65
67
|
class Options
|
|
66
68
|
def #{name}
|
|
67
|
-
|
|
68
|
-
raise if f.nil?
|
|
69
|
-
f.to_f
|
|
69
|
+
@hash['#{name}']&.to_f or raise
|
|
70
70
|
rescue
|
|
71
71
|
raise UsageError, MSG[NOT_FLOAT,'#{name}']
|
|
72
72
|
end
|
|
@@ -81,9 +81,7 @@ module HelpParser
|
|
|
81
81
|
code = <<-CODE
|
|
82
82
|
class Options
|
|
83
83
|
def #{name}?
|
|
84
|
-
|
|
85
|
-
f = f.to_f if f
|
|
86
|
-
return f
|
|
84
|
+
@hash['#{name}']&.to_f
|
|
87
85
|
rescue
|
|
88
86
|
raise UsageError, MSG[NOT_FLOAT,'#{name}']
|
|
89
87
|
end
|
|
@@ -98,9 +96,7 @@ module HelpParser
|
|
|
98
96
|
code = <<-CODE
|
|
99
97
|
class Options
|
|
100
98
|
def #{name}
|
|
101
|
-
|
|
102
|
-
raise unless f.is_a?(Array)
|
|
103
|
-
f.map{|_|_.to_f}
|
|
99
|
+
@hash['#{name}'].map{_1.to_f}
|
|
104
100
|
rescue
|
|
105
101
|
raise UsageError, MSG[#{NOT_FLOATS},'#{name}']
|
|
106
102
|
end
|
|
@@ -115,10 +111,7 @@ module HelpParser
|
|
|
115
111
|
code = <<-CODE
|
|
116
112
|
class Options
|
|
117
113
|
def #{name}?
|
|
118
|
-
|
|
119
|
-
return nil unless f
|
|
120
|
-
raise unless f.is_a?(Array)
|
|
121
|
-
f.map{|_|_.to_f}
|
|
114
|
+
@hash['#{name}']&.map{_1.to_f}
|
|
122
115
|
rescue
|
|
123
116
|
raise UsageError, MSG[NOT_FLOATS,'#{name}']
|
|
124
117
|
end
|
|
@@ -133,9 +126,7 @@ module HelpParser
|
|
|
133
126
|
code = <<-CODE
|
|
134
127
|
class Options
|
|
135
128
|
def #{name}
|
|
136
|
-
|
|
137
|
-
raise if f.nil?
|
|
138
|
-
f.to_i
|
|
129
|
+
@hash['#{name}']&.to_i or raise
|
|
139
130
|
rescue
|
|
140
131
|
raise UsageError, MSG[NOT_INTEGER,'#{name}']
|
|
141
132
|
end
|
|
@@ -150,9 +141,7 @@ module HelpParser
|
|
|
150
141
|
code = <<-CODE
|
|
151
142
|
class Options
|
|
152
143
|
def #{name}?
|
|
153
|
-
|
|
154
|
-
f = f.to_i if f
|
|
155
|
-
return f
|
|
144
|
+
@hash['#{name}']&.to_i
|
|
156
145
|
rescue
|
|
157
146
|
raise UsageError, MSG[NOT_INTEGER,'#{name}']
|
|
158
147
|
end
|
|
@@ -167,9 +156,7 @@ module HelpParser
|
|
|
167
156
|
code = <<-CODE
|
|
168
157
|
class Options
|
|
169
158
|
def #{name}
|
|
170
|
-
|
|
171
|
-
raise unless f.is_a?(Array)
|
|
172
|
-
f.map{|_|_.to_i}
|
|
159
|
+
@hash['#{name}'].map{_1.to_i}
|
|
173
160
|
rescue
|
|
174
161
|
raise UsageError, MSG[NOT_INTEGERS,'#{name}']
|
|
175
162
|
end
|
|
@@ -184,10 +171,7 @@ module HelpParser
|
|
|
184
171
|
code = <<-CODE
|
|
185
172
|
class Options
|
|
186
173
|
def #{name}?
|
|
187
|
-
|
|
188
|
-
return nil unless f
|
|
189
|
-
raise unless f.is_a?(Array)
|
|
190
|
-
f.map{|_|_.to_i}
|
|
174
|
+
@hash['#{name}']&.map{_1.to_i}
|
|
191
175
|
rescue
|
|
192
176
|
raise UsageError, MSG[NOT_INTEGERS,'#{name}']
|
|
193
177
|
end
|
data/lib/help_parser/options.rb
CHANGED
|
@@ -2,36 +2,44 @@ module HelpParser
|
|
|
2
2
|
class Options
|
|
3
3
|
def initialize(version, help, argv)
|
|
4
4
|
@hash = HelpParser.parsea(argv)
|
|
5
|
-
if version &&
|
|
5
|
+
if version && VSN.any?{@hash.has_key? _1}
|
|
6
6
|
# -v or --version
|
|
7
7
|
raise VersionException, version
|
|
8
8
|
end
|
|
9
9
|
if help
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
HelpParser.parseh(help, validate: true) if h.all?{|_|@hash.key?_}
|
|
10
|
+
if HLP.any?{@hash.key? _1}
|
|
11
|
+
HelpParser.parseh(help, validate: true) if HLP.all?{@hash.key? _1}
|
|
13
12
|
raise HelpException, help
|
|
14
13
|
end
|
|
15
14
|
specs = HelpParser.parseh(help)
|
|
16
15
|
Completion.new(@hash, specs)
|
|
17
16
|
if exclusive=specs[EXCLUSIVE]
|
|
18
17
|
exclusive.each do |x|
|
|
19
|
-
count =
|
|
18
|
+
count = x.count{@hash.key? _1}
|
|
20
19
|
raise HelpParser::UsageError, MSG[EXCLUSIVE_KEYS,*x] if count > 1
|
|
21
20
|
end
|
|
22
21
|
end
|
|
23
22
|
if inclusive=specs[INCLUSIVE]
|
|
24
23
|
inclusive.each do |i|
|
|
25
|
-
count =
|
|
26
|
-
|
|
24
|
+
count = i.count{@hash.key? _1}
|
|
25
|
+
unless count==0 or count==i.length
|
|
26
|
+
raise HelpParser::UsageError, MSG[INCLUSIVE_KEYS,*i]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
if conditional=specs[CONDITIONAL]
|
|
31
|
+
conditional.each do |c|
|
|
32
|
+
if @hash.key? c[0] and not c.all?{@hash.key? _1}
|
|
33
|
+
raise HelpParser::UsageError, MSG[CONDITIONAL_KEYS,*c]
|
|
34
|
+
end
|
|
27
35
|
end
|
|
28
36
|
end
|
|
29
37
|
end
|
|
30
|
-
$VERBOSE = true if @hash[
|
|
31
|
-
$DEBUG = true if @hash[
|
|
38
|
+
$VERBOSE = true if @hash[VRBS]==true
|
|
39
|
+
$DEBUG = true if @hash[DBG]==true
|
|
32
40
|
end
|
|
33
41
|
|
|
34
|
-
def
|
|
42
|
+
def to_h
|
|
35
43
|
@hash
|
|
36
44
|
end
|
|
37
45
|
|
data/lib/help_parser/parseh.rb
CHANGED
|
@@ -4,8 +4,8 @@ module HelpParser
|
|
|
4
4
|
help.each_line do |line|
|
|
5
5
|
line.chomp!
|
|
6
6
|
next if line==''
|
|
7
|
-
if line
|
|
8
|
-
name =
|
|
7
|
+
if md = SECTION_NAME.match(line)
|
|
8
|
+
name = md[:name].downcase
|
|
9
9
|
specs[name] = []
|
|
10
10
|
else
|
|
11
11
|
next if name==''
|
|
@@ -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
|
-
|
|
18
|
+
Validate.balanced_brackets(spec.chars) if validate
|
|
19
19
|
tokens = HelpParser.parseu(spec.chars)
|
|
20
|
-
|
|
20
|
+
Validate.usage_tokens(tokens) if validate
|
|
21
21
|
specs[USAGE].push tokens
|
|
22
22
|
when TYPES
|
|
23
|
-
|
|
23
|
+
if validate and not spec=~TYPE_DEF
|
|
24
|
+
raise HelpError, MSG[UNRECOGNIZED_TYPE,spec]
|
|
25
|
+
end
|
|
24
26
|
specs[TYPES].push spec.split(CSV)
|
|
25
|
-
when EXCLUSIVE,INCLUSIVE
|
|
26
|
-
|
|
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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
40
|
+
Validate.usage_specs(specs)
|
|
38
41
|
if t2r = HelpParser.t2r(specs)
|
|
39
42
|
k2t = HelpParser.k2t(specs)
|
|
40
|
-
|
|
43
|
+
Validate.k2t2r(specs, k2t, t2r)
|
|
41
44
|
end
|
|
42
45
|
end
|
|
43
46
|
return specs
|
data/lib/help_parser/parseu.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module HelpParser
|
|
2
|
-
|
|
2
|
+
module Validate
|
|
3
|
+
def self.balanced_brackets(chars)
|
|
3
4
|
count = 0
|
|
4
5
|
chars.each do |c|
|
|
5
6
|
if c=='['
|
|
@@ -12,30 +13,29 @@ module HelpParser
|
|
|
12
13
|
raise HelpError, MSG[UNBALANCED,chars.join] unless count==0
|
|
13
14
|
end
|
|
14
15
|
|
|
15
|
-
def self.
|
|
16
|
+
def self.usage_tokens(tokens)
|
|
16
17
|
words = []
|
|
17
18
|
tokens.flatten.each do |token|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
token.match(FLAG_GROUP)
|
|
22
|
-
raise HelpError, MSG[UNRECOGNIZED_TOKEN,token] unless match
|
|
23
|
-
words.push match['k'] # key
|
|
19
|
+
raise HelpError, MSG[UNRECOGNIZED_TOKEN,token] unless
|
|
20
|
+
[FLAG,LITERAL,VARIABLE,FLAG_GROUP]
|
|
21
|
+
.detect{_=token.match(_1) and words.push(_[:k])}
|
|
24
22
|
end
|
|
25
23
|
words.each_with_index do |word,i|
|
|
26
24
|
raise HelpError, MSG[DUP_WORD,word] unless i==words.rindex(word)
|
|
27
25
|
end
|
|
28
26
|
end
|
|
29
27
|
|
|
30
|
-
def self.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
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]}
|
|
31
|
+
FLAG_CLUMPS.each do |k|
|
|
34
32
|
if a=specs[k]
|
|
35
33
|
seen = {}
|
|
36
34
|
a.each do |xs|
|
|
37
35
|
k = xs.sort.join(' ').to_sym
|
|
38
|
-
|
|
36
|
+
if seen[k] or not xs.length==xs.uniq.length
|
|
37
|
+
raise HelpError, MSG[DUP_X,k]
|
|
38
|
+
end
|
|
39
39
|
seen[k] = true
|
|
40
40
|
xs.each do |x|
|
|
41
41
|
raise HelpError, MSG[UNSEEN_FLAG, x] unless flags.include?(x)
|
|
@@ -51,7 +51,7 @@ module HelpParser
|
|
|
51
51
|
unless specs_usage.nil?
|
|
52
52
|
specs_usage.flatten.each do |token|
|
|
53
53
|
if match = token.match(FLAG_GROUP)
|
|
54
|
-
key = match[
|
|
54
|
+
key = match[:k]
|
|
55
55
|
raise HelpError, MSG[UNDEFINED_SECTION,key] unless specs[key]
|
|
56
56
|
group.push(key)
|
|
57
57
|
end
|
|
@@ -59,19 +59,19 @@ module HelpParser
|
|
|
59
59
|
end
|
|
60
60
|
specs.each do |key,tokens|
|
|
61
61
|
raise HelpError, MSG[MISSING_CASES,key] unless tokens.size>0
|
|
62
|
-
next if specs_usage.nil? or RESERVED
|
|
62
|
+
next if specs_usage.nil? or RESERVED.include? key
|
|
63
63
|
raise HelpError, MSG[MISSING_USAGE,key] unless group.include?(key)
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
def self.
|
|
67
|
+
def self.k2t2r(specs, k2t, t2r)
|
|
68
68
|
a,b = k2t.values.uniq.sort,t2r.keys.sort
|
|
69
69
|
unless a==b
|
|
70
70
|
c = (a+b).uniq.select{|x|!(a.include?(x) && b.include?(x))}
|
|
71
71
|
raise HelpError, MSG[UNCOMPLETED_TYPES,c.join(',')]
|
|
72
72
|
end
|
|
73
73
|
specs.each do |section,tokens|
|
|
74
|
-
next if
|
|
74
|
+
next if RESERVED.include? section
|
|
75
75
|
tokens.each do |words|
|
|
76
76
|
next if words.size<2
|
|
77
77
|
default = words[-1]
|
|
@@ -82,8 +82,11 @@ module HelpParser
|
|
|
82
82
|
long = long_type[2..(i-1)]
|
|
83
83
|
type = long_type[(i+1)..-1]
|
|
84
84
|
regex = t2r[type]
|
|
85
|
-
|
|
85
|
+
unless regex=~default
|
|
86
|
+
raise HelpError, MSG[BAD_DEFAULT,long,default,type,regex.inspect]
|
|
87
|
+
end
|
|
86
88
|
end
|
|
87
89
|
end
|
|
88
90
|
end
|
|
89
91
|
end
|
|
92
|
+
end
|
data/lib/help_parser.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
require_relative '
|
|
2
|
-
require_relative '
|
|
3
|
-
require_relative '
|
|
4
|
-
require_relative '
|
|
5
|
-
require_relative '
|
|
6
|
-
require_relative '
|
|
7
|
-
require_relative '
|
|
8
|
-
require_relative '
|
|
9
|
-
require_relative '
|
|
10
|
-
require_relative '
|
|
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 = '
|
|
13
|
+
VERSION = '8.1.221206'
|
|
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,20 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: help_parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 8.1.221206
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- CarlosJHR64
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-12-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description:
|
|
14
|
-
Can't help YOU???
|
|
15
|
-
You're not the first to say that...
|
|
16
|
-
|
|
17
|
-
I will parse your help!
|
|
13
|
+
description: "Welcome to Help Parser! \nDo you have your help text? \nLet's parse!\n"
|
|
18
14
|
email: carlosjhr64@gmail.com
|
|
19
15
|
executables: []
|
|
20
16
|
extensions: []
|
|
@@ -33,8 +29,8 @@ files:
|
|
|
33
29
|
- lib/help_parser/parsea.rb
|
|
34
30
|
- lib/help_parser/parseh.rb
|
|
35
31
|
- lib/help_parser/parseu.rb
|
|
36
|
-
- lib/help_parser/
|
|
37
|
-
homepage: https://github.com/carlosjhr64/
|
|
32
|
+
- lib/help_parser/validate.rb
|
|
33
|
+
homepage: https://github.com/carlosjhr64/help_parser
|
|
38
34
|
licenses:
|
|
39
35
|
- MIT
|
|
40
36
|
metadata: {}
|
|
@@ -53,9 +49,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
53
49
|
- !ruby/object:Gem::Version
|
|
54
50
|
version: '0'
|
|
55
51
|
requirements:
|
|
56
|
-
- 'ruby: ruby
|
|
57
|
-
rubygems_version: 3.
|
|
52
|
+
- 'ruby: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [aarch64-linux]'
|
|
53
|
+
rubygems_version: 3.3.7
|
|
58
54
|
signing_key:
|
|
59
55
|
specification_version: 4
|
|
60
|
-
summary:
|
|
56
|
+
summary: Welcome to Help Parser! Do you have your help text? Let's parse!
|
|
61
57
|
test_files: []
|