help_parser 1.3.0 → 2.0.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/README.rdoc +11 -0
- data/lib/help_parser.rb +7 -8
- data/lib/help_parser/errors.rb +12 -13
- data/lib/help_parser/exceptions.rb +25 -0
- data/lib/help_parser/help_parser.rb +75 -40
- data/lib/help_parser/refinements.rb +40 -0
- data/lib/help_parser/version.rb +1 -1
- metadata +6 -9
- data/lib/help_parser/functions.rb +0 -62
- data/lib/help_parser/help_exception.rb +0 -16
- data/lib/help_parser/implementation_error.rb +0 -16
- data/lib/help_parser/usage_error.rb +0 -16
- data/lib/help_parser/usage_exception.rb +0 -18
- data/lib/help_parser/version_exception.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e34375237fe8e17187ef472cdec33cecb71a604
|
4
|
+
data.tar.gz: ddb37f1e37e3900494b3099ad8d944cfbdb5847e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4eaf7e06d366440c40e7519656e1dc05a04b4efde4af03e691dcbbe693ba177165622dac7cb608c515ce7eece9ab9f9fed0b96c9c45f7000460a4d2c168b7ea4
|
7
|
+
data.tar.gz: 17a48d312dd790501189f5ab05a94f6c55d59d8aa613988223ce464415cb50ff05aae6eddccf1119d57772fff1ab35507cdff55315f797e3d5c2c65d7f546760
|
data/README.rdoc
CHANGED
@@ -24,11 +24,22 @@ HelpParser - Parses your help text to define your command line options.
|
|
24
24
|
-v --version Show the version and exit
|
25
25
|
-q --quiet Be quiet
|
26
26
|
-V --verbose Say more about whats going on
|
27
|
+
--value=5.0 Pass values, provide default.
|
27
28
|
HELP
|
28
29
|
begin
|
29
30
|
OPTIONS = HelpParser.new('1.0.0', HELP)
|
30
31
|
puts "Tracing..." unless OPTIONS[:quiet]
|
31
32
|
puts "More tracing..." if OPTIONS[:V] # verbose
|
33
|
+
if value = OPTIONS[:value]
|
34
|
+
if value == 5.0
|
35
|
+
# --value by itself gives the give default.
|
36
|
+
puts "You gave the default value of 5.0."
|
37
|
+
else
|
38
|
+
puts "You gave different value #{value}."
|
39
|
+
end
|
40
|
+
else
|
41
|
+
puts "You did not give me a value."
|
42
|
+
end
|
32
43
|
# mycmdapp code continues...
|
33
44
|
# ...
|
34
45
|
rescue UsageException
|
data/lib/help_parser.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'help_parser/version
|
2
|
-
require 'help_parser/
|
3
|
-
require 'help_parser/help_exception'
|
4
|
-
require 'help_parser/version_exception'
|
5
|
-
require 'help_parser/implementation_error'
|
6
|
-
require 'help_parser/usage_error'
|
1
|
+
require 'help_parser/version'
|
2
|
+
require 'help_parser/exceptions'
|
7
3
|
require 'help_parser/errors'
|
8
|
-
require 'help_parser/
|
9
|
-
require 'help_parser/help_parser
|
4
|
+
require 'help_parser/refinements'
|
5
|
+
require 'help_parser/help_parser'
|
6
|
+
|
7
|
+
# Requires:
|
8
|
+
#`ruby`
|
data/lib/help_parser/errors.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
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
2
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
raise ImplementationError, [msg, self]
|
15
|
-
end
|
3
|
+
# ImplementationError is an error due to a
|
4
|
+
# inconsistent help text. The raise is as follows:
|
5
|
+
# raise ImplementationError, message
|
6
|
+
class ImplementationError < StandardError
|
16
7
|
end
|
8
|
+
|
9
|
+
# UsageError is an error when the user passed command
|
10
|
+
# line options that are inconsistent with expectations.
|
11
|
+
# The raise is as follows:
|
12
|
+
# raise UsageError, message
|
13
|
+
class UsageError < StandardError
|
14
|
+
end
|
15
|
+
|
17
16
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
|
3
|
+
# UsageException is an actual exception to normal flow.
|
4
|
+
# For example, when a user asks for help or version
|
5
|
+
# number in the command line options.
|
6
|
+
# The raise is as follows:
|
7
|
+
# raise UsageException, message
|
8
|
+
class UsageException < Exception
|
9
|
+
end
|
10
|
+
|
11
|
+
# HelpException is a type of UsageException, where the
|
12
|
+
# user asks for help in the command line options.
|
13
|
+
# The raise is as follows:
|
14
|
+
# raise HelpException, help_message
|
15
|
+
class HelpException < UsageException
|
16
|
+
end
|
17
|
+
|
18
|
+
# VersionException is a type of UsageException, where the
|
19
|
+
# user asks for version in the command line options.
|
20
|
+
# The raise is as follows:
|
21
|
+
# raise VersionException, version_message
|
22
|
+
class VersionException < UsageException
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -1,93 +1,126 @@
|
|
1
1
|
module HELP_PARSER
|
2
2
|
class HelpParser < Hash
|
3
|
-
|
4
|
-
extend Functions
|
3
|
+
using HELP_PARSER
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
# HelpParser.parse parses the argv for command line
|
6
|
+
# options, shifting them out, and passes on the key-value
|
7
|
+
# pairs to the block. no-key values are negated.
|
8
|
+
def self.parse(argv, &block)
|
9
|
+
while argv[0] and argv[0][0]=='-'
|
10
|
+
option = argv.shift[1..-1]
|
11
|
+
if option[0]=='-'
|
12
|
+
loption, value = option[1..-1].split('=', 2)
|
13
|
+
if loption[0..2]=='no-'
|
14
|
+
loption = loption[3..-1]
|
15
|
+
if value
|
16
|
+
raise UsageError, "no-key should not have value: no-#{loption}=#{value}"
|
17
|
+
end
|
18
|
+
value = :F
|
19
|
+
end
|
20
|
+
block.call loption, value
|
21
|
+
else
|
22
|
+
# These are single character options...
|
23
|
+
option.each_char do |c|
|
24
|
+
block.call c, :T
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
8
28
|
end
|
9
29
|
|
10
|
-
|
11
30
|
# HelpParser.new(version, help, argv=ARGV, dict={})
|
12
31
|
# Not necessarily in that order, see the code.
|
13
|
-
attr_reader :version, :help, :dict
|
14
32
|
def initialize(*parameters)
|
15
33
|
super()
|
16
34
|
|
17
35
|
# Figure out what parameters you were given...
|
18
|
-
|
19
|
-
|
36
|
+
argv = parameters.detect{|parameter| parameter.class == Array} || ARGV
|
37
|
+
dict = parameters.detect{|parameter| parameter.class == Hash } || {}
|
20
38
|
parameters = parameters.select{|parameter| parameter.class == String}
|
21
|
-
|
22
|
-
|
39
|
+
version = parameters.shift
|
40
|
+
help = parameters.pop
|
41
|
+
preferred = {}
|
23
42
|
|
24
|
-
raise "Need help" unless
|
25
|
-
raise "Need version" unless
|
43
|
+
raise "Need help" unless help
|
44
|
+
raise "Need version" unless version
|
26
45
|
|
27
|
-
# We ensure the following
|
28
|
-
|
29
|
-
|
46
|
+
# We ensure the following mappings...
|
47
|
+
dict[:help], preferred[:help] = :h, :T
|
48
|
+
dict[:version], preferred[:version] = :v, :T
|
30
49
|
|
31
50
|
# Using the help for the options definition
|
32
|
-
|
51
|
+
help.split("\n").select{|l|
|
33
52
|
(l=~/^\s*-/)
|
34
53
|
}.map{|l|
|
35
|
-
l.strip.split(
|
54
|
+
l.strip.split(/\s+/)[0..1].select{|o|
|
36
55
|
o[0]=='-'
|
37
56
|
}.map{|o|
|
38
|
-
|
57
|
+
v = :T
|
58
|
+
if i = o.index('=')
|
59
|
+
v = o[i+1..-1]
|
60
|
+
o = o[0...i]
|
61
|
+
end
|
62
|
+
o = o.to_key
|
63
|
+
preferred[o] = v
|
64
|
+
o
|
39
65
|
}.reverse
|
40
66
|
}.each do |k,v|
|
41
|
-
unless
|
67
|
+
unless dict[k].nil?
|
42
68
|
# This is an implementation error. The help text is inconsistent.
|
43
|
-
# Note that we may have been given
|
44
|
-
|
69
|
+
# Note that we may have been given dict, and we're verifying the help.
|
70
|
+
unless dict[k]==v
|
71
|
+
raise ImplementationError, "#{k} redefinition from #{dict[k]} to #{v}."
|
72
|
+
end
|
45
73
|
end
|
46
|
-
|
74
|
+
dict[k]=v
|
47
75
|
end
|
48
76
|
|
49
77
|
# Values must be terminal states, that is for example:
|
50
78
|
# if :version => :v, then :v => nil.
|
51
79
|
terminals = []
|
52
|
-
|
80
|
+
dict.each do |k,v|
|
53
81
|
next if v.nil?
|
54
|
-
if
|
55
|
-
unless
|
56
|
-
|
82
|
+
if dict.has_key?(v)
|
83
|
+
unless dict[v].nil?
|
84
|
+
raise ImplementationError, "Expected terminal #{v}: #{k} => #{v} => #{dict[v]}"
|
57
85
|
end
|
58
86
|
else
|
59
87
|
terminals.push(v)
|
60
88
|
end
|
61
89
|
end
|
62
|
-
terminals.each{|v|
|
90
|
+
terminals.each{|v| dict[v] = nil}
|
63
91
|
|
64
92
|
# Parsing command line options
|
65
|
-
parse do |opt, value|
|
66
|
-
key =
|
93
|
+
HelpParser.parse(argv) do |opt, value|
|
94
|
+
key = opt.to_key
|
95
|
+
value = preferred[key] if value.nil?
|
67
96
|
# Translate key to the terminal key.
|
68
|
-
key =
|
97
|
+
key = dict[key] unless dict[key].nil?
|
69
98
|
# Ensure user only uses the defined keys.
|
70
|
-
|
99
|
+
unless dict.has_key?(key)
|
100
|
+
raise UsageError, "Not a valid option: #{opt}"
|
101
|
+
end
|
71
102
|
# As we parse ARGV, we should only be setting keys once.
|
72
|
-
|
73
|
-
|
103
|
+
if self.has_key?(key)
|
104
|
+
raise UsageError, "Duplicate command line option: #{opt}"
|
105
|
+
end
|
106
|
+
self[key] = value.to_value
|
74
107
|
end
|
75
108
|
|
76
109
|
# The parse takes all options to its terminal value.
|
77
|
-
# Now set the
|
78
|
-
|
110
|
+
# Now set the synonyms...
|
111
|
+
dict.each do |synonym, terminal|
|
79
112
|
next if terminal.nil?
|
80
113
|
if self.has_key?(terminal)
|
81
114
|
# I did not mean for the synonyms to have been set yet, so if I do,
|
82
115
|
# I have a bug somewhere.
|
83
|
-
raise "unexpected key overwrite" if self.has_key?(
|
84
|
-
self[
|
116
|
+
raise "unexpected key overwrite" if self.has_key?(synonym)
|
117
|
+
self[synonym] = self[terminal]
|
85
118
|
end
|
86
119
|
end
|
87
120
|
|
88
121
|
# Did the user ask for help or version?
|
89
|
-
raise HelpException,
|
90
|
-
raise VersionException,
|
122
|
+
raise HelpException, help if self[:h]==true
|
123
|
+
raise VersionException, version if self[:v]==true
|
91
124
|
end
|
92
125
|
|
93
126
|
# HelpParser#defaults is a helper method to []
|
@@ -97,7 +130,9 @@ module HELP_PARSER
|
|
97
130
|
value = (a.nil?)? default1 : a
|
98
131
|
value = default2 if value==true
|
99
132
|
# !value is true if value is false or nil.
|
100
|
-
|
133
|
+
unless !value or value.class == type
|
134
|
+
raise UsageError, "Type error: #{symbol} needs to be #{type}"
|
135
|
+
end
|
101
136
|
return value
|
102
137
|
end
|
103
138
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module HELP_PARSER
|
2
|
+
# Refinements
|
3
|
+
|
4
|
+
refine Symbol do
|
5
|
+
def to_value
|
6
|
+
case self
|
7
|
+
when :T
|
8
|
+
return true
|
9
|
+
when :F
|
10
|
+
return false
|
11
|
+
end
|
12
|
+
raise "Unrecognized key: #{self}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
refine String do
|
17
|
+
def to_value
|
18
|
+
case self
|
19
|
+
when /^[-+]?\d+$/
|
20
|
+
return self.to_i
|
21
|
+
when /^[-+]?\d+\.\d+([eE][+-]?\d+)?$/
|
22
|
+
return self.to_f
|
23
|
+
when /,/
|
24
|
+
return self.split(',').map{|s| s.to_value}
|
25
|
+
else
|
26
|
+
return self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Converts String keys to Symbol.
|
31
|
+
# Symbol keys can have '-', but it's cumbersome notation:
|
32
|
+
# :"a-b"
|
33
|
+
# So I translate it to underscore:
|
34
|
+
# :a_b
|
35
|
+
def to_key
|
36
|
+
self.sub(/^--?/,'').gsub('-','_').to_sym
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
data/lib/help_parser/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: help_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.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: 2015-12-
|
11
|
+
date: 2015-12-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
HelpParser - Parses your help text to define your command line options.
|
@@ -21,14 +21,10 @@ files:
|
|
21
21
|
- README.rdoc
|
22
22
|
- lib/help_parser.rb
|
23
23
|
- lib/help_parser/errors.rb
|
24
|
-
- lib/help_parser/
|
25
|
-
- lib/help_parser/help_exception.rb
|
24
|
+
- lib/help_parser/exceptions.rb
|
26
25
|
- lib/help_parser/help_parser.rb
|
27
|
-
- lib/help_parser/
|
28
|
-
- lib/help_parser/usage_error.rb
|
29
|
-
- lib/help_parser/usage_exception.rb
|
26
|
+
- lib/help_parser/refinements.rb
|
30
27
|
- lib/help_parser/version.rb
|
31
|
-
- lib/help_parser/version_exception.rb
|
32
28
|
homepage: https://github.com/carlosjhr64/help_parser
|
33
29
|
licenses:
|
34
30
|
- MIT
|
@@ -49,7 +45,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
45
|
- - ">="
|
50
46
|
- !ruby/object:Gem::Version
|
51
47
|
version: '0'
|
52
|
-
requirements:
|
48
|
+
requirements:
|
49
|
+
- 'ruby: ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]'
|
53
50
|
rubyforge_project:
|
54
51
|
rubygems_version: 2.4.5.1
|
55
52
|
signing_key:
|
@@ -1,62 +0,0 @@
|
|
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+([eE][+-]?\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
|
@@ -1,16 +0,0 @@
|
|
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,16 +0,0 @@
|
|
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
|
@@ -1,16 +0,0 @@
|
|
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
|
@@ -1,18 +0,0 @@
|
|
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
|
@@ -1,16 +0,0 @@
|
|
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
|