help_parser 8.0.210917 → 8.2.230210
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|