help_parser 8.0.210917 → 8.2.230210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -7
- data/lib/help_parser/aliases.rb +2 -2
- data/lib/help_parser/completion.rb +58 -43
- data/lib/help_parser/constants.rb +13 -12
- data/lib/help_parser/exceptions.rb +24 -10
- data/lib/help_parser/k2t2r.rb +12 -8
- data/lib/help_parser/macros.rb +84 -140
- data/lib/help_parser/options.rb +19 -20
- data/lib/help_parser/parsea.rb +3 -3
- data/lib/help_parser/parseh.rb +13 -11
- data/lib/help_parser/parseu.rb +6 -2
- data/lib/help_parser/validate.rb +30 -40
- data/lib/help_parser.rb +4 -4
- metadata +68 -9
- data/LICENSE +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f19d24ec56736d0d1bbcce1e0a847ac45e9d82defc89c7799c7b9c8c7c4ae078
|
4
|
+
data.tar.gz: fe92cf2d740771329bee184dd205d59bc72c1265d79ac50af3a6c4d0fa735297
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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,19 +93,19 @@ 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
|
105
|
-
* `HelpParser::REDTTY[msg]` will red color output `msg` to
|
102
|
+
* `HelpParser::REDTTY[msg]` will red color output `msg` to `$stderr`.
|
106
103
|
|
107
104
|
## LICENSE:
|
108
105
|
|
109
106
|
(The MIT License)
|
110
107
|
|
111
|
-
Copyright (c)
|
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
|
data/lib/help_parser/aliases.rb
CHANGED
@@ -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]
|
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
|
11
|
+
raise UsageError, MSG[DUP_KEY,k] if key?(k)
|
12
12
|
super
|
13
13
|
end
|
14
14
|
end
|
@@ -3,36 +3,50 @@ module HelpParser
|
|
3
3
|
def initialize(hash, specs)
|
4
4
|
@hash,@specs = hash,specs
|
5
5
|
@cache = NoDupHash.new
|
6
|
-
usage or diagnose
|
6
|
+
usage or diagnose if @specs.key?(USAGE)
|
7
7
|
pad
|
8
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
34
|
+
false # Bad! Did not match any of the expected usage.
|
26
35
|
end
|
27
36
|
|
28
37
|
# Diagnose user's usage.
|
29
38
|
def diagnose
|
30
39
|
dict = {}
|
31
|
-
@specs.each do |
|
32
|
-
next if RESERVED.include?
|
33
|
-
|
40
|
+
@specs.each do |section,list|
|
41
|
+
next if RESERVED.include? section
|
42
|
+
list.flatten.select{_1[0]=='-'}.each do |key_type|
|
43
|
+
key_type.scan(/\w+/) do |key|
|
44
|
+
dict[key]=true
|
45
|
+
break
|
46
|
+
end
|
47
|
+
end
|
34
48
|
end
|
35
|
-
typos = @hash.keys.select{
|
49
|
+
typos = @hash.keys.select{_1.is_a?(String) && !dict[_1]}
|
36
50
|
raise UsageError, MSG[UNRECOGNIZED, typos] unless typos.empty?
|
37
51
|
|
38
52
|
raise UsageError, MATCH_USAGE
|
@@ -41,32 +55,31 @@ module HelpParser
|
|
41
55
|
def types
|
42
56
|
t2r,k2t = HelpParser.t2r(@specs),HelpParser.k2t(@specs)
|
43
57
|
@hash.each do |key,value|
|
44
|
-
next unless key.is_a?(String)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
"--#{key}=#{string} !~ #{type}=#{regex.inspect}"
|
57
|
-
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}"
|
58
70
|
end
|
59
|
-
else
|
60
|
-
raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
|
61
71
|
end
|
72
|
+
else
|
73
|
+
raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
|
62
74
|
end
|
63
75
|
end
|
76
|
+
k2t
|
64
77
|
end
|
65
78
|
|
66
79
|
def pad
|
67
80
|
# Synonyms and defaults:
|
68
81
|
@specs.each do |section,options|
|
69
|
-
next if section==
|
82
|
+
next if RESERVED.any?{section==_1}
|
70
83
|
options.each do |words|
|
71
84
|
next unless words.size>1
|
72
85
|
first,second,default = words[0],words[1],words[2]
|
@@ -74,12 +87,12 @@ module HelpParser
|
|
74
87
|
if second[0]=='-'
|
75
88
|
i = second.index('=') || 0
|
76
89
|
short,long = first[1],second[2..(i-1)]
|
77
|
-
if @hash.
|
78
|
-
if @hash.
|
90
|
+
if @hash.key?(short)
|
91
|
+
if @hash.key?(long)
|
79
92
|
raise UsageError, MSG[REDUNDANT, short, long]
|
80
93
|
end
|
81
|
-
@hash[long] =
|
82
|
-
elsif value
|
94
|
+
@hash[long] = default.nil? ? true : default
|
95
|
+
elsif (value=@hash[long])
|
83
96
|
@hash[short] = true
|
84
97
|
if value==true && !default.nil?
|
85
98
|
@hash.delete(long) # ArgvHash reset
|
@@ -95,6 +108,8 @@ module HelpParser
|
|
95
108
|
@hash[long] = default
|
96
109
|
end
|
97
110
|
end
|
111
|
+
else
|
112
|
+
raise SoftwareError, MSG[UNEXPECTED, words]
|
98
113
|
end
|
99
114
|
end
|
100
115
|
end
|
@@ -110,20 +125,20 @@ module HelpParser
|
|
110
125
|
# OK, NEVERMIND!
|
111
126
|
end
|
112
127
|
next
|
113
|
-
elsif m=FLAG_GROUP.match
|
128
|
+
elsif (m=FLAG_GROUP.match token)
|
114
129
|
group,plus = m[:k],m[:p]
|
115
130
|
key = keys[i]
|
116
|
-
raise NoMatch
|
131
|
+
raise NoMatch unless key.is_a? String
|
117
132
|
list = @specs[group].flatten.select{|f|f[0]=='-'}.map{|f| F2K[f]}
|
118
133
|
raise NoMatch unless list.include?(key)
|
119
134
|
unless plus.nil?
|
120
135
|
loop do
|
121
136
|
key = keys[i+1]
|
122
|
-
break
|
137
|
+
break unless key.is_a?(String) && list.include?(key)
|
123
138
|
i+=1
|
124
139
|
end
|
125
140
|
end
|
126
|
-
elsif m=VARIABLE.match(token)
|
141
|
+
elsif (m=VARIABLE.match(token))
|
127
142
|
key = keys[i]
|
128
143
|
raise NoMatch unless key.is_a?(Integer)
|
129
144
|
variable,plus = m[:k],m[:p]
|
@@ -146,7 +161,7 @@ module HelpParser
|
|
146
161
|
end
|
147
162
|
i += 1
|
148
163
|
end
|
149
|
-
|
164
|
+
i
|
150
165
|
end
|
151
166
|
end
|
152
167
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module HelpParser
|
2
|
-
|
3
|
-
|
2
|
+
VSN = %w[v version]
|
3
|
+
HLP = %w[h help]
|
4
4
|
VRBS,DBG = 'verbose','debug'
|
5
5
|
|
6
6
|
# reserved name
|
@@ -13,22 +13,22 @@ module HelpParser
|
|
13
13
|
RESERVED = [USAGE,TYPES,EXCLUSIVE,INCLUSIVE,CONDITIONAL]
|
14
14
|
|
15
15
|
# sections
|
16
|
-
SECTION_NAME = /^[A-Z]\w
|
16
|
+
SECTION_NAME = /^(?<name>[A-Z]\w+):$/
|
17
17
|
|
18
18
|
# usage
|
19
|
-
FLAG =
|
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 =
|
26
|
-
LONG =
|
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 =
|
29
|
+
SHORT_LONG = /^-(?<s>\w),?\s+--(?<k>\w+)$/
|
30
30
|
SHORT_LONG_DEFAULT =
|
31
|
-
|
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 =
|
83
|
-
F2K =
|
84
|
-
REDTTY = lambda
|
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
|
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
|
13
|
-
REDTTY[
|
14
|
+
if @code.positive?
|
15
|
+
REDTTY[message]
|
14
16
|
else
|
15
|
-
$stdout.puts
|
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
|
24
|
+
def _init
|
25
|
+
@code = 0
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
class HelpException < HelpParserException
|
26
|
-
def _init
|
30
|
+
def _init
|
31
|
+
@code = 0
|
32
|
+
end
|
27
33
|
end
|
28
34
|
|
29
35
|
class UsageError < HelpParserException
|
30
|
-
def _init
|
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
|
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
|
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
|
61
|
+
def _init
|
62
|
+
@code = EX_CONFIG
|
63
|
+
end
|
50
64
|
end
|
51
65
|
end
|
data/lib/help_parser/k2t2r.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
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
|
-
|
5
|
+
# If specs section is not a RESERVED section, it's an options list.
|
6
|
+
tokens = specs.select{|k,_| k==USAGE or !RESERVED.include?(k)}
|
7
|
+
# Tokens associating a key to a type.
|
8
|
+
.values.flatten.select{|v|v.include?('=')}
|
6
9
|
tokens.each do |token|
|
7
|
-
if match = VARIABLE.match(token) || LONG.match(token)
|
10
|
+
if (match = VARIABLE.match(token) || LONG.match(token))
|
8
11
|
name, type = match[:k], match[:t]
|
9
|
-
if _=k2t[name]
|
10
|
-
raise HelpError, MSG[INCONSISTENT,name,type,_]
|
12
|
+
if (_=k2t[name])
|
13
|
+
raise HelpError, MSG[INCONSISTENT,name,type,_] unless type==_
|
11
14
|
else
|
12
15
|
k2t[name] = type
|
13
16
|
end
|
@@ -16,11 +19,12 @@ module HelpParser
|
|
16
19
|
raise SoftwareError, MSG[UNEXPECTED,token]
|
17
20
|
end
|
18
21
|
end
|
19
|
-
|
22
|
+
k2t
|
20
23
|
end
|
21
24
|
|
25
|
+
# t2r is an acronym for "type to regexp"
|
22
26
|
def self.t2r(specs)
|
23
|
-
if types
|
27
|
+
if (types=specs[TYPES])
|
24
28
|
t2r = NoDupHash.new
|
25
29
|
types.each do |pair|
|
26
30
|
type, pattern = *pair
|
@@ -32,6 +36,6 @@ module HelpParser
|
|
32
36
|
end
|
33
37
|
return t2r
|
34
38
|
end
|
35
|
-
|
39
|
+
nil
|
36
40
|
end
|
37
41
|
end
|
data/lib/help_parser/macros.rb
CHANGED
@@ -1,201 +1,145 @@
|
|
1
1
|
module HelpParser
|
2
2
|
def self.string(*names)
|
3
3
|
names.each do |name|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
raise UsageError, MSG[NOT_FLOAT,'#{name}']
|
74
|
-
end
|
75
|
-
end
|
76
|
-
CODE
|
77
|
-
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
|
78
59
|
end
|
79
60
|
end
|
80
61
|
|
81
62
|
def self.float?(*names)
|
82
63
|
names.each do |name|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
raise UsageError, MSG[NOT_FLOAT,'#{name}']
|
91
|
-
end
|
92
|
-
end
|
93
|
-
CODE
|
94
|
-
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
|
95
71
|
end
|
96
72
|
end
|
97
73
|
|
98
74
|
def self.floats(*names)
|
99
75
|
names.each do |name|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
raise UsageError, MSG[#{NOT_FLOATS},'#{name}']
|
108
|
-
end
|
109
|
-
end
|
110
|
-
CODE
|
111
|
-
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
|
112
83
|
end
|
113
84
|
end
|
114
85
|
|
115
86
|
def self.floats?(*names)
|
116
87
|
names.each do |name|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
rescue
|
125
|
-
raise UsageError, MSG[NOT_FLOATS,'#{name}']
|
126
|
-
end
|
127
|
-
end
|
128
|
-
CODE
|
129
|
-
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
|
130
95
|
end
|
131
96
|
end
|
132
97
|
|
133
98
|
def self.int(*names)
|
134
99
|
names.each do |name|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
raise UsageError, MSG[NOT_INTEGER,'#{name}']
|
143
|
-
end
|
144
|
-
end
|
145
|
-
CODE
|
146
|
-
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
|
147
107
|
end
|
148
108
|
end
|
149
109
|
|
150
110
|
def self.int?(*names)
|
151
111
|
names.each do |name|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
raise UsageError, MSG[NOT_INTEGER,'#{name}']
|
160
|
-
end
|
161
|
-
end
|
162
|
-
CODE
|
163
|
-
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
|
164
119
|
end
|
165
120
|
end
|
166
121
|
|
167
122
|
def self.ints(*names)
|
168
123
|
names.each do |name|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
raise UsageError, MSG[NOT_INTEGERS,'#{name}']
|
177
|
-
end
|
178
|
-
end
|
179
|
-
CODE
|
180
|
-
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
|
181
131
|
end
|
182
132
|
end
|
183
133
|
|
184
134
|
def self.ints?(*names)
|
185
135
|
names.each do |name|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
rescue
|
194
|
-
raise UsageError, MSG[NOT_INTEGERS,'#{name}']
|
195
|
-
end
|
196
|
-
end
|
197
|
-
CODE
|
198
|
-
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
|
199
143
|
end
|
200
144
|
end
|
201
145
|
end
|
data/lib/help_parser/options.rb
CHANGED
@@ -2,35 +2,35 @@ 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.key? _1}
|
6
6
|
# -v or --version
|
7
|
-
raise VersionException, version
|
7
|
+
raise VersionException, String(version)
|
8
8
|
end
|
9
9
|
if help
|
10
|
-
|
11
|
-
if
|
12
|
-
HelpParser.parseh(help, validate: true)
|
10
|
+
help = String(help)
|
11
|
+
if HLP.any?{@hash.key? _1}
|
12
|
+
HelpParser.parseh(help, validate: true) if HLP.all?{@hash.key? _1}
|
13
13
|
raise HelpException, help
|
14
14
|
end
|
15
15
|
specs = HelpParser.parseh(help)
|
16
16
|
Completion.new(@hash, specs)
|
17
|
-
if exclusive=specs[EXCLUSIVE]
|
17
|
+
if (exclusive=specs[EXCLUSIVE])
|
18
18
|
exclusive.each do |x|
|
19
19
|
count = x.count{@hash.key? _1}
|
20
20
|
raise HelpParser::UsageError, MSG[EXCLUSIVE_KEYS,*x] if count > 1
|
21
21
|
end
|
22
22
|
end
|
23
|
-
if inclusive=specs[INCLUSIVE]
|
23
|
+
if (inclusive=specs[INCLUSIVE])
|
24
24
|
inclusive.each do |i|
|
25
25
|
count = i.count{@hash.key? _1}
|
26
|
-
unless count
|
26
|
+
unless count.zero? || count==i.length
|
27
27
|
raise HelpParser::UsageError, MSG[INCLUSIVE_KEYS,*i]
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
|
-
if conditional=specs[CONDITIONAL]
|
31
|
+
if (conditional=specs[CONDITIONAL])
|
32
32
|
conditional.each do |c|
|
33
|
-
if @hash.key?
|
33
|
+
if @hash.key?(c[0]) && !c.all?{@hash.key? _1}
|
34
34
|
raise HelpParser::UsageError, MSG[CONDITIONAL_KEYS,*c]
|
35
35
|
end
|
36
36
|
end
|
@@ -48,17 +48,16 @@ module HelpParser
|
|
48
48
|
@hash[k]
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
@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'
|
61
59
|
end
|
60
|
+
m[-1]=='?' ? @hash.key?(m[0..-2].to_s) : @hash[m.to_s]
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
data/lib/help_parser/parsea.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
27
|
+
hsh
|
28
28
|
end
|
29
29
|
end
|
data/lib/help_parser/parseh.rb
CHANGED
@@ -4,45 +4,47 @@ 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==''
|
12
12
|
break if line[0]=='#'
|
13
|
-
next
|
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
|
15
|
+
raise HelpError, EXTRANEOUS_SPACES if validate && spec.empty?
|
16
16
|
case name
|
17
17
|
when USAGE
|
18
|
-
Validate.
|
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
|
-
if validate
|
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
|
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
|
-
|
34
|
-
|
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
|
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
|
-
|
48
|
+
specs
|
47
49
|
end
|
48
50
|
end
|
data/lib/help_parser/parseu.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
module HelpParser
|
2
|
+
# Chars := String.split(/\t/,2).first.strip.chars
|
3
|
+
# Token := String=~/^[^ \[\]]$/
|
4
|
+
# Note that emergent Token is String=~/^[^\s\[\]]$/
|
5
|
+
# Tokens := Array(Token|Tokens)
|
2
6
|
def self.parseu(chars)
|
3
7
|
tokens,token = [],''
|
4
|
-
while c
|
8
|
+
while (c=chars.shift)
|
5
9
|
case c
|
6
10
|
when ' ','[',']'
|
7
11
|
unless token==''
|
@@ -15,6 +19,6 @@ module HelpParser
|
|
15
19
|
end
|
16
20
|
end
|
17
21
|
tokens.push(token) unless token==''
|
18
|
-
|
22
|
+
tokens
|
19
23
|
end
|
20
24
|
end
|
data/lib/help_parser/validate.rb
CHANGED
@@ -1,27 +1,20 @@
|
|
1
1
|
module HelpParser
|
2
2
|
module Validate
|
3
|
-
def self.
|
3
|
+
def self.balanced_brackets(chars)
|
4
4
|
count = 0
|
5
5
|
chars.each do |c|
|
6
|
-
|
7
|
-
|
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
|
9
|
+
raise HelpError, MSG[UNBALANCED,chars.join] unless count.zero?
|
14
10
|
end
|
15
11
|
|
16
12
|
def self.usage_tokens(tokens)
|
17
13
|
words = []
|
18
14
|
tokens.flatten.each do |token|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
token.match(FLAG_GROUP)
|
23
|
-
raise HelpError, MSG[UNRECOGNIZED_TOKEN,token] unless match
|
24
|
-
words.push match[:k] # key
|
15
|
+
raise HelpError, MSG[UNRECOGNIZED_TOKEN,token] unless
|
16
|
+
[FLAG,LITERAL,VARIABLE,FLAG_GROUP]
|
17
|
+
.detect{(_=token.match _1) && words.push(_[:k])}
|
25
18
|
end
|
26
19
|
words.each_with_index do |word,i|
|
27
20
|
raise HelpError, MSG[DUP_WORD,word] unless i==words.rindex(word)
|
@@ -29,40 +22,37 @@ module Validate
|
|
29
22
|
end
|
30
23
|
|
31
24
|
def self.usage_specs(specs)
|
32
|
-
|
33
|
-
|
25
|
+
flags = specs.except(*RESERVED).values.flatten
|
26
|
+
.select{_1[0]=='-'}.map{F2K[_1]}
|
34
27
|
FLAG_CLUMPS.each do |k|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
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)
|
46
38
|
end
|
47
39
|
end
|
48
40
|
end
|
49
41
|
flags.each_with_index do |flag,i|
|
50
42
|
raise HelpError, MSG[DUP_FLAG,flag] unless i==flags.rindex(flag)
|
51
|
-
end
|
43
|
+
end
|
52
44
|
group = []
|
53
45
|
specs_usage = specs[USAGE]
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
group.push(key)
|
60
|
-
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)
|
61
51
|
end
|
62
52
|
end
|
63
53
|
specs.each do |key,tokens|
|
64
|
-
raise HelpError, MSG[MISSING_CASES,key]
|
65
|
-
next if specs_usage.nil?
|
54
|
+
raise HelpError, MSG[MISSING_CASES,key] if tokens.empty?
|
55
|
+
next if specs_usage.nil? || RESERVED.include?(key)
|
66
56
|
raise HelpError, MSG[MISSING_USAGE,key] unless group.include?(key)
|
67
57
|
end
|
68
58
|
end
|
@@ -70,11 +60,11 @@ module Validate
|
|
70
60
|
def self.k2t2r(specs, k2t, t2r)
|
71
61
|
a,b = k2t.values.uniq.sort,t2r.keys.sort
|
72
62
|
unless a==b
|
73
|
-
c = (a+b).uniq.
|
63
|
+
c = (a+b).uniq.reject{|x|a.include?(x) && b.include?(x)}
|
74
64
|
raise HelpError, MSG[UNCOMPLETED_TYPES,c.join(',')]
|
75
65
|
end
|
76
66
|
specs.each do |section,tokens|
|
77
|
-
next if
|
67
|
+
next if RESERVED.include? section
|
78
68
|
tokens.each do |words|
|
79
69
|
next if words.size<2
|
80
70
|
default = words[-1]
|
@@ -83,7 +73,7 @@ module Validate
|
|
83
73
|
i = long_type.index('=')
|
84
74
|
next if i.nil?
|
85
75
|
long = long_type[2..(i-1)]
|
86
|
-
type = long_type[(i+1)
|
76
|
+
type = long_type[(i+1)..]
|
87
77
|
regex = t2r[type]
|
88
78
|
unless regex=~default
|
89
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.
|
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 =>
|
22
|
-
|
21
|
+
rescue HelpParserException => e
|
22
|
+
e.exit
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
# Requires:
|
27
|
-
|
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.
|
4
|
+
version: 8.2.230210
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- CarlosJHR64
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
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
|
@@ -34,7 +93,7 @@ homepage: https://github.com/carlosjhr64/help_parser
|
|
34
93
|
licenses:
|
35
94
|
- MIT
|
36
95
|
metadata: {}
|
37
|
-
post_install_message:
|
96
|
+
post_install_message:
|
38
97
|
rdoc_options: []
|
39
98
|
require_paths:
|
40
99
|
- lib
|
@@ -49,9 +108,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
108
|
- !ruby/object:Gem::Version
|
50
109
|
version: '0'
|
51
110
|
requirements:
|
52
|
-
- '
|
53
|
-
rubygems_version: 3.
|
54
|
-
signing_key:
|
111
|
+
- 'git: 2.30'
|
112
|
+
rubygems_version: 3.4.6
|
113
|
+
signing_key:
|
55
114
|
specification_version: 4
|
56
115
|
summary: Welcome to Help Parser! Do you have your help text? Let's parse!
|
57
116
|
test_files: []
|
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.
|