micro-optparse 1.0.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +17 -2
- data/lib/micro-optparse/parser.rb +12 -12
- data/lib/micro-optparse/version.rb +1 -1
- data/spec/parser_spec.rb +117 -71
- data/spec/programs/{another_example.rb → eating.rb} +5 -3
- data/spec/programs/{empty_example.rb → empty.rb} +0 -0
- data/spec/programs/version.rb +10 -0
- metadata +11 -11
- data/spec/programs/example.rb +0 -17
data/README.md
CHANGED
@@ -65,13 +65,28 @@ The automatically generated help message looks like this:
|
|
65
65
|
-h, --help Show this message
|
66
66
|
-V, --version Print version
|
67
67
|
|
68
|
+
It doesn't stop at the command line!
|
69
|
+
------------------------------------
|
70
|
+
|
71
|
+
µ-optparse can parse any array which is formatted like ARGV, e.g. `["--severity", "4"]` is the same as typing `"--severity 4"` behind your program call.
|
72
|
+
You can even process several arrays with the same parser (see example below).
|
73
|
+
In addition, you don't need to specify all options at once, i.e. you can pass the parser around and add more options until you call the `process!`-method.
|
74
|
+
|
75
|
+
require 'rubygems' # necessary for ruby v1.8.*
|
76
|
+
require 'micro-optparse'
|
77
|
+
|
78
|
+
parser = Parser.new
|
79
|
+
parser.option :eat_snickers, "How many?", :default => 0
|
80
|
+
options1 = parser.process!(["--eat-snickers", "2"])
|
81
|
+
options2 = parser.process!(["--eat-snickers", "1"])
|
82
|
+
|
68
83
|
Where do I get µ-optparse?
|
69
84
|
--------------------------
|
70
85
|
|
71
|
-
You can either go and install the gem via `gem install micro-optparse` or grab it from [
|
86
|
+
You can either go and install the gem via `gem install micro-optparse` or grab it from [this repository](https://github.com/florianpilz/micro-optparse/blob/master/lib/micro-optparse/parser.rb) and paste it into your script.
|
72
87
|
If you choose the latter option, you may delete the `validate`-method to spare another 15 lines of code.
|
73
88
|
|
74
|
-
If you want to contribute, you can fork
|
89
|
+
If you want to contribute, you can fork this repository, make your changes and send me a pull request.
|
75
90
|
However, improvements must be one of the following:
|
76
91
|
|
77
92
|
* use fewer lines of code, without sacrificing readablity or functionality
|
@@ -3,11 +3,10 @@ require 'optparse'
|
|
3
3
|
|
4
4
|
class Parser
|
5
5
|
attr_accessor :banner, :version
|
6
|
-
|
7
6
|
def initialize
|
8
7
|
@options = []
|
9
8
|
@used_short = []
|
10
|
-
yield self
|
9
|
+
yield self if block_given?
|
11
10
|
end
|
12
11
|
|
13
12
|
def option(name, desc, settings = {})
|
@@ -37,18 +36,18 @@ class Parser
|
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
|
-
def process!
|
41
|
-
|
42
|
-
optionparser
|
39
|
+
def process!(arguments = ARGV)
|
40
|
+
@result = (@default_values || {}).clone # reset or new
|
41
|
+
@optionparser ||= OptionParser.new do |p| # prepare only once
|
43
42
|
@options.each do |o|
|
44
43
|
@used_short << short = o[2][:short] || short_from(o[0])
|
45
|
-
|
44
|
+
@result[o[0]] = o[2][:default] || false # set default
|
46
45
|
klass = o[2][:default].class == Fixnum ? Integer : o[2][:default].class
|
47
46
|
|
48
47
|
if [TrueClass, FalseClass, NilClass].include?(klass) # boolean switch
|
49
|
-
p.on("-" << short, "--[no-]" << o[0].to_s.gsub("_", "-"), o[1]) {|x|
|
48
|
+
p.on("-" << short, "--[no-]" << o[0].to_s.gsub("_", "-"), o[1]) {|x| @result[o[0]] = x}
|
50
49
|
else # argument with parameter
|
51
|
-
p.on("-" << short, "--" << o[0].to_s.gsub("_", "-") << " " << o[2][:default].to_s, klass, o[1]) {|x|
|
50
|
+
p.on("-" << short, "--" << o[0].to_s.gsub("_", "-") << " " << o[2][:default].to_s, klass, o[1]) {|x| @result[o[0]] = x}
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
@@ -56,15 +55,16 @@ class Parser
|
|
56
55
|
p.on_tail("-h", "--help", "Show this message") {puts p ; exit}
|
57
56
|
short = @used_short.include?("v") ? "-V" : "-v"
|
58
57
|
p.on_tail(short, "--version", "Print version") {puts @version ; exit} unless @version.nil?
|
58
|
+
@default_values = @result.clone # save default values to reset @result in subsequent calls
|
59
59
|
end
|
60
60
|
|
61
61
|
begin
|
62
|
-
optionparser.parse!(
|
62
|
+
@optionparser.parse!(arguments)
|
63
63
|
rescue OptionParser::ParseError => e
|
64
64
|
puts e.message ; exit(1)
|
65
65
|
end
|
66
|
-
|
67
|
-
validate(
|
68
|
-
|
66
|
+
|
67
|
+
validate(@result) if self.respond_to?("validate")
|
68
|
+
@result
|
69
69
|
end
|
70
70
|
end
|
data/spec/parser_spec.rb
CHANGED
@@ -1,9 +1,98 @@
|
|
1
1
|
require "micro-optparse"
|
2
2
|
|
3
3
|
describe Parser do
|
4
|
+
before(:all) do
|
5
|
+
@evolutionary_algorithm_parser = Parser.new do |p|
|
6
|
+
p.option :severity, "set severity", :default => 4, :value_in_set => [4,5,6,7,8]
|
7
|
+
p.option :verbose, "enable verbose output"
|
8
|
+
p.option :mutation, "set mutation", :default => "MightyMutation", :value_matches => /Mutation/
|
9
|
+
p.option :plus_selection, "use plus-selection if set", :default => true
|
10
|
+
p.option :selection, "selection used", :default => "BestSelection", :short => "l"
|
11
|
+
p.option :chance, "set mutation chance", :default => 0.8, :value_satisfies => lambda {|x| x >= 0.0 && x <= 1.0}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "parsing of default values" do
|
16
|
+
it "should assume false as default value if no default value was given" do
|
17
|
+
result = @evolutionary_algorithm_parser.process!([])
|
18
|
+
result[:verbose].should == false
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return default values if called without arguments" do
|
22
|
+
result = @evolutionary_algorithm_parser.process!([])
|
23
|
+
result[:severity].should == 4
|
24
|
+
result[:verbose].should == false
|
25
|
+
result[:mutation].should == "MightyMutation"
|
26
|
+
result[:plus_selection].should == true
|
27
|
+
result[:selection].should == "BestSelection"
|
28
|
+
result[:chance].should == 0.8
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "setting of custom values" do
|
33
|
+
it "should display overwritten values accordingly when long option names were used" do
|
34
|
+
args = ["--severity", "5", "--verbose", "--mutation", "DumbMutation",
|
35
|
+
"--no-plus-selection", "--selection", "WorstSelection", "--chance", "0.1"]
|
36
|
+
result = @evolutionary_algorithm_parser.process!(args)
|
37
|
+
result[:severity].should == 5
|
38
|
+
result[:verbose].should == true
|
39
|
+
result[:mutation].should == "DumbMutation"
|
40
|
+
result[:plus_selection].should == false
|
41
|
+
result[:selection].should == "WorstSelection"
|
42
|
+
result[:chance].should == 0.1
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should display overwritten values accordingly when the 'long=value' form was used" do
|
46
|
+
args = ["--severity=5", "--mutation=DumbMutation", "--selection=WorstSelection", "--chance=0.1"]
|
47
|
+
result = @evolutionary_algorithm_parser.process!(args)
|
48
|
+
result[:severity].should == 5
|
49
|
+
result[:mutation].should == "DumbMutation"
|
50
|
+
result[:selection].should == "WorstSelection"
|
51
|
+
result[:chance].should == 0.1
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should display overwritten values accordingly when short option names were used" do
|
55
|
+
# there is no short form to set switches to false
|
56
|
+
args = ["-s", "5", "-v", "-m", "DumbMutation", "--no-plus-selection", "-l", "WorstSelection", "-c", "0.1"]
|
57
|
+
result = @evolutionary_algorithm_parser.process!(args)
|
58
|
+
result[:severity].should == 5
|
59
|
+
result[:verbose].should == true
|
60
|
+
result[:mutation].should == "DumbMutation"
|
61
|
+
result[:plus_selection].should == false
|
62
|
+
result[:selection].should == "WorstSelection"
|
63
|
+
result[:chance].should == 0.1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "parsing of several arrays using the same parser" do
|
68
|
+
it "should not manipulate old results" do
|
69
|
+
result1 = @evolutionary_algorithm_parser.process!(["--severity=5"])
|
70
|
+
result2 = @evolutionary_algorithm_parser.process!(["--severity=6"])
|
71
|
+
result3 = @evolutionary_algorithm_parser.process!([])
|
72
|
+
|
73
|
+
result1[:severity].should == 5
|
74
|
+
result2[:severity].should == 6
|
75
|
+
result3[:severity].should == 4
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "empty parser" do
|
80
|
+
it "should be allowed to create a parser with an empty block" do
|
81
|
+
parser = Parser.new { }
|
82
|
+
parser.should_not be_nil
|
83
|
+
parser.class.should == Parser
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be allowed to create a parser without a block" do
|
87
|
+
parser = Parser.new
|
88
|
+
parser.should_not be_nil
|
89
|
+
parser.class.should == Parser
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
4
93
|
describe "help message" do
|
5
94
|
it "should show help message when called with --help or -h" do
|
6
|
-
results = [`ruby spec/programs/
|
95
|
+
results = [`ruby spec/programs/eating.rb -h`, `ruby spec/programs/eating.rb --help`]
|
7
96
|
results.each do |result|
|
8
97
|
result.should include("--help")
|
9
98
|
result.should include("Show this message")
|
@@ -13,134 +102,91 @@ describe Parser do
|
|
13
102
|
|
14
103
|
describe "banner message" do
|
15
104
|
it "should include the banner info in the help message" do
|
16
|
-
result = `ruby spec/programs/
|
105
|
+
result = `ruby spec/programs/eating.rb --help`
|
17
106
|
result.should include("This is a banner")
|
18
107
|
end
|
19
108
|
|
20
109
|
it "should include the default banner info if no banner message was set" do
|
21
|
-
result = `ruby spec/programs/
|
22
|
-
result.should include("Usage:
|
110
|
+
result = `ruby spec/programs/empty.rb --help`
|
111
|
+
result.should include("Usage: empty [options]")
|
23
112
|
end
|
24
113
|
end
|
25
114
|
|
26
115
|
describe "version information" do
|
27
116
|
it "should display the version when called with --version or -V" do
|
28
117
|
# here -V is used for version, as -v is already taken for the verbose switch
|
29
|
-
results = [`ruby spec/programs/
|
118
|
+
results = [`ruby spec/programs/eating.rb -V`, `ruby spec/programs/eating.rb --version`]
|
30
119
|
results.each do |result|
|
31
|
-
result.strip.should == "
|
120
|
+
result.strip.should == "EatingScript 1.0 (c) Florian Pilz 2011"
|
32
121
|
end
|
33
122
|
end
|
34
123
|
|
35
124
|
it "should display the version when called with -v" do
|
36
|
-
result = `ruby spec/programs/
|
37
|
-
result.strip.should == "
|
125
|
+
result = `ruby spec/programs/version.rb -v`
|
126
|
+
result.strip.should == "VersionScript 0.0 (c) Florian Pilz 2011"
|
38
127
|
end
|
39
128
|
|
40
129
|
it "should display a warning when --version or -v was called but no version was set" do
|
41
130
|
results = [
|
42
|
-
`ruby spec/programs/
|
43
|
-
`ruby spec/programs/
|
131
|
+
`ruby spec/programs/empty.rb --version 2>&1`,
|
132
|
+
`ruby spec/programs/empty.rb -v 2>&1`
|
44
133
|
]
|
45
134
|
results.each do |result|
|
46
|
-
result.strip.should == "
|
135
|
+
result.strip.should == "empty: version unknown"
|
47
136
|
end
|
48
137
|
end
|
49
138
|
end
|
50
139
|
|
51
|
-
describe "parsing of default values" do
|
52
|
-
it "should display the default values if called without arguments" do
|
53
|
-
result = `ruby spec/programs/example.rb`
|
54
|
-
result.should include(":severity => 4")
|
55
|
-
result.should include(":verbose => false")
|
56
|
-
result.should include(":mutation => MightyMutation")
|
57
|
-
result.should include(":plus_selection => true")
|
58
|
-
result.should include(":selection => BestSelection")
|
59
|
-
result.should include(":chance => 0.8")
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should assume false as default value if no default value was given" do
|
63
|
-
result = `ruby spec/programs/another_example.rb`
|
64
|
-
result.should include(":eat_nothing => false")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "setting of custom values" do
|
69
|
-
it "should display overwritten values accordingly when long option names were used" do
|
70
|
-
args = "--severity 5 --verbose --mutation DumbMutation \
|
71
|
-
--no-plus-selection --selection WorstSelection --chance 0.1"
|
72
|
-
result = `ruby spec/programs/example.rb #{args}`
|
73
|
-
result.should include(":severity => 5")
|
74
|
-
result.should include(":verbose => true")
|
75
|
-
result.should include(":mutation => DumbMutation")
|
76
|
-
result.should include(":plus_selection => false")
|
77
|
-
result.should include(":selection => WorstSelection")
|
78
|
-
result.should include(":chance => 0.1")
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should display overwritten values accordingly when short option names were used" do
|
82
|
-
# there is no short form to set switches to false
|
83
|
-
args = "-s 5 -v -m DumbMutation --no-plus-selection -l WorstSelection -c 0.1"
|
84
|
-
result = `ruby spec/programs/example.rb #{args}`
|
85
|
-
result.should include(":severity => 5")
|
86
|
-
result.should include(":verbose => true")
|
87
|
-
result.should include(":mutation => DumbMutation")
|
88
|
-
result.should include(":plus_selection => false")
|
89
|
-
result.should include(":selection => WorstSelection")
|
90
|
-
result.should include(":chance => 0.1")
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
140
|
describe "warnings from optparse" do
|
95
141
|
it "should display a warning if an argument was invalid" do
|
96
|
-
result = `ruby spec/programs/
|
142
|
+
result = `ruby spec/programs/eating.rb --free-beer`
|
97
143
|
result.strip.should == "invalid option: --free-beer"
|
98
144
|
end
|
99
145
|
|
100
146
|
it "should display a warning if another argument is needed" do
|
101
|
-
result = `ruby spec/programs/
|
102
|
-
result.strip.should == "missing argument: --
|
147
|
+
result = `ruby spec/programs/eating.rb --eat-cake`
|
148
|
+
result.strip.should == "missing argument: --eat-cake"
|
103
149
|
end
|
104
150
|
|
105
151
|
it "should display a warning if an argument of the wrong type was given" do
|
106
|
-
result = `ruby spec/programs/
|
107
|
-
result.strip.should == "invalid argument: --
|
152
|
+
result = `ruby spec/programs/eating.rb --eat-marshmellows OMFG!!!`
|
153
|
+
result.strip.should == "invalid argument: --eat-marshmellows OMFG!!!"
|
108
154
|
end
|
109
155
|
|
110
156
|
it "should display a warning if autocompletion of an argument was ambiguous" do
|
111
|
-
result = `ruby spec/programs/
|
112
|
-
result.strip.should == "ambiguous option: --
|
157
|
+
result = `ruby spec/programs/eating.rb --eat yummy!`
|
158
|
+
result.strip.should == "ambiguous option: --eat"
|
113
159
|
end
|
114
160
|
end
|
115
161
|
|
116
162
|
describe "warnings if validation failed" do
|
117
163
|
it "should display a warning if validation value_in_set failed" do
|
118
|
-
result = `ruby spec/programs/
|
119
|
-
result.strip.should
|
164
|
+
result = `ruby spec/programs/eating.rb --eat-bagel AshBagel`
|
165
|
+
result.strip.should match(/Parameter for --eat-bagel must be in \[SalmonBagel,\s?ParmesanBagel\]/)
|
120
166
|
end
|
121
167
|
|
122
168
|
it "should display a warning if validation value_matches failed" do
|
123
|
-
result = `ruby spec/programs/
|
124
|
-
result.strip.should == "Parameter for --
|
169
|
+
result = `ruby spec/programs/eating.rb --eat-cake Chocolate`
|
170
|
+
result.strip.should == "Parameter for --eat-cake must match /Cake/"
|
125
171
|
end
|
126
172
|
|
127
173
|
it "should display a warning if validation value_satisfies failed" do
|
128
|
-
result = `ruby spec/programs/
|
129
|
-
result.strip.should == "Parameter for --
|
174
|
+
result = `ruby spec/programs/eating.rb --eat-cake 12Cakes`
|
175
|
+
result.strip.should == "Parameter for --eat-cake must satisfy given conditions (see description)"
|
130
176
|
end
|
131
177
|
|
132
|
-
it "should validate all given
|
133
|
-
result = `ruby spec/programs/
|
178
|
+
it "should validate all validations if several are given for an option" do
|
179
|
+
result = `ruby spec/programs/eating.rb --eat-cake VanillaBrownie`
|
134
180
|
result.strip.should == "Parameter for --eat-cake must match /Cake/"
|
135
181
|
|
136
|
-
result = `ruby spec/programs/
|
182
|
+
result = `ruby spec/programs/eating.rb --eat-cake 2VanillaCakes`
|
137
183
|
result.strip.should == "Parameter for --eat-cake must satisfy given conditions (see description)"
|
138
184
|
end
|
139
185
|
end
|
140
186
|
|
141
187
|
describe "automatic assignment of default accessors" do
|
142
188
|
it "should assign a different character for the short accessor if the first / second / ... is already taken" do
|
143
|
-
result = `ruby spec/programs/
|
189
|
+
result = `ruby spec/programs/eating.rb --help`
|
144
190
|
result.should include("--eat-cake")
|
145
191
|
result.should include("-a, --eat-salad")
|
146
192
|
result.should include("-t, --eat-bagel")
|
@@ -2,12 +2,14 @@ require "rubygems"
|
|
2
2
|
require "micro-optparse"
|
3
3
|
|
4
4
|
options = Parser.new do |p|
|
5
|
-
p.version = "
|
5
|
+
p.version = "EatingScript 1.0 (c) Florian Pilz 2011"
|
6
|
+
p.banner = "This is a banner"
|
7
|
+
p.option :verbose, "Switch on verbosity"
|
6
8
|
p.option :eat_cake, "Eath the yummy cake!", :default => "PlainCake", :value_matches => /Cake/, :value_satisfies => lambda { |arg| arg.to_i == 0 }
|
7
9
|
p.option :eat_salad, "It's healty!", :default => "CucumberSalad"
|
8
|
-
p.option :eat_bagel, "You should try it with salmon.", :default => "SalmonBagel"
|
10
|
+
p.option :eat_bagel, "You should try it with salmon.", :default => "SalmonBagel", :value_in_set => ["SalmonBagel", "ParmesanBagel"]
|
9
11
|
p.option :eat_nothing, "Stupid decision ..."
|
10
|
-
p.option :
|
12
|
+
p.option :eat_marshmellows, "How many?", :default => 0
|
11
13
|
p.option :eat_me, "WHAT?!?", :default => "TastyHuman"
|
12
14
|
end.process!
|
13
15
|
|
File without changes
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: micro-optparse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 1
|
9
|
+
- 3
|
10
|
+
version: 1.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Florian Pilz
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-04-19 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -52,9 +52,9 @@ files:
|
|
52
52
|
- lib/micro-optparse/version.rb
|
53
53
|
- micro-optparse.gemspec
|
54
54
|
- spec/parser_spec.rb
|
55
|
-
- spec/programs/
|
56
|
-
- spec/programs/
|
57
|
-
- spec/programs/
|
55
|
+
- spec/programs/eating.rb
|
56
|
+
- spec/programs/empty.rb
|
57
|
+
- spec/programs/version.rb
|
58
58
|
has_rdoc: true
|
59
59
|
homepage: http://florianpilz.github.com/micro-optparse/
|
60
60
|
licenses:
|
@@ -91,6 +91,6 @@ specification_version: 3
|
|
91
91
|
summary: An option parser which is 70 lines short.
|
92
92
|
test_files:
|
93
93
|
- spec/parser_spec.rb
|
94
|
-
- spec/programs/
|
95
|
-
- spec/programs/
|
96
|
-
- spec/programs/
|
94
|
+
- spec/programs/eating.rb
|
95
|
+
- spec/programs/empty.rb
|
96
|
+
- spec/programs/version.rb
|
data/spec/programs/example.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require "rubygems"
|
2
|
-
require "micro-optparse"
|
3
|
-
|
4
|
-
options = Parser.new do |p|
|
5
|
-
p.banner = "This is a banner"
|
6
|
-
p.version = "OptParseWrapper 0.8 (c) Florian Pilz 2011"
|
7
|
-
p.option :severity, "set severity", :default => 4, :value_in_set => [4,5,6,7,8]
|
8
|
-
p.option :verbose, "enable verbose output"
|
9
|
-
p.option :mutation, "set mutation", :default => "MightyMutation", :value_matches => /Mutation/
|
10
|
-
p.option :plus_selection, "use plus-selection if set", :default => true
|
11
|
-
p.option :selection, "selection used", :default => "BestSelection", :short => "l"
|
12
|
-
p.option :chance, "set mutation chance", :default => 0.8, :value_satisfies => lambda {|x| x >= 0.0 && x <= 1.0}
|
13
|
-
end.process!
|
14
|
-
|
15
|
-
options.each_pair do |key, value|
|
16
|
-
puts ":#{key} => #{value}"
|
17
|
-
end
|