help_parser 4.0.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +42 -130
- data/lib/help_parser.rb +34 -6
- data/lib/help_parser/aliases.rb +19 -0
- data/lib/help_parser/completion.rb +135 -0
- data/lib/help_parser/constants.rb +17 -69
- data/lib/help_parser/exceptions.rb +51 -0
- data/lib/help_parser/k2t2r.rb +33 -0
- data/lib/help_parser/macros.rb +199 -0
- data/lib/help_parser/options.rb +40 -0
- data/lib/help_parser/parsea.rb +29 -0
- data/lib/help_parser/parseh.rb +29 -0
- data/lib/help_parser/parseu.rb +28 -0
- data/lib/help_parser/validations.rb +98 -0
- metadata +22 -10
- data/lib/help_parser/help_parser.rb +0 -99
- data/lib/help_parser/pattern.rb +0 -140
- data/lib/help_parser/usage.rb +0 -100
metadata
CHANGED
@@ -1,29 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: help_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- carlosjhr64
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description: |
|
14
|
+
All help is about to get parsed...
|
15
|
+
Again!!!
|
14
16
|
|
15
|
-
|
17
|
+
And this time,
|
18
|
+
the battle between complexity and simplicity
|
19
|
+
has as familiar text.
|
16
20
|
email: carlosjhr64@gmail.com
|
17
21
|
executables: []
|
18
22
|
extensions: []
|
19
23
|
extra_rdoc_files: []
|
20
24
|
files:
|
25
|
+
- LICENSE
|
21
26
|
- README.md
|
22
27
|
- lib/help_parser.rb
|
28
|
+
- lib/help_parser/aliases.rb
|
29
|
+
- lib/help_parser/completion.rb
|
23
30
|
- lib/help_parser/constants.rb
|
24
|
-
- lib/help_parser/
|
25
|
-
- lib/help_parser/
|
26
|
-
- lib/help_parser/
|
31
|
+
- lib/help_parser/exceptions.rb
|
32
|
+
- lib/help_parser/k2t2r.rb
|
33
|
+
- lib/help_parser/macros.rb
|
34
|
+
- lib/help_parser/options.rb
|
35
|
+
- lib/help_parser/parsea.rb
|
36
|
+
- lib/help_parser/parseh.rb
|
37
|
+
- lib/help_parser/parseu.rb
|
38
|
+
- lib/help_parser/validations.rb
|
27
39
|
homepage: https://github.com/carlosjhr64/help_parser
|
28
40
|
licenses:
|
29
41
|
- MIT
|
@@ -43,10 +55,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
43
55
|
- !ruby/object:Gem::Version
|
44
56
|
version: '0'
|
45
57
|
requirements:
|
46
|
-
- 'ruby: ruby 2.4.
|
58
|
+
- 'ruby: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]'
|
47
59
|
rubyforge_project:
|
48
|
-
rubygems_version: 2.6.
|
60
|
+
rubygems_version: 2.6.11
|
49
61
|
signing_key:
|
50
62
|
specification_version: 4
|
51
|
-
summary:
|
63
|
+
summary: All help is about to get parsed... Again!!!
|
52
64
|
test_files: []
|
@@ -1,99 +0,0 @@
|
|
1
|
-
module HELP_PARSER
|
2
|
-
|
3
|
-
# HelpParser should not alter argv
|
4
|
-
class HelpParser < BasicObject
|
5
|
-
USAGE_ERROR = lambda do |msg|
|
6
|
-
::Kernel::raise ::HELP_PARSER::UsageError,msg
|
7
|
-
end
|
8
|
-
|
9
|
-
Ms,Es = ::HELP_PARSER::M.to_sym, ::HELP_PARSER::E.to_sym
|
10
|
-
VALIDATE_KEY = lambda do |hsh,k|
|
11
|
-
USAGE_ERROR[DUP_KEY+k.to_s] if hsh.key?(k)
|
12
|
-
USAGE_ERROR[ILLEGAL_KEY+k.to_s] if Ms==k or Es==k
|
13
|
-
end
|
14
|
-
|
15
|
-
PARSE_ARGV = lambda do |argv|
|
16
|
-
hsh,n,i = {},0,0
|
17
|
-
argv.each do |a|
|
18
|
-
if a[0]==M # '-'
|
19
|
-
break if a==M
|
20
|
-
if a[1]==M
|
21
|
-
s,v = a.split(E,2) # split by '='
|
22
|
-
k = s[2..-1].to_sym
|
23
|
-
VALIDATE_KEY[hsh,k]
|
24
|
-
hsh[k] = (v)? v : true
|
25
|
-
else
|
26
|
-
# set each flag
|
27
|
-
a[1..-1].chars.each do |c|
|
28
|
-
k = c.to_sym
|
29
|
-
VALIDATE_KEY[hsh,k]
|
30
|
-
hsh[k]=true
|
31
|
-
end
|
32
|
-
end
|
33
|
-
else
|
34
|
-
# the nth argument
|
35
|
-
hsh[n] = a
|
36
|
-
n+=1
|
37
|
-
end
|
38
|
-
i+=1
|
39
|
-
end
|
40
|
-
return hsh
|
41
|
-
end
|
42
|
-
|
43
|
-
def initialize(version=nil, help=nil, argv=nil)
|
44
|
-
begin
|
45
|
-
hsh = PARSE_ARGV[(argv.nil?)? [::File.basename($0)]+::ARGV : argv]
|
46
|
-
if version and (hsh.key?(V) or hsh.key?(LV)) # -v or --version
|
47
|
-
$stdout.puts version
|
48
|
-
::Kernel::exit(0)
|
49
|
-
end
|
50
|
-
if help
|
51
|
-
if hsh.key?(H) or hsh.key?(LH) # -h or --help
|
52
|
-
$stdout.puts help
|
53
|
-
::Kernel::exit(0)
|
54
|
-
end
|
55
|
-
@usage = ::HELP_PARSER::Usage.new(help).validate(hsh)
|
56
|
-
end
|
57
|
-
rescue ::HELP_PARSER::UsageError => e
|
58
|
-
$stderr.puts COLOR[1]+e.message+COLOR[0]
|
59
|
-
$stderr.puts help if help
|
60
|
-
::Kernel::exit(64) # Usage
|
61
|
-
rescue ::HELP_PARSER::HelpError => e
|
62
|
-
msg = e.message
|
63
|
-
$stderr.puts COLOR[1]+msg+COLOR[0]
|
64
|
-
if ERROR_KEY =~ msg
|
65
|
-
$stderr.puts help.gsub($1,COLOR[1]+$1+COLOR[0])
|
66
|
-
else
|
67
|
-
$stderr.puts help
|
68
|
-
end
|
69
|
-
::Kernel::exit(78) # Config
|
70
|
-
end
|
71
|
-
@hash = hsh.freeze
|
72
|
-
end
|
73
|
-
|
74
|
-
def [](k)
|
75
|
-
@hash[k]
|
76
|
-
end
|
77
|
-
|
78
|
-
def _hash
|
79
|
-
@hash
|
80
|
-
end
|
81
|
-
|
82
|
-
def _usage
|
83
|
-
@usage
|
84
|
-
end
|
85
|
-
|
86
|
-
def method_missing(mthd, *args, &block)
|
87
|
-
super if block or args.length > 0
|
88
|
-
m = mthd.to_s
|
89
|
-
case m[-1]
|
90
|
-
when '?'
|
91
|
-
@hash.key? m[0..-2].to_sym
|
92
|
-
when '!'
|
93
|
-
super
|
94
|
-
else
|
95
|
-
@hash[mthd]
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
data/lib/help_parser/pattern.rb
DELETED
@@ -1,140 +0,0 @@
|
|
1
|
-
module HELP_PARSER
|
2
|
-
class Pattern
|
3
|
-
|
4
|
-
TYPE_MAP = lambda do |type,values,&block|
|
5
|
-
case type
|
6
|
-
when INT
|
7
|
-
case values
|
8
|
-
when Array
|
9
|
-
block.call values.map{|v|v.to_i}
|
10
|
-
when String
|
11
|
-
block.call values.to_i
|
12
|
-
end
|
13
|
-
when FLOAT
|
14
|
-
case values
|
15
|
-
when Array
|
16
|
-
block.call values.map{|v|v.to_f}
|
17
|
-
when String
|
18
|
-
block.call values.to_f
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
TYPE_VALIDATE = lambda do |values,tx,msg|
|
24
|
-
[*values].each do |value|
|
25
|
-
unless tx.match(value)
|
26
|
-
raise UsageError, sprintf(msg,value)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def initialize(options,usage)
|
32
|
-
@options,@usage = options,usage
|
33
|
-
@keys = options.keys
|
34
|
-
@cache = {}
|
35
|
-
end
|
36
|
-
|
37
|
-
def types
|
38
|
-
@usage[TYPES].each do |type,*words|
|
39
|
-
tx = Types[type] || Regexp.new(type.to_s)
|
40
|
-
words.each do |word|
|
41
|
-
values = @options[word]
|
42
|
-
next if values.nil?
|
43
|
-
TYPE_VALIDATE[values,tx,"#{word}: %s !~ /#{type}/"]
|
44
|
-
TYPE_MAP.call(type,values){|m| @options[word]=m}
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def pad
|
50
|
-
@cache.each{|k,v|@options[k]=v}
|
51
|
-
@usage.each do |name,words|
|
52
|
-
next if [USAGE,TYPES,DEFAULTS].include?(name)
|
53
|
-
words.each do |word|
|
54
|
-
next unless word.length==2
|
55
|
-
k,v = word
|
56
|
-
if v.class==Symbol
|
57
|
-
# Synonyms
|
58
|
-
if @options[k].nil?
|
59
|
-
@options[k]=@options[v] if @options.key?(v)
|
60
|
-
else
|
61
|
-
@options[v]=@options[k] unless @options.key?(v)
|
62
|
-
end
|
63
|
-
else
|
64
|
-
# Default
|
65
|
-
@options[k]=v unless @options.key?(k)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
if @usage.key?(DEFAULTS)
|
70
|
-
@usage[DEFAULTS].each do |words|
|
71
|
-
*ks,v = words
|
72
|
-
ks.each do |k|
|
73
|
-
@options[k]=v.to_s unless @options.key?(k)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def _matches(pattern, i)
|
80
|
-
pattern.each do |token|
|
81
|
-
key = @keys[i] # Might be nil, but need to proceed...
|
82
|
-
case token
|
83
|
-
when Array # it's optional, so a key.nil? might be ok
|
84
|
-
begin
|
85
|
-
i = _matches(token,i)
|
86
|
-
rescue NoMatch
|
87
|
-
# Ok, no problem!
|
88
|
-
end
|
89
|
-
next
|
90
|
-
when SELECTION_P # it's a selection
|
91
|
-
raise NoMatch if key.nil?
|
92
|
-
section,plus = $1,$2
|
93
|
-
list = @usage[section]
|
94
|
-
list = list.flatten
|
95
|
-
raise NoMatch unless list.include?(key)
|
96
|
-
unless plus.nil?
|
97
|
-
while list.include?(@keys[i+1])
|
98
|
-
i+=1
|
99
|
-
end
|
100
|
-
end
|
101
|
-
when VARIABLE_P # it's a variable
|
102
|
-
raise NoMatch if key.to_s.to_i==0 # nil.to_s.to_i==0 also works
|
103
|
-
word,plus = $1.to_sym,$2
|
104
|
-
unless plus.nil?
|
105
|
-
@cache[word] = [@options[key]]
|
106
|
-
while (key=@keys[i+1]).to_s.to_i > 0
|
107
|
-
i+=1
|
108
|
-
@cache[word].push(@options[key])
|
109
|
-
end
|
110
|
-
else
|
111
|
-
@cache[word] = @options[key]
|
112
|
-
end
|
113
|
-
else # it's a literal
|
114
|
-
raise NoMatch if key.nil?
|
115
|
-
if token[0]==M
|
116
|
-
raise NoMatch unless token == ((key.length>1)? MM : M)+key.to_s
|
117
|
-
else
|
118
|
-
raise NoMatch unless @options[key]==token
|
119
|
-
end
|
120
|
-
end
|
121
|
-
i+=1
|
122
|
-
end
|
123
|
-
return i
|
124
|
-
end
|
125
|
-
|
126
|
-
def matches(pattern)
|
127
|
-
begin
|
128
|
-
i = _matches(pattern, 0)
|
129
|
-
raise NoMatch if i != @options.length
|
130
|
-
pad
|
131
|
-
types if @usage[TYPES]
|
132
|
-
rescue NoMatch
|
133
|
-
return false
|
134
|
-
ensure
|
135
|
-
@cache.clear
|
136
|
-
end
|
137
|
-
return true
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
data/lib/help_parser/usage.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
module HELP_PARSER
|
2
|
-
class Usage
|
3
|
-
using HELP_PARSER::Refinements
|
4
|
-
|
5
|
-
DUPLICATES = lambda do |hsh|
|
6
|
-
a = hsh.select{|k| k!=TYPES and k!=DEFAULTS}.values.flatten.select{|e|e.class==Symbol}
|
7
|
-
if d = a.detect_duplicate
|
8
|
-
raise HelpError, DUP_KEY+d.to_s
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
VALIDATE_USAGE = lambda do |tokens|
|
13
|
-
seen = {}
|
14
|
-
tokens.flatten.each do |token|
|
15
|
-
t = token
|
16
|
-
if VARIABLE=~token
|
17
|
-
t = $1
|
18
|
-
elsif KEY=~token
|
19
|
-
t = $1
|
20
|
-
end
|
21
|
-
#raise HelpError, 'Duplicate Token: '+t if seen[t]
|
22
|
-
raise HelpError, DUP_KEY+t if seen[t]
|
23
|
-
seen[t]=true
|
24
|
-
end
|
25
|
-
return tokens
|
26
|
-
end
|
27
|
-
|
28
|
-
PARSE_USAGE = lambda do |chars|
|
29
|
-
tokens, token = [], I
|
30
|
-
while c = chars.shift
|
31
|
-
case c
|
32
|
-
when S,P,Q
|
33
|
-
unless token==I
|
34
|
-
tokens.push(token)
|
35
|
-
token = I
|
36
|
-
end
|
37
|
-
tokens.push PARSE_USAGE[chars] if c==P
|
38
|
-
return tokens if c==Q
|
39
|
-
else
|
40
|
-
token += c
|
41
|
-
end
|
42
|
-
end
|
43
|
-
tokens.push(token) unless token==I
|
44
|
-
return tokens
|
45
|
-
end
|
46
|
-
|
47
|
-
BALANCED = lambda do |chars|
|
48
|
-
count = 0
|
49
|
-
chars.each do |c|
|
50
|
-
if c==P then count+=1 elsif c==Q then count-=1 end
|
51
|
-
break if count<0
|
52
|
-
end
|
53
|
-
return count==0
|
54
|
-
end
|
55
|
-
|
56
|
-
def initialize(help)
|
57
|
-
hsh,name = {},Z
|
58
|
-
help.strip.split(SNS).each do |line|
|
59
|
-
next if line[0]==C # skip comment lines
|
60
|
-
line.sub!(COMMENTARY,'') # strip out commentary
|
61
|
-
case line
|
62
|
-
when SELECTION
|
63
|
-
name = $1.downcase
|
64
|
-
break if name==NOTES
|
65
|
-
raise HelpError, SECTION_REDEFINITION+name if hsh[name]
|
66
|
-
hsh[name] = []
|
67
|
-
else
|
68
|
-
case name
|
69
|
-
when Z
|
70
|
-
# Nothing to do
|
71
|
-
when USAGE
|
72
|
-
chars = line.chars
|
73
|
-
raise HelpError, UNBALANCE_BRACKETS+line unless BALANCED[chars]
|
74
|
-
hsh[USAGE].push(VALIDATE_USAGE[PARSE_USAGE[chars]])
|
75
|
-
when TYPES,DEFAULTS
|
76
|
-
raise HelpError, NOT_A_FLAG+line if line[0]==M
|
77
|
-
hsh[name].push line.split(SPS).map{|_|_.to_sym}
|
78
|
-
else
|
79
|
-
raise HelpError, MISSING_MINUS+line unless line[0]==M
|
80
|
-
hsh[name].push line.split(SPS).map{|_|(_[0]==M)? _.sub(MNS,'').to_sym : _}
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
DUPLICATES[hsh]
|
85
|
-
@hash = hsh.freeze
|
86
|
-
end
|
87
|
-
|
88
|
-
def _hash
|
89
|
-
@hash
|
90
|
-
end
|
91
|
-
|
92
|
-
def validate(options)
|
93
|
-
pattern = Pattern.new(options,@hash)
|
94
|
-
@hash[USAGE].each do |cmd|
|
95
|
-
return self if pattern.matches(cmd)
|
96
|
-
end
|
97
|
-
raise UsageError, MATCH_USAGE
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|