help_parser 6.3.0 → 7.0.200907
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +115 -61
- data/lib/help_parser.rb +1 -1
- data/lib/help_parser/completion.rb +32 -20
- data/lib/help_parser/constants.rb +9 -13
- data/lib/help_parser/exceptions.rb +4 -4
- data/lib/help_parser/k2t2r.rb +5 -2
- data/lib/help_parser/options.rb +16 -10
- data/lib/help_parser/parseh.rb +4 -4
- data/lib/help_parser/validations.rb +10 -8
- metadata +9 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7df1feedeed249286efe5cd5f1e2cc187a91d348eab654d5a6f110292d0c3476
|
4
|
+
data.tar.gz: a3f142a3d2cf4c6bf038b25e3552dfc3f56bfbb3469749386994b0763ccaea4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3df75b2ae4640bc268e86774facbc7f60e74fda4d58c3262022e3a571cb3d716af2be92e7d1652e2ffa5469a1852da4a412e582141f155fe849f37e62d4e4dc
|
7
|
+
data.tar.gz: 447dfb4939662fec618c4c315f104785e1923a6a625b82ed028981a9ff98c35c9049b23586501c8bd06e244f21de8da4cec2c491bf815a17d3c2d38f93495e4e
|
data/README.md
CHANGED
@@ -1,73 +1,127 @@
|
|
1
|
-
# Help Parser
|
1
|
+
# Help Parser VII: Deader
|
2
2
|
|
3
|
+
* [VERSION 7.0.200907](https://github.com/carlosjhr64/Ruby-HelpParser/releases)
|
3
4
|
* [github](https://www.github.com/carlosjhr64/Ruby-HelpParser)
|
4
5
|
* [rubygems](https://rubygems.org/gems/help_parser)
|
5
6
|
|
6
7
|
## DESCRIPTION:
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
I
|
8
|
+
|
9
|
+
Can't help YOU???
|
10
|
+
You're not the first to say that...
|
11
|
+
|
12
|
+
I will parse your help!
|
12
13
|
|
13
14
|
## SYNOPSIS:
|
15
|
+
<!-- The following PREVIEW has been approved for ALL PROGRAMMERS by CarlosJHR64.
|
16
|
+
For the README validator that checks against me lying....
|
17
|
+
```ruby
|
18
|
+
unless File.basename($PROGRAM_NAME) == 'deader'
|
19
|
+
# For example's sake say
|
20
|
+
$PROGRAM_NAME = 'deader'
|
21
|
+
# and ARGV is
|
22
|
+
ARGV.concat ["-\-age", "-\-date=2020-09-07", 'invoke', 'the', 'command']
|
23
|
+
# and proceed as if run as:
|
24
|
+
# awesome -\-name=Doe -\-value a b c
|
25
|
+
end
|
26
|
+
```
|
27
|
+
The following gem has been rated
|
28
|
+
| M | Mature |
|
29
|
+
-->
|
30
|
+
|
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
|
+
```ruby
|
36
|
+
require "help_parser"
|
37
|
+
|
38
|
+
HELP = <<-HELP
|
39
|
+
# <= Hash here, parser skips
|
40
|
+
# HelpParser: Deader command example #
|
41
|
+
Usage:
|
42
|
+
deader :options+ [<args>+]
|
43
|
+
deader [:alternate] <arg=FLOAT>
|
44
|
+
deader literal <arg1=WORD> <arg2=WORD> <arg3=WORD>
|
45
|
+
Options:
|
46
|
+
-v --version \t Give version and quit
|
47
|
+
-h --help \t Give help and quit
|
48
|
+
-s --long \t Short long synonyms
|
49
|
+
--command invoke \t Defaulted
|
50
|
+
--date=DATE \t Typed
|
51
|
+
--age=INTEGER 80 \t Typed and Defaulted
|
52
|
+
-a --all=YN y \t Short, long, typed, and defaulted
|
53
|
+
--to_be
|
54
|
+
--not_to_be
|
55
|
+
Exclusive:
|
56
|
+
to_be not_to_be \t Tells parser these are mutually exclusive keys
|
57
|
+
Inclusive:
|
58
|
+
date age \t Tells parser any of these must include all of these
|
59
|
+
Alternate:
|
60
|
+
--invoke
|
61
|
+
--wut
|
62
|
+
Types:
|
63
|
+
WORD /^[A-Za-z]+$/
|
64
|
+
DATE /^\\d\\d\\d\\d-\\d\\d-\\d\\d$/
|
65
|
+
INTEGER /^\\d+$/
|
66
|
+
FLOAT /^\\d+\\.\\d+$/
|
67
|
+
YN /^[YNyn]$/
|
68
|
+
# <= Hash here, parser breaks out
|
69
|
+
# Notes #
|
70
|
+
Don't invoke the command.
|
71
|
+
HELP
|
72
|
+
|
73
|
+
VERSION = "1.2.3"
|
74
|
+
|
75
|
+
OPTIONS = HelpParser[VERSION, HELP] #~> HelpParser
|
76
|
+
|
77
|
+
# Macros:
|
78
|
+
HelpParser.strings?(:args) # for OPTIONS.args : Array(String) | Nil
|
79
|
+
HelpParser.int?(:age) # for OPTIONS.age? : Integer | Nil
|
80
|
+
HelpParser.float(:arg) # for options.arg : Float
|
81
|
+
HelpParser.string(:arg1, :arg2, :arg3) # for OPTIONS.arg1, etc : String
|
82
|
+
#=> [:arg1, :arg2, :arg3]
|
83
|
+
|
84
|
+
## If run as:
|
85
|
+
## deader --age --date=2020-09-07 invoke the command
|
86
|
+
OPTIONS.age #=> 80
|
87
|
+
OPTIONS.args #=> ["invoke", "the", "command"]
|
88
|
+
OPTIONS.arg? and OPTIONS.arg #=> false
|
89
|
+
```
|
14
90
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
awesome :alternate <arg=NAME>
|
24
|
-
Options:
|
25
|
-
-v --version \t Give version and quit
|
26
|
-
-h --help \t Give help and quit
|
27
|
-
-s --long \t Short long synonyms
|
28
|
-
--name=NAME \t Typed
|
29
|
-
--number 5 \t Defaulted
|
30
|
-
--value=FLOAT 1.23 \t Typed and Defaulted
|
31
|
-
-a --all=YN y \t Short, long, typed, and defaulted
|
32
|
-
Alternate:
|
33
|
-
-V \t Just short
|
34
|
-
Types:
|
35
|
-
NAME /^[A-Z][a-z]+$/
|
36
|
-
FLOAT /^\\d+\\.\\d+$/
|
37
|
-
YN /^[YNyn]$/
|
38
|
-
Exclusive:
|
39
|
-
version help \t Tells parser these are exclusive keys
|
40
|
-
# <= Hash here, parser breaks out
|
41
|
-
# Notes #
|
42
|
-
Blah blah blah
|
43
|
-
HELP
|
44
|
-
|
45
|
-
VERSION = "6.3.0"
|
46
|
-
|
47
|
-
# Macros:
|
48
|
-
HelpParser.string(name) # for options.name : String
|
49
|
-
HelpParser.strings(args) # for options.args : Array(String)
|
50
|
-
HelpParser.float(value) # for options.value : Float
|
51
|
-
HelpParser.int?(number) # for options.number? : Int32 | Nil
|
52
|
-
|
53
|
-
HelpParser.run(VERSION, HELP) do |options|
|
54
|
-
hash = options._hash
|
55
|
-
pp hash # to inspect the hash
|
56
|
-
|
57
|
-
pp options.name if hash["name"]?
|
58
|
-
pp options.args if hash["args"]?
|
59
|
-
pp options.value if hash["value"]?
|
60
|
-
pp options.number?
|
61
|
-
end
|
62
|
-
|
63
|
-
Well, what do you think?
|
64
|
-
PERFECT!
|
65
|
-
|
66
|
-
## New for 6.1.0:
|
67
|
-
|
68
|
-
Running your `awesome` command with the `--help` flag will also check your help text for errors,
|
69
|
-
on top of giving the help text. Otherwise, the parser no longer checks for help text errors.
|
91
|
+
YOU HAVE INVOKED THE COMMAND...
|
92
|
+
YOUR HELP BELONGS TO ME!!!
|
93
|
+
|
94
|
+
## Features
|
95
|
+
|
96
|
+
* $DEBUG=true on --debug
|
97
|
+
* $VERBOSE=true on --verbose
|
98
|
+
* -h and --help simultaneously will check help string for errors
|
70
99
|
|
71
100
|
## INSTALL:
|
72
101
|
|
73
102
|
$ sudo gem install help_parser
|
103
|
+
|
104
|
+
## LICENSE:
|
105
|
+
|
106
|
+
(The MIT License)
|
107
|
+
|
108
|
+
Copyright (c) 2020 CarlosJHR64
|
109
|
+
|
110
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
111
|
+
a copy of this software and associated documentation files (the
|
112
|
+
'Software'), to deal in the Software without restriction, including
|
113
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
114
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
115
|
+
permit persons to whom the Software is furnished to do so, subject to
|
116
|
+
the following conditions:
|
117
|
+
|
118
|
+
The above copyright notice and this permission notice shall be
|
119
|
+
included in all copies or substantial portions of the Software.
|
120
|
+
|
121
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
122
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
123
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
124
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
125
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
126
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
127
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/help_parser.rb
CHANGED
@@ -3,44 +3,56 @@ module HelpParser
|
|
3
3
|
def initialize(hash, specs)
|
4
4
|
@hash,@specs = hash,specs
|
5
5
|
@cache = NoDupHash.new
|
6
|
-
usage if @specs.has_key?(USAGE)
|
6
|
+
usage or diagnose if @specs.has_key?(USAGE)
|
7
7
|
pad
|
8
|
-
types
|
8
|
+
types if @specs.has_key?(TYPES)
|
9
9
|
end
|
10
10
|
|
11
|
+
# Which usage does the user's command options match?
|
11
12
|
def usage
|
12
13
|
@specs[USAGE].each do |cmd|
|
13
14
|
begin
|
14
15
|
i = matches(cmd)
|
15
16
|
raise NoMatch unless @hash.size==i
|
16
17
|
@cache.each{|k,v|@hash[k]=v} # Variables
|
17
|
-
return
|
18
|
+
return true # Good! Found matching usage.
|
18
19
|
rescue NoMatch
|
19
20
|
next
|
20
21
|
ensure
|
21
22
|
@cache.clear
|
22
23
|
end
|
23
24
|
end
|
25
|
+
return false # Bad! Did not match any of the expected usage.
|
26
|
+
end
|
27
|
+
|
28
|
+
# Diagnose user's usage.
|
29
|
+
def diagnose
|
30
|
+
dict = {}
|
31
|
+
@specs.each do |k,v|
|
32
|
+
next if RESERVED[k]
|
33
|
+
v.flatten.map{|_|_.scan(/\w+/).first}.each{|_|dict[_]=true}
|
34
|
+
end
|
35
|
+
typos = @hash.keys.select{|k|k.is_a? String and not dict[k]}
|
36
|
+
raise UsageError, MSG[UNRECOGNIZED, typos] unless typos.empty?
|
37
|
+
|
24
38
|
raise UsageError, MATCH_USAGE
|
25
39
|
end
|
26
40
|
|
27
41
|
def types
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
raise UsageError, "--#{key}=#{string} !~ #{type}=#{regex.inspect}" unless string=~regex
|
40
|
-
end
|
41
|
-
else
|
42
|
-
raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
|
42
|
+
t2r,k2t = HelpParser.t2r(@specs),HelpParser.k2t(@specs)
|
43
|
+
@hash.each do |key,value|
|
44
|
+
next unless key.is_a?(String)
|
45
|
+
if type = k2t[key]
|
46
|
+
regex = t2r[type]
|
47
|
+
case value
|
48
|
+
when String
|
49
|
+
raise UsageError, "--#{key}=#{value} !~ #{type}=#{regex.inspect}" unless value=~regex
|
50
|
+
when Array
|
51
|
+
value.each do |string|
|
52
|
+
raise UsageError, "--#{key}=#{string} !~ #{type}=#{regex.inspect}" unless string=~regex
|
43
53
|
end
|
54
|
+
else
|
55
|
+
raise UsageError, "--#{key} !~ #{type}=#{regex.inspect}"
|
44
56
|
end
|
45
57
|
end
|
46
58
|
end
|
@@ -65,7 +77,7 @@ module HelpParser
|
|
65
77
|
elsif value = @hash[long]
|
66
78
|
@hash[short] = true
|
67
79
|
if value==true && !default.nil?
|
68
|
-
@hash.delete(long)
|
80
|
+
@hash.delete(long) # ArgvHash reset
|
69
81
|
@hash[long]=default
|
70
82
|
end
|
71
83
|
end
|
@@ -74,7 +86,7 @@ module HelpParser
|
|
74
86
|
long,default = first[2..(i-1)],second
|
75
87
|
value = @hash[long]
|
76
88
|
if value==true
|
77
|
-
@hash.delete(long)
|
89
|
+
@hash.delete(long) # ArgvHash reset
|
78
90
|
@hash[long] = default
|
79
91
|
end
|
80
92
|
end
|
@@ -1,15 +1,8 @@
|
|
1
1
|
module HelpParser
|
2
|
-
@@validate = false
|
3
|
-
def self.validate!
|
4
|
-
@@validate = true
|
5
|
-
end
|
6
|
-
def self.validate?
|
7
|
-
@@validate
|
8
|
-
end
|
9
|
-
|
10
2
|
USAGE = 'usage'
|
11
3
|
TYPES = 'types'
|
12
4
|
EXCLUSIVE = 'exclusive'
|
5
|
+
INCLUSIVE = 'inclusive'
|
13
6
|
|
14
7
|
# usage
|
15
8
|
FLAG = /^[-][-]?(?<k>\w+)$/
|
@@ -29,7 +22,7 @@ module HelpParser
|
|
29
22
|
TYPE_DEF = /^(?<t>[A-Z]+),?\s+\/(?<r>\S+)\/$/
|
30
23
|
|
31
24
|
# spec w+( w+)+
|
32
|
-
X_DEF = /^\w+( +\w+)+$/
|
25
|
+
X_DEF = /^\w+( +\w+)+$/ # for both exclusive and inclusive specs
|
33
26
|
|
34
27
|
CSV = /,?\s+/
|
35
28
|
|
@@ -42,18 +35,20 @@ module HelpParser
|
|
42
35
|
DUP_KEY = 'Duplicate key'
|
43
36
|
DUP_WORD = 'Duplicate word'
|
44
37
|
DUP_FLAG = 'Duplicate flag'
|
45
|
-
DUP_X = 'Duplicate exclusive spec'
|
38
|
+
DUP_X = 'Duplicate exclusive/inclusive spec'
|
46
39
|
UNSEEN_FLAG = 'Undefined flag'
|
47
40
|
INCONSISTENT = 'Inconsistent use of variable'
|
48
41
|
UNEXPECTED = 'Unexpected string in help text'
|
49
42
|
BAD_REGEX = 'Bad regex'
|
50
43
|
REDUNDANT = 'Redundant'
|
51
44
|
EXCLUSIVE_KEYS = 'Exclusive keys'
|
45
|
+
INCLUSIVE_KEYS = 'Inclusive keys'
|
52
46
|
UNBALANCED = 'Unbalanced brackets'
|
53
47
|
UNRECOGNIZED_TOKEN = 'Unrecognized usage token'
|
54
48
|
UNRECOGNIZED_TYPE = 'Unrecognized type spec'
|
55
|
-
UNRECOGNIZED_X = 'Unrecognized exclusive spec'
|
49
|
+
UNRECOGNIZED_X = 'Unrecognized exclusive/inclusive spec'
|
56
50
|
UNRECOGNIZED_OPTION = 'Unrecognized option spec'
|
51
|
+
UNRECOGNIZED = 'Unrecognized'
|
57
52
|
UNDEFINED_SECTION = 'Section not defined'
|
58
53
|
MISSING_CASES = 'Missing cases'
|
59
54
|
MISSING_USAGE = 'Missing usage'
|
@@ -71,7 +66,8 @@ module HelpParser
|
|
71
66
|
EXTRANEOUS_SPACES = 'Extraneous spaces in help.'
|
72
67
|
|
73
68
|
# lambda utilities
|
74
|
-
MSG = lambda{|msg,*keys| "
|
69
|
+
MSG = lambda{|msg,*keys| "#{msg}: #{keys.join(' ')}"}
|
75
70
|
F2K = lambda{|f| f[1]=='-' ? f[2..((f.index('=')||0)-1)] : f[1]}
|
76
|
-
RESERVED = lambda{|k| [USAGE,TYPES,EXCLUSIVE].include?(k)} # reserved
|
71
|
+
RESERVED = lambda{|k| [USAGE,TYPES,EXCLUSIVE,INCLUSIVE].include?(k)} # reserved
|
72
|
+
REDTTY = lambda{|msg,out=$stderr| out.tty? ? out.puts("\033[0;31m#{msg}\033[0m"): out.puts(msg)}
|
77
73
|
end
|
@@ -10,9 +10,9 @@ module HelpParser
|
|
10
10
|
|
11
11
|
def exit
|
12
12
|
if @code > 0
|
13
|
-
|
13
|
+
REDTTY[self.message]
|
14
14
|
else
|
15
|
-
puts self.message
|
15
|
+
$stdout.puts self.message
|
16
16
|
end
|
17
17
|
Kernel.exit @code
|
18
18
|
end
|
@@ -36,10 +36,10 @@ module HelpParser
|
|
36
36
|
end
|
37
37
|
|
38
38
|
class NoMatch < HelpParserException
|
39
|
-
# used to
|
39
|
+
# used to short-circuit out
|
40
40
|
def _init; @code = EX_SOFTWARE; end
|
41
41
|
|
42
|
-
# Forces it's
|
42
|
+
# Forces it's own message
|
43
43
|
def initialize
|
44
44
|
super(NO_MATCH)
|
45
45
|
end
|
data/lib/help_parser/k2t2r.rb
CHANGED
@@ -5,8 +5,11 @@ module HelpParser
|
|
5
5
|
tokens.each do |token|
|
6
6
|
if match = VARIABLE.match(token) || LONG.match(token)
|
7
7
|
name, type = match['k'], match['t']
|
8
|
-
k2t[name]
|
9
|
-
|
8
|
+
if _=k2t[name]
|
9
|
+
raise HelpError, MSG[INCONSISTENT,name,type,_] unless type==_
|
10
|
+
else
|
11
|
+
k2t[name] = type
|
12
|
+
end
|
10
13
|
else
|
11
14
|
# Expected these to be caught earlier...
|
12
15
|
raise SoftwareError, MSG[UNEXPECTED,token]
|
data/lib/help_parser/options.rb
CHANGED
@@ -7,22 +7,28 @@ module HelpParser
|
|
7
7
|
raise VersionException, version
|
8
8
|
end
|
9
9
|
if help
|
10
|
-
|
11
|
-
if
|
12
|
-
|
13
|
-
# validates help
|
14
|
-
HelpParser.parseh(help, true)
|
15
|
-
rescue HelpError
|
16
|
-
$stderr.puts $!
|
17
|
-
end if _
|
10
|
+
h = ['h', 'help']
|
11
|
+
if h.any?{|_|@hash.key?_}
|
12
|
+
HelpParser.parseh(help, validate: true) if h.all?{|_|@hash.key?_}
|
18
13
|
raise HelpException, help
|
19
14
|
end
|
20
|
-
specs = HelpParser.parseh(help
|
15
|
+
specs = HelpParser.parseh(help)
|
21
16
|
Completion.new(@hash, specs)
|
22
17
|
if exclusive=specs[EXCLUSIVE]
|
23
|
-
exclusive.each
|
18
|
+
exclusive.each do |x|
|
19
|
+
count = @hash.keys.count{|k|x.include?(k)}
|
20
|
+
raise HelpParser::UsageError, MSG[EXCLUSIVE_KEYS,*x] if count > 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
if inclusive=specs[INCLUSIVE]
|
24
|
+
inclusive.each do |i|
|
25
|
+
count = @hash.keys.count{|k|i.include?(k)}
|
26
|
+
raise HelpParser::UsageError, MSG[INCLUSIVE_KEYS,*i] unless count==0 or count==i.length
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
30
|
+
$VERBOSE = true if @hash['verbose']==true
|
31
|
+
$DEBUG = true if @hash['debug']==true
|
26
32
|
end
|
27
33
|
|
28
34
|
def _hash
|
data/lib/help_parser/parseh.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module HelpParser
|
2
|
-
def self.parseh(help, validate
|
2
|
+
def self.parseh(help, validate: false)
|
3
3
|
specs,name = NoDupHash.new,''
|
4
4
|
help.each_line do |line|
|
5
5
|
line.chomp!
|
@@ -18,11 +18,11 @@ module HelpParser
|
|
18
18
|
HelpParser.validate_line_chars(spec.chars) if validate
|
19
19
|
tokens = HelpParser.parseu(spec.chars)
|
20
20
|
HelpParser.validate_usage_tokens(tokens) if validate
|
21
|
-
specs[
|
21
|
+
specs[USAGE].push tokens
|
22
22
|
when TYPES
|
23
23
|
raise HelpError, MSG[UNRECOGNIZED_TYPE,spec] if validate and not spec=~TYPE_DEF
|
24
|
-
specs[
|
25
|
-
when EXCLUSIVE
|
24
|
+
specs[TYPES].push spec.split(CSV)
|
25
|
+
when EXCLUSIVE,INCLUSIVE
|
26
26
|
raise HelpError, MSG[UNRECOGNIZED_X,spec] if validate and not spec=~X_DEF
|
27
27
|
specs[name].push spec.split(CSV)
|
28
28
|
else
|
@@ -30,14 +30,16 @@ module HelpParser
|
|
30
30
|
def self.validate_usage_specs(specs)
|
31
31
|
option_specs = specs.select{|a,b| !RESERVED[a]}
|
32
32
|
flags = option_specs.values.flatten.select{|f|f[0]=='-'}.map{|f| F2K[f]}
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
33
|
+
[EXCLUSIVE,INCLUSIVE].each do |k|
|
34
|
+
if a=specs[k]
|
35
|
+
seen = {}
|
36
|
+
a.each do |xs|
|
37
|
+
k = xs.sort.join(' ').to_sym
|
38
|
+
raise HelpError, MSG[DUP_X,k] if seen[k] or not xs.length==xs.uniq.length
|
39
|
+
seen[k] = true
|
40
|
+
xs.each do |x|
|
41
|
+
raise HelpError, MSG[UNSEEN_FLAG, x] unless flags.include?(x)
|
42
|
+
end
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
metadata
CHANGED
@@ -1,21 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: help_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 7.0.200907
|
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: 2020-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
I prefer easy.
|
14
|
+
Can't help YOU???
|
15
|
+
You're not the first to say that...
|
16
|
+
|
17
|
+
I will parse your help!
|
19
18
|
email: carlosjhr64@gmail.com
|
20
19
|
executables: []
|
21
20
|
extensions: []
|
@@ -54,11 +53,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
53
|
- !ruby/object:Gem::Version
|
55
54
|
version: '0'
|
56
55
|
requirements:
|
57
|
-
- 'ruby: ruby 2.
|
58
|
-
|
59
|
-
rubygems_version: 2.7.3
|
56
|
+
- 'ruby: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]'
|
57
|
+
rubygems_version: 3.1.2
|
60
58
|
signing_key:
|
61
59
|
specification_version: 4
|
62
|
-
summary:
|
63
|
-
Hard? I prefer easy.
|
60
|
+
summary: Can't help YOU??? You're not the first to say that...
|
64
61
|
test_files: []
|