help_parser 1.0.2 → 1.1.0
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/History.txt +2 -0
- data/Manifest.txt +7 -5
- data/TODO.txt +3 -0
- data/help_parser.gemspec +15 -8
- data/lib/help_parser.rb +7 -0
- data/lib/help_parser/errors.rb +17 -0
- data/lib/help_parser/functions.rb +62 -0
- data/lib/help_parser/help_exception.rb +16 -0
- data/lib/help_parser/help_parser.rb +103 -260
- data/lib/help_parser/implementation_error.rb +16 -0
- data/lib/help_parser/usage_error.rb +16 -0
- data/lib/help_parser/usage_exception.rb +18 -0
- data/lib/help_parser/version.rb +1 -1
- data/lib/help_parser/version_exception.rb +16 -0
- data/test/help_parser.rb +2 -2
- metadata +53 -9
- data/Rakefile +0 -94
- data/tasks/gemspecker.rb +0 -60
- data/tasks/manifester.rb +0 -13
- data/tasks/syntaxer.rb +0 -25
- data/tasks/unit_tests.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b2c52b4521273e3423cf52dbb22b9f475fedade
|
4
|
+
data.tar.gz: 67c4807edaa755306f43b30ca85cf0400250a8d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be5f3fde5967198c766bf2e6dfcdfd084476d6843ae43b0f76243753c8ddb7e498d509d10f2f0fba33d78c07f39bd43159d5a0a000b5347f3ad8794224873b34
|
7
|
+
data.tar.gz: a07a636b9c9f0c5b482fcd7a2442c01d680d601854f1822954071778945308df2f76e438c86ca53d102db203a378b6f01bc75363aca5b4095fa8fe70ea5ae5e0
|
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
History.txt
|
2
2
|
Manifest.txt
|
3
3
|
README.rdoc
|
4
|
-
Rakefile
|
5
4
|
TODO.txt
|
6
5
|
examples/command_suite
|
7
6
|
examples/implementation_error_duplicate_key
|
@@ -14,10 +13,13 @@ features/step_definitions/help_parser_steps.rb
|
|
14
13
|
features/suite.feature
|
15
14
|
help_parser.gemspec
|
16
15
|
lib/help_parser.rb
|
16
|
+
lib/help_parser/errors.rb
|
17
|
+
lib/help_parser/functions.rb
|
18
|
+
lib/help_parser/help_exception.rb
|
17
19
|
lib/help_parser/help_parser.rb
|
20
|
+
lib/help_parser/implementation_error.rb
|
21
|
+
lib/help_parser/usage_error.rb
|
22
|
+
lib/help_parser/usage_exception.rb
|
18
23
|
lib/help_parser/version.rb
|
19
|
-
|
20
|
-
tasks/manifester.rb
|
21
|
-
tasks/syntaxer.rb
|
22
|
-
tasks/unit_tests.rb
|
24
|
+
lib/help_parser/version_exception.rb
|
23
25
|
test/help_parser.rb
|
data/TODO.txt
CHANGED
data/help_parser.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'help_parser'
|
4
|
-
s.version = '1.0
|
4
|
+
s.version = '1.1.0'
|
5
5
|
|
6
6
|
s.homepage = 'https://github.com/carlosjhr64/help_parser'
|
7
7
|
|
8
8
|
s.author = 'CarlosJHR64'
|
9
9
|
s.email = 'carlosjhr64@gmail.com'
|
10
10
|
|
11
|
-
s.date = '2013-12-
|
11
|
+
s.date = '2013-12-16'
|
12
12
|
s.licenses = ['MIT']
|
13
13
|
|
14
14
|
s.description = <<DESCRIPTION
|
@@ -27,7 +27,6 @@ SUMMARY
|
|
27
27
|
History.txt
|
28
28
|
Manifest.txt
|
29
29
|
README.rdoc
|
30
|
-
Rakefile
|
31
30
|
TODO.txt
|
32
31
|
examples/command_suite
|
33
32
|
examples/implementation_error_duplicate_key
|
@@ -40,13 +39,21 @@ features/step_definitions/help_parser_steps.rb
|
|
40
39
|
features/suite.feature
|
41
40
|
help_parser.gemspec
|
42
41
|
lib/help_parser.rb
|
42
|
+
lib/help_parser/errors.rb
|
43
|
+
lib/help_parser/functions.rb
|
44
|
+
lib/help_parser/help_exception.rb
|
43
45
|
lib/help_parser/help_parser.rb
|
46
|
+
lib/help_parser/implementation_error.rb
|
47
|
+
lib/help_parser/usage_error.rb
|
48
|
+
lib/help_parser/usage_exception.rb
|
44
49
|
lib/help_parser/version.rb
|
45
|
-
|
46
|
-
tasks/manifester.rb
|
47
|
-
tasks/syntaxer.rb
|
48
|
-
tasks/unit_tests.rb
|
50
|
+
lib/help_parser/version_exception.rb
|
49
51
|
test/help_parser.rb
|
50
|
-
)
|
52
|
+
)
|
53
|
+
|
54
|
+
s.add_development_dependency 'rainbow', '~> 1.1', '>= 1.1.4'
|
55
|
+
s.add_development_dependency 'test-unit', '~> 2.5', '>= 2.5.5'
|
56
|
+
s.requirements << 'requires json in development'
|
57
|
+
s.requirements << 'requires open3 in development'
|
51
58
|
|
52
59
|
end
|
data/lib/help_parser.rb
CHANGED
@@ -1,2 +1,9 @@
|
|
1
1
|
require 'help_parser/version.rb'
|
2
|
+
require 'help_parser/usage_exception'
|
3
|
+
require 'help_parser/help_exception'
|
4
|
+
require 'help_parser/version_exception'
|
5
|
+
require 'help_parser/implementation_error'
|
6
|
+
require 'help_parser/usage_error'
|
7
|
+
require 'help_parser/errors'
|
8
|
+
require 'help_parser/functions'
|
2
9
|
require 'help_parser/help_parser.rb'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# Used to *include* in a class.
|
3
|
+
module Errors
|
4
|
+
# HelpParser#usage_error will have make the HelpParser
|
5
|
+
# object raise a UsageError error with the given message.
|
6
|
+
def usage_error(msg)
|
7
|
+
raise UsageError, [msg, self]
|
8
|
+
end
|
9
|
+
|
10
|
+
# HelpParser#implementation_error will have make the
|
11
|
+
# HelpParser object raise a UsageError error with the
|
12
|
+
# given message.
|
13
|
+
def implementation_error(msg)
|
14
|
+
raise ImplementationError, [msg, self]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# I'm wrapping class functions in a Function module.
|
3
|
+
# Used to *extend* a class.
|
4
|
+
module Functions
|
5
|
+
|
6
|
+
# HelpParser.to_value
|
7
|
+
def to_value(string)
|
8
|
+
case string
|
9
|
+
when /^-?\d+$/
|
10
|
+
return string.to_i
|
11
|
+
when /^-?\d+\.\d+$/
|
12
|
+
return string.to_f
|
13
|
+
when /,/
|
14
|
+
return string.split(',').map{|s| to_value(s)}
|
15
|
+
end
|
16
|
+
return string
|
17
|
+
end
|
18
|
+
|
19
|
+
# HelpParser.str2sym converts String keys to
|
20
|
+
# Symbol. Symbol keys can have '-', but it's cumbersome
|
21
|
+
# notation:
|
22
|
+
# :"a-b"
|
23
|
+
# So I translate it to underscore:
|
24
|
+
# :a_b
|
25
|
+
def str2sym(str)
|
26
|
+
str.gsub('-','_').to_sym
|
27
|
+
end
|
28
|
+
|
29
|
+
# HelpParser.parse parses the @argv for command line
|
30
|
+
# options, shifting them out, and passes on the key-value
|
31
|
+
# pairs to the block. The keys are translated to their
|
32
|
+
# short version if available, and the values are converted
|
33
|
+
# to their best interpreted form as per Funtion.to_value.
|
34
|
+
# Furthermore, no-key values are negated.
|
35
|
+
def parse(argv, obj, &block)
|
36
|
+
while argv[0] and argv[0][0]=='-'
|
37
|
+
option = argv.shift[1..-1]
|
38
|
+
if option[0]=='-'
|
39
|
+
loption, value = option[1..-1].split('=', 2)
|
40
|
+
if loption=~/no-(\w.*)$/
|
41
|
+
loption = $1
|
42
|
+
if value
|
43
|
+
raise UsageError, ["no-key should not have value: no-#{loption}=#{value}", obj]
|
44
|
+
end
|
45
|
+
value = false
|
46
|
+
end
|
47
|
+
if value.nil?
|
48
|
+
value = true
|
49
|
+
block.call loption, value
|
50
|
+
else
|
51
|
+
block.call loption, self.to_value(value)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
# These are single character options...
|
55
|
+
option.each_char do |c|
|
56
|
+
block.call c, true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# HelpException is a type of UsageException, where the
|
3
|
+
# user asks for help in the command line options. The
|
4
|
+
# raise in a class method is as follows:
|
5
|
+
# raise HelpException, self
|
6
|
+
# The object that raised the exception will be available
|
7
|
+
# as:
|
8
|
+
# $!.obj
|
9
|
+
# The message will be the help text:
|
10
|
+
# $!.message == $!.obj.help # => true
|
11
|
+
class HelpException < UsageException
|
12
|
+
def initialize(help_parser)
|
13
|
+
super([help_parser.help, help_parser])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,285 +1,128 @@
|
|
1
1
|
module HELP_PARSER
|
2
|
+
class HelpParser < Hash
|
3
|
+
include Errors
|
4
|
+
extend Functions
|
2
5
|
|
3
|
-
|
4
|
-
|
5
|
-
# The raise in a class method is as follows:
|
6
|
-
# raise UsageError, [message, self]
|
7
|
-
# The object that raised the error will be available as:
|
8
|
-
# $!.obj
|
9
|
-
class UsageError < StandardError
|
10
|
-
attr_accessor :obj
|
11
|
-
def initialize(array)
|
12
|
-
self.obj = array.pop
|
13
|
-
msg = array.pop
|
14
|
-
super(msg)
|
6
|
+
def parse(&block)
|
7
|
+
HelpParser.parse(@argv, self, &block)
|
15
8
|
end
|
16
|
-
end
|
17
|
-
# **ImplementationError** is an error due to a
|
18
|
-
# inconsistent help text. The raise in a class method is
|
19
|
-
# as follows:
|
20
|
-
# raise ImplementationError, [message, self]
|
21
|
-
# The object that raised the error will be available as:
|
22
|
-
# $!.obj
|
23
|
-
class ImplementationError < StandardError
|
24
|
-
attr_accessor :obj
|
25
|
-
def initialize(array)
|
26
|
-
self.obj = array.pop
|
27
|
-
msg = array.pop
|
28
|
-
super(msg)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# UsageException is an actual exception to normal flow.
|
33
|
-
# For example, when a user asks for help or version
|
34
|
-
# number in the command line options. The raise in a
|
35
|
-
# class method is as follows:
|
36
|
-
# raise UsageException, [message, self]
|
37
|
-
# The object that raised the exception will be available
|
38
|
-
# as:
|
39
|
-
# $!.obj
|
40
|
-
class UsageException < Exception
|
41
|
-
attr_accessor :obj
|
42
|
-
def initialize(array)
|
43
|
-
self.obj = array.pop
|
44
|
-
msg = array.pop
|
45
|
-
super(msg)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# HelpException is a type of UsageException, where the
|
50
|
-
# user asks for help in the command line options. The
|
51
|
-
# raise in a class method is as follows:
|
52
|
-
# raise HelpException, self
|
53
|
-
# The object that raised the exception will be available
|
54
|
-
# as:
|
55
|
-
# $!.obj
|
56
|
-
# The message will be the help text:
|
57
|
-
# $!.message == $!.obj.help # => true
|
58
|
-
class HelpException < UsageException
|
59
|
-
def initialize(help_parser)
|
60
|
-
super([help_parser.help, help_parser])
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# VersionException is a type of UsageException, where the
|
65
|
-
# user asks for version in the command line options. The
|
66
|
-
# raise in a class method is as follows:
|
67
|
-
# raise VersionException, self
|
68
|
-
# The object that raised the exception will be available
|
69
|
-
# as:
|
70
|
-
# $!.obj
|
71
|
-
# The message will be the version text:
|
72
|
-
# $!.message == $!.obj.version # => true
|
73
|
-
class VersionException < UsageException
|
74
|
-
def initialize(help_parser)
|
75
|
-
super([help_parser.version, help_parser])
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
module Errors
|
80
|
-
# HelpParser#usage_error will have make the HelpParser
|
81
|
-
# object raise a UsageError error with the given message.
|
82
|
-
def usage_error(msg)
|
83
|
-
raise UsageError, [msg, self]
|
84
|
-
end
|
85
|
-
|
86
|
-
# HelpParser#implementation_error will have make the
|
87
|
-
# HelpParser object raise a UsageError error with the
|
88
|
-
# given message.
|
89
|
-
def implementation_error(msg)
|
90
|
-
raise ImplementationError, [msg, self]
|
91
|
-
end
|
92
|
-
end
|
93
9
|
|
94
|
-
class HelpParser < Hash
|
95
|
-
include Errors
|
96
10
|
|
97
|
-
|
98
|
-
|
11
|
+
# HelpParser.new(version, help, argv=ARGV, dict={})
|
12
|
+
# Not necessarily in that order, see the code.
|
13
|
+
attr_reader :version, :help, :dict
|
14
|
+
def initialize(*parameters)
|
15
|
+
super()
|
99
16
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
17
|
+
# Figure out what parameters you were given...
|
18
|
+
@argv = parameters.detect{|parameter| parameter.class == Array} || ARGV
|
19
|
+
@dict = parameters.detect{|parameter| parameter.class == Hash } || {}
|
20
|
+
parameters = parameters.select{|parameter| parameter.class == String}
|
21
|
+
@version = parameters.shift
|
22
|
+
@help = parameters.pop
|
23
|
+
|
24
|
+
raise "Need help" unless @help
|
25
|
+
raise "Need version" unless @version
|
26
|
+
|
27
|
+
# We ensure the following two mappings...
|
28
|
+
@dict[:help] = :h
|
29
|
+
@dict[:version] = :v
|
30
|
+
|
31
|
+
# Using the help for the options definition
|
32
|
+
@help.split("\n").select{|l|
|
33
|
+
(l=~/^\s*-/)
|
34
|
+
}.map{|l|
|
35
|
+
l.strip.split(/[,\s]+/)[0..1].select{|o|
|
36
|
+
o[0]=='-'
|
37
|
+
}.map{|o|
|
38
|
+
HelpParser.str2sym o.sub(/--?/,'').sub(/=.*$/,'')
|
39
|
+
}.reverse
|
40
|
+
}.each do |k,v|
|
41
|
+
unless @dict[k].nil?
|
42
|
+
# This is an implementation error. The help text is inconsistent.
|
43
|
+
# Note that we may have been given @dict, and we're verifying the help.
|
44
|
+
implementation_error "#{k} redefinition from #{@dict[k]} to #{v}." unless @dict[k]==v
|
112
45
|
end
|
113
|
-
|
46
|
+
@dict[k]=v
|
114
47
|
end
|
115
|
-
end
|
116
|
-
extend Private
|
117
48
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
# HelpParser#parse parses the @argv for command line
|
129
|
-
# options, shifting them out, and passes on the key-value
|
130
|
-
# pairs to the block. The keys are translated to their
|
131
|
-
# short version if available, and the values are converted
|
132
|
-
# to their best interpreted form as per Funtion.to_value.
|
133
|
-
# Furthermore, no-key values are negated.
|
134
|
-
def parse(argv, obj, &block)
|
135
|
-
while argv[0] and argv[0][0]=='-'
|
136
|
-
option = argv.shift[1..-1]
|
137
|
-
if option[0]=='-'
|
138
|
-
loption, value = option[1..-1].split('=', 2)
|
139
|
-
if loption=~/no-(\w.*)$/
|
140
|
-
loption = $1
|
141
|
-
if value
|
142
|
-
raise UsageError, ["no-key should not have value: no-#{loption}=#{value}", obj]
|
143
|
-
end
|
144
|
-
value = false
|
145
|
-
end
|
146
|
-
if value.nil?
|
147
|
-
value = true
|
148
|
-
block.call loption, value
|
149
|
-
else
|
150
|
-
block.call loption, Function.to_value(value)
|
49
|
+
# Values must be terminal states, that is for example:
|
50
|
+
# if :version => :v, then :v => nil.
|
51
|
+
terminals = []
|
52
|
+
@dict.each do |k,v|
|
53
|
+
next if v.nil?
|
54
|
+
if @dict.has_key?(v)
|
55
|
+
unless @dict[v].nil?
|
56
|
+
implementation_error "Expected terminal #{v}: #{k} => #{v} => #{@dict[v]}"
|
151
57
|
end
|
152
58
|
else
|
153
|
-
|
154
|
-
option.each_char do |c|
|
155
|
-
block.call c, true
|
156
|
-
end
|
59
|
+
terminals.push(v)
|
157
60
|
end
|
158
61
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
def initialize(*parameters)
|
172
|
-
super()
|
173
|
-
|
174
|
-
# Figure out what parameters you were given...
|
175
|
-
@argv = parameters.detect{|parameter| parameter.class == Array} || ARGV
|
176
|
-
@dict = parameters.detect{|parameter| parameter.class == Hash } || {}
|
177
|
-
parameters = parameters.select{|parameter| parameter.class == String}
|
178
|
-
@version = parameters.shift
|
179
|
-
@help = parameters.pop
|
180
|
-
|
181
|
-
raise "Need help" unless @help
|
182
|
-
raise "Need version" unless @version
|
183
|
-
|
184
|
-
# We ensure the following two mappings...
|
185
|
-
@dict[:help] = :h
|
186
|
-
@dict[:version] = :v
|
187
|
-
|
188
|
-
# Using the help for the options definition
|
189
|
-
@help.split("\n").select{|l|
|
190
|
-
(l=~/^\s*-/)
|
191
|
-
}.map{|l|
|
192
|
-
l.strip.split(/[,\s]+/)[0..1].select{|o|
|
193
|
-
o[0]=='-'
|
194
|
-
}.map{|o|
|
195
|
-
HelpParser.str2sym o.sub(/--?/,'').sub(/=.*$/,'')
|
196
|
-
}.reverse
|
197
|
-
}.each do |k,v|
|
198
|
-
unless @dict[k].nil?
|
199
|
-
# This is an implementation error. The help text is inconsistent.
|
200
|
-
# Note that we may have been given @dict, and we're verifying the help.
|
201
|
-
implementation_error "#{k} redefinition from #{@dict[k]} to #{v}." unless @dict[k]==v
|
62
|
+
terminals.each{|v| @dict[v] = nil}
|
63
|
+
|
64
|
+
# Parsing command line options
|
65
|
+
parse do |opt, value|
|
66
|
+
key = HelpParser.str2sym opt
|
67
|
+
# Translate key to the terminal key.
|
68
|
+
key = @dict[key] unless @dict[key].nil?
|
69
|
+
# Ensure user only uses the defined keys.
|
70
|
+
usage_error "not a valid option: #{opt}" unless @dict.has_key?(key)
|
71
|
+
# As we parse ARGV, we should only be setting keys once.
|
72
|
+
usage_error "duplicate command line option: #{opt}" if self.has_key?(key)
|
73
|
+
self[key] = value
|
202
74
|
end
|
203
|
-
@dict[k]=v
|
204
|
-
end
|
205
75
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
76
|
+
# The parse takes all options to its terminal value.
|
77
|
+
# Now set the synonims...
|
78
|
+
@dict.each do |synonim, terminal|
|
79
|
+
next if terminal.nil?
|
80
|
+
if self.has_key?(terminal)
|
81
|
+
# I did not mean for the synonyms to have been set yet, so if I do,
|
82
|
+
# I have a bug somewhere.
|
83
|
+
raise "unexpected key overwrite" if self.has_key?(synonim)
|
84
|
+
self[synonim] = self[terminal]
|
214
85
|
end
|
215
|
-
else
|
216
|
-
terminals.push(v)
|
217
86
|
end
|
218
|
-
end
|
219
|
-
terminals.each{|v| @dict[v] = nil}
|
220
87
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
# Translate key to the terminal key.
|
225
|
-
key = @dict[key] unless @dict[key].nil?
|
226
|
-
# Ensure user only uses the defined keys.
|
227
|
-
usage_error "not a valid option: #{opt}" unless @dict.has_key?(key)
|
228
|
-
# As we parse ARGV, we should only be setting keys once.
|
229
|
-
usage_error "duplicate command line option: #{opt}" if self.has_key?(key)
|
230
|
-
self[key] = value
|
88
|
+
# Did the user ask for help or version?
|
89
|
+
raise HelpException, self if self[:h]==true
|
90
|
+
raise VersionException, self if self[:v]==true
|
231
91
|
end
|
232
92
|
|
233
|
-
#
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
end
|
93
|
+
# HelpParser#defaults is a helper method to []
|
94
|
+
def defaults(symbol, default1, default2=default1)
|
95
|
+
type = (default2 || default1).class
|
96
|
+
a = self[symbol]
|
97
|
+
value = (a.nil?)? default1 : a
|
98
|
+
value = default2 if value==true
|
99
|
+
# !value is true if value is false or nil.
|
100
|
+
usage_error "type error: #{symbol} needs to be #{type}" unless !value or value.class == type
|
101
|
+
return value
|
243
102
|
end
|
244
103
|
|
245
|
-
#
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
# HelpParser#defaults is a helper method to []
|
251
|
-
def defaults(symbol, default1, default2=default1)
|
252
|
-
type = (default2 || default1).class
|
253
|
-
a = self[symbol]
|
254
|
-
value = (a.nil?)? default1 : a
|
255
|
-
value = default2 if value==true
|
256
|
-
# !value is true if value is false or nil.
|
257
|
-
usage_error "type error: #{symbol} needs to be #{type}" unless !value or value.class == type
|
258
|
-
return value
|
259
|
-
end
|
260
|
-
|
261
|
-
# HelpParser#defaults! is used to replace value with a
|
262
|
-
# default in the hash, self.
|
263
|
-
def defaults!(symbol, default1, default2)
|
264
|
-
self[symbol] = defaults(symbol, default1, default2)
|
265
|
-
end
|
104
|
+
# HelpParser#defaults! is used to replace value with a
|
105
|
+
# default in the hash, self.
|
106
|
+
def defaults!(symbol, default1, default2)
|
107
|
+
self[symbol] = defaults(symbol, default1, default2)
|
108
|
+
end
|
266
109
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
110
|
+
# HelpParser#[k, default1=nil, default2=nil]
|
111
|
+
# Basically, for #[k, default1, default2]:
|
112
|
+
# value = help_parser[k]
|
113
|
+
# case value
|
114
|
+
# when nil then default1
|
115
|
+
# when true then default2
|
116
|
+
# else value
|
117
|
+
# end
|
118
|
+
# For #[k, default1]:
|
119
|
+
# value = help_parser[k] || default1
|
120
|
+
# For #[k]:
|
121
|
+
# help_parser[k]
|
122
|
+
# Raises a UsageError if the value is not of the expected
|
123
|
+
# type as given by the last default.
|
124
|
+
def [](k, *defaults12)
|
125
|
+
(defaults12.length==0)? super(k) : defaults(k, *defaults12)
|
126
|
+
end
|
283
127
|
end
|
284
128
|
end
|
285
|
-
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# **ImplementationError** is an error due to a
|
3
|
+
# inconsistent help text. The raise in a class method is
|
4
|
+
# as follows:
|
5
|
+
# raise ImplementationError, [message, self]
|
6
|
+
# The object that raised the error will be available as:
|
7
|
+
# $!.obj
|
8
|
+
class ImplementationError < StandardError
|
9
|
+
attr_accessor :obj
|
10
|
+
def initialize(array)
|
11
|
+
self.obj = array.pop
|
12
|
+
msg = array.pop
|
13
|
+
super(msg)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# **UsageError** is an error when the user passed command
|
3
|
+
# line options that are inconsistent with expectations.
|
4
|
+
# The raise in a class method is as follows:
|
5
|
+
# raise UsageError, [message, self]
|
6
|
+
# The object that raised the error will be available as:
|
7
|
+
# $!.obj
|
8
|
+
class UsageError < StandardError
|
9
|
+
attr_accessor :obj
|
10
|
+
def initialize(array)
|
11
|
+
self.obj = array.pop
|
12
|
+
msg = array.pop
|
13
|
+
super(msg)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# UsageException is an actual exception to normal flow.
|
3
|
+
# For example, when a user asks for help or version
|
4
|
+
# number in the command line options. The raise in a
|
5
|
+
# class method is as follows:
|
6
|
+
# raise UsageException, [message, self]
|
7
|
+
# The object that raised the exception will be available
|
8
|
+
# as:
|
9
|
+
# $!.obj
|
10
|
+
class UsageException < Exception
|
11
|
+
attr_accessor :obj
|
12
|
+
def initialize(array)
|
13
|
+
self.obj = array.pop
|
14
|
+
msg = array.pop
|
15
|
+
super(msg)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/help_parser/version.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# VersionException is a type of UsageException, where the
|
3
|
+
# user asks for version in the command line options. The
|
4
|
+
# raise in a class method is as follows:
|
5
|
+
# raise VersionException, self
|
6
|
+
# The object that raised the exception will be available
|
7
|
+
# as:
|
8
|
+
# $!.obj
|
9
|
+
# The message will be the version text:
|
10
|
+
# $!.message == $!.obj.version # => true
|
11
|
+
class VersionException < UsageException
|
12
|
+
def initialize(help_parser)
|
13
|
+
super([help_parser.version, help_parser])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/test/help_parser.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require 'help_parser
|
2
|
+
require 'help_parser'
|
3
3
|
|
4
4
|
class Test_HELP_PARSER_HelpParser < Test::Unit::TestCase
|
5
5
|
include HELP_PARSER
|
@@ -142,7 +142,7 @@ class Test_HELP_PARSER_HelpParser < Test::Unit::TestCase
|
|
142
142
|
|
143
143
|
def test_008_to_value
|
144
144
|
[['1', Integer], ['1.0', Float], ['One', String], ['1,2.0,Three', Array]].each do |string, type|
|
145
|
-
value = HelpParser
|
145
|
+
value = HelpParser.to_value(string)
|
146
146
|
assert( value.kind_of?(type) )
|
147
147
|
end
|
148
148
|
end
|
metadata
CHANGED
@@ -1,15 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: help_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- CarlosJHR64
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-12-
|
12
|
-
dependencies:
|
11
|
+
date: 2013-12-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rainbow
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.1'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.1.4
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.1'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.1.4
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: test-unit
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.5'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 2.5.5
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '2.5'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 2.5.5
|
13
53
|
description: |
|
14
54
|
_HelpParser_ - Parses your help text to define your command line options.
|
15
55
|
email: carlosjhr64@gmail.com
|
@@ -21,7 +61,6 @@ files:
|
|
21
61
|
- History.txt
|
22
62
|
- Manifest.txt
|
23
63
|
- README.rdoc
|
24
|
-
- Rakefile
|
25
64
|
- TODO.txt
|
26
65
|
- examples/command_suite
|
27
66
|
- examples/implementation_error_duplicate_key
|
@@ -34,12 +73,15 @@ files:
|
|
34
73
|
- features/suite.feature
|
35
74
|
- help_parser.gemspec
|
36
75
|
- lib/help_parser.rb
|
76
|
+
- lib/help_parser/errors.rb
|
77
|
+
- lib/help_parser/functions.rb
|
78
|
+
- lib/help_parser/help_exception.rb
|
37
79
|
- lib/help_parser/help_parser.rb
|
80
|
+
- lib/help_parser/implementation_error.rb
|
81
|
+
- lib/help_parser/usage_error.rb
|
82
|
+
- lib/help_parser/usage_exception.rb
|
38
83
|
- lib/help_parser/version.rb
|
39
|
-
-
|
40
|
-
- tasks/manifester.rb
|
41
|
-
- tasks/syntaxer.rb
|
42
|
-
- tasks/unit_tests.rb
|
84
|
+
- lib/help_parser/version_exception.rb
|
43
85
|
- test/help_parser.rb
|
44
86
|
homepage: https://github.com/carlosjhr64/help_parser
|
45
87
|
licenses:
|
@@ -61,7 +103,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
103
|
- - ">="
|
62
104
|
- !ruby/object:Gem::Version
|
63
105
|
version: '0'
|
64
|
-
requirements:
|
106
|
+
requirements:
|
107
|
+
- requires json in development
|
108
|
+
- requires open3 in development
|
65
109
|
rubyforge_project:
|
66
110
|
rubygems_version: 2.0.3
|
67
111
|
signing_key:
|
data/Rakefile
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'find'
|
2
|
-
|
3
|
-
module RakingTasks
|
4
|
-
def RakingTasks.git_tag_list
|
5
|
-
`git tag --list`.strip.split("\n")
|
6
|
-
end
|
7
|
-
|
8
|
-
def RakingTasks.git_status_porcelain
|
9
|
-
`git status --porcelain`.strip
|
10
|
-
end
|
11
|
-
|
12
|
-
def RakingTasks.gemspec_files
|
13
|
-
`ls ./*.gemspec 2> /dev/null`.strip.split("\n")
|
14
|
-
end
|
15
|
-
|
16
|
-
def RakingTasks.uniq_gemspec_file
|
17
|
-
gemspecs = RakingTasks.gemspec_files
|
18
|
-
raise "Gemspec file not found" if gemspecs.length == 0
|
19
|
-
raise "Mutiple gemspec files found" if gemspecs.length > 1
|
20
|
-
gemspecs.first
|
21
|
-
end
|
22
|
-
|
23
|
-
def RakingTasks.pkg_gem_files
|
24
|
-
`ls ./pkg/*.gem 2> /dev/null`.strip.split("\n")
|
25
|
-
end
|
26
|
-
|
27
|
-
def RakingTasks.gem_files
|
28
|
-
`ls ./*.gem 2> /dev/null`.strip.split("\n")
|
29
|
-
end
|
30
|
-
|
31
|
-
def RakingTasks.uniq_gem_file
|
32
|
-
gems = RakingTasks.gem_files
|
33
|
-
raise "Gem file not found" if gems.length == 0
|
34
|
-
raise "Multiple gem files found" if gems.length > 1
|
35
|
-
gems.first
|
36
|
-
end
|
37
|
-
|
38
|
-
def RakingTasks.gem_build
|
39
|
-
raise "Git status not clear" unless RakingTasks.git_status_porcelain.length == 0
|
40
|
-
gems = RakingTasks.gem_files
|
41
|
-
raise "Found gem files: #{gems.join(',')}" unless gems.length == 0
|
42
|
-
gemspec = RakingTasks.uniq_gemspec_file
|
43
|
-
system("gem build #{gemspec}")
|
44
|
-
end
|
45
|
-
|
46
|
-
def RakingTasks.load_existing_tasks
|
47
|
-
if Dir.exist?('./tasks')
|
48
|
-
Find.find('./tasks') do |fn|
|
49
|
-
require fn if fn=~/\.rb/
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
RakingTasks.load_existing_tasks
|
55
|
-
|
56
|
-
desc 'By default, run git status'
|
57
|
-
task :default do
|
58
|
-
system('git status')
|
59
|
-
end
|
60
|
-
|
61
|
-
desc 'Cucumbers tests'
|
62
|
-
task :cucumber do
|
63
|
-
system('cucumber -f progress')
|
64
|
-
end
|
65
|
-
|
66
|
-
desc 'Runs all tests'
|
67
|
-
task :'test-all' => [:syntaxer, :'unit-tests', :cucumber]
|
68
|
-
|
69
|
-
desc 'Builds pre-release gem for testing, not published.'
|
70
|
-
task :gem_build do
|
71
|
-
RakingTasks.gem_build
|
72
|
-
end
|
73
|
-
|
74
|
-
desc 'pushes to rubygems and git'
|
75
|
-
task :publish, :version do |t, args|
|
76
|
-
version = args[:version]
|
77
|
-
tags = RakingTasks.git_tag_list
|
78
|
-
raise "#{version} in git tag list" if tags.include?(version)
|
79
|
-
RakingTasks.gem_build
|
80
|
-
gem = File.basename RakingTasks.uniq_gem_file
|
81
|
-
raise "#{version} did not match gem file" unless gem.include?(version)
|
82
|
-
pkgem = File.join('pkg', gem)
|
83
|
-
raise "pkg/#{gem} exists!?" if File.exist? pkgem
|
84
|
-
if system("gem push #{gem}")
|
85
|
-
File.rename(gem, pkgem)
|
86
|
-
File.open('./History.txt', 'a'){|fh| fh.puts "=== #{version} / #{Time.now}"}
|
87
|
-
File.open('./History.txt', 'a'){|fh| fh.puts `md5sum #{pkgem}`}
|
88
|
-
system("git commit -m '#{version}' ./History.txt")
|
89
|
-
system("git tag '#{version}'")
|
90
|
-
system('git push')
|
91
|
-
else
|
92
|
-
File.unlink(gem)
|
93
|
-
end
|
94
|
-
end
|
data/tasks/gemspecker.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'date'
|
3
|
-
|
4
|
-
module Gemspecker
|
5
|
-
def self.task
|
6
|
-
|
7
|
-
name = File.basename(Dir.getwd)
|
8
|
-
version = File.read("lib/#{name}/version.rb").match(/\d+\.\d+\.\d+/)[0]
|
9
|
-
date = Date.today.to_s
|
10
|
-
author = `git config user.name`.strip
|
11
|
-
email = `git config user.email`.strip
|
12
|
-
# get the first readme, preferably rdoc.
|
13
|
-
readme = `ls README.rdoc README.txt README* 2> /dev/null`.split.first.strip
|
14
|
-
description = File.read(readme).match(/DESCRIPTION:([^=]*)/i)[1].strip
|
15
|
-
summary = description.split(/\n\n/).first
|
16
|
-
|
17
|
-
# ./name.gemspec
|
18
|
-
File.open("./#{name}.gemspec", 'w') do |gemspec|
|
19
|
-
|
20
|
-
### Gem Specification ####
|
21
|
-
gemspec.puts <<EOT
|
22
|
-
Gem::Specification.new do |s|
|
23
|
-
|
24
|
-
s.name = '#{name}'
|
25
|
-
s.version = '#{version}'
|
26
|
-
|
27
|
-
s.homepage = 'https://github.com/#{author.downcase}/#{name}'
|
28
|
-
|
29
|
-
s.author = '#{author}'
|
30
|
-
s.email = '#{email}'
|
31
|
-
|
32
|
-
s.date = '#{date}'
|
33
|
-
s.licenses = ['MIT']
|
34
|
-
|
35
|
-
s.description = <<DESCRIPTION
|
36
|
-
#{description}
|
37
|
-
DESCRIPTION
|
38
|
-
|
39
|
-
s.summary = <<SUMMARY
|
40
|
-
#{summary}
|
41
|
-
SUMMARY
|
42
|
-
|
43
|
-
s.extra_rdoc_files = ['#{readme}']
|
44
|
-
s.rdoc_options = ["--main", "#{readme}"]
|
45
|
-
|
46
|
-
s.require_paths = ["lib"]
|
47
|
-
s.files = %w(
|
48
|
-
#{`git ls-files`})
|
49
|
-
|
50
|
-
end
|
51
|
-
EOT
|
52
|
-
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
desc "Create/Update gemspec"
|
58
|
-
task :gemspecker do
|
59
|
-
Gemspecker.task
|
60
|
-
end
|
data/tasks/manifester.rb
DELETED
data/tasks/syntaxer.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'find'
|
3
|
-
require 'open3'
|
4
|
-
require 'rainbow'
|
5
|
-
|
6
|
-
module Syntaxer
|
7
|
-
def self.task
|
8
|
-
count = 0
|
9
|
-
Find.find('.') do |fn|
|
10
|
-
if fn=~/\.rb$/
|
11
|
-
stdout, stderr, process = Open3.capture3("ruby -c #{fn}")
|
12
|
-
unless process.exitstatus == 0
|
13
|
-
count += 1
|
14
|
-
puts stderr.chomp.color(:red)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
puts "No syntax errors found.".color(:green) if count == 0
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
desc "Checks *.rb's syntax"
|
23
|
-
task :syntaxer do
|
24
|
-
Syntaxer.task
|
25
|
-
end
|
data/tasks/unit_tests.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'find'
|
3
|
-
|
4
|
-
module UnitTests
|
5
|
-
def self.task
|
6
|
-
count = 0
|
7
|
-
Find.find('./test') do |fn|
|
8
|
-
if fn=~/\.rb$/
|
9
|
-
system("ruby -I ./lib #{fn} --verbose=progress")
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
desc "Runs unit tests"
|
16
|
-
task :'unit-tests' do
|
17
|
-
UnitTests.task
|
18
|
-
end
|