jls-clamp 0.3.1 → 0.3.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +38 -0
- data/lib/clamp/attribute.rb +3 -3
- data/lib/clamp/command.rb +2 -1
- data/lib/clamp/option.rb +15 -1
- data/lib/clamp/option/parsing.rb +37 -6
- data/lib/clamp/parameter.rb +3 -0
- data/lib/clamp/parameter/parsing.rb +12 -0
- data/lib/clamp/version.rb +1 -1
- data/spec/clamp/command_spec.rb +94 -8
- data/spec/clamp/option_spec.rb +16 -1
- metadata +2 -2
data/README.markdown
CHANGED
@@ -88,6 +88,32 @@ Negatable flags are easy to generate, too:
|
|
88
88
|
|
89
89
|
Clamp will handle both "`--force`" and "`--no-force`" options, setting the value of "`#force?`" appropriately.
|
90
90
|
|
91
|
+
### Values from the environment
|
92
|
+
|
93
|
+
Sometimes you'll want to pass in option values from the environment:
|
94
|
+
|
95
|
+
option "--port", "PORT", "the port to listen on", :env => "PORT" do |val|
|
96
|
+
val.to_i
|
97
|
+
end
|
98
|
+
|
99
|
+
The above means that in the absence of '--port' on the command line, Clamp will
|
100
|
+
check for `PORT` in the environment. This lets you do:
|
101
|
+
|
102
|
+
% export PORT=8080
|
103
|
+
% ./mycommand
|
104
|
+
|
105
|
+
### Required options
|
106
|
+
|
107
|
+
While a 'required option' is a bit of an oxymoron, it is common to use options
|
108
|
+
as named parameters to your program. Clamp lets you make an option required:
|
109
|
+
|
110
|
+
option "--password", "PASSWORD", "the secret password", :required => true
|
111
|
+
|
112
|
+
Special notes about required options:
|
113
|
+
|
114
|
+
* You may not use :required and :default values in the same option ('require' doesn't make sense if you provide a default)
|
115
|
+
* You may not use :required on :flag options. Since :flag options are boolean, a 'required flag' would mean "always true" ;)
|
116
|
+
|
91
117
|
Declaring parameters
|
92
118
|
--------------------
|
93
119
|
|
@@ -116,6 +142,18 @@ Three dots at the end of a parameter name makes it "greedy" - it will consume al
|
|
116
142
|
|
117
143
|
The suffix "`_list`" is appended to the default attribute name for greedy parameters; in this case, an attribute called "`file_list`" would be generated.
|
118
144
|
|
145
|
+
### Parameters from the environment
|
146
|
+
|
147
|
+
Optional parameters can have values given from the environment the same way options can.
|
148
|
+
|
149
|
+
parameter "[EXAMPLE]", "This is an example", :env => "EXAMPLE"
|
150
|
+
|
151
|
+
The above means that in the absence of a value on the command line, Clamp will
|
152
|
+
check for `EXAMPLE` in the environment. This lets you do:
|
153
|
+
|
154
|
+
% export EXAMPLE="hello"
|
155
|
+
% ./mycommand
|
156
|
+
|
119
157
|
Parsing and validation of options and parameters
|
120
158
|
------------------------------------------------
|
121
159
|
|
data/lib/clamp/attribute.rb
CHANGED
@@ -2,15 +2,15 @@ module Clamp
|
|
2
2
|
|
3
3
|
class Attribute
|
4
4
|
|
5
|
-
attr_reader :description, :attribute_name, :default_value, :
|
5
|
+
attr_reader :description, :attribute_name, :default_value, :environment_variable
|
6
6
|
|
7
7
|
def help_rhs
|
8
8
|
rhs = description
|
9
9
|
if defined?(@default_value)
|
10
10
|
rhs += " (default: #{@default_value.inspect})"
|
11
11
|
end
|
12
|
-
if defined?(@
|
13
|
-
rhs += " (env: #{@
|
12
|
+
if defined?(@environment_variable)
|
13
|
+
rhs += " (env: #{@environment_variable.inspect})"
|
14
14
|
end
|
15
15
|
rhs
|
16
16
|
end
|
data/lib/clamp/command.rb
CHANGED
data/lib/clamp/option.rb
CHANGED
@@ -15,7 +15,17 @@ module Clamp
|
|
15
15
|
@default_value = options[:default]
|
16
16
|
end
|
17
17
|
if options.has_key?(:env)
|
18
|
-
@
|
18
|
+
@environment_variable = options[:env]
|
19
|
+
end
|
20
|
+
if options.has_key?(:required)
|
21
|
+
@required = options[:required]
|
22
|
+
# Do some light validation for conflicting settings.
|
23
|
+
if options.has_key?(:default)
|
24
|
+
raise ArgumentError, "Specifying a :default value also :required doesn't make sense"
|
25
|
+
end
|
26
|
+
if type == :flag
|
27
|
+
raise ArgumentError, "A required flag (boolean) doesn't make sense."
|
28
|
+
end
|
19
29
|
end
|
20
30
|
end
|
21
31
|
|
@@ -33,6 +43,10 @@ module Clamp
|
|
33
43
|
recognised_switches.member?(switch)
|
34
44
|
end
|
35
45
|
|
46
|
+
def required?
|
47
|
+
@required
|
48
|
+
end
|
49
|
+
|
36
50
|
def flag?
|
37
51
|
@type == :flag
|
38
52
|
end
|
data/lib/clamp/option/parsing.rb
CHANGED
@@ -3,6 +3,24 @@ module Clamp
|
|
3
3
|
|
4
4
|
module Parsing
|
5
5
|
|
6
|
+
# For :flag options with environment variables attached, this is a list
|
7
|
+
# of possible values that are accepted as 'true'
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# option "--foo", :flag, "Use foo", :env => "FOO"
|
12
|
+
#
|
13
|
+
# All of these will set 'foo' to true:
|
14
|
+
#
|
15
|
+
# FOO=1 ./myprogram
|
16
|
+
# FOO=true ./myprogram
|
17
|
+
# FOO=yes ./myprogram
|
18
|
+
# FOO=on ./myprogram
|
19
|
+
# FOO=enable ./myprogram
|
20
|
+
#
|
21
|
+
# See {Clamp::Command.option} for more information.
|
22
|
+
TRUTHY_ENVIRONMENT_VALUES = %w(1 yes enable on true)
|
23
|
+
|
6
24
|
protected
|
7
25
|
|
8
26
|
def parse_options
|
@@ -30,16 +48,29 @@ module Clamp
|
|
30
48
|
end
|
31
49
|
|
32
50
|
end
|
51
|
+
|
52
|
+
# Verify that all required options are present
|
53
|
+
self.class.recognised_options.each do |option|
|
54
|
+
# If this option is required and the value is nil, there's an error.
|
55
|
+
if option.required? and send(option.attribute_name).nil?
|
56
|
+
message = "option '#{option.switches.first}'"
|
57
|
+
if option.environment_variable
|
58
|
+
message += " (or env #{option.environment_variable})"
|
59
|
+
end
|
60
|
+
message += " is required"
|
61
|
+
signal_usage_error message
|
62
|
+
end
|
63
|
+
end
|
33
64
|
end
|
34
65
|
|
35
|
-
def
|
66
|
+
def parse_environment_options
|
36
67
|
self.class.recognised_options.each do |option|
|
37
|
-
next if option.
|
38
|
-
next unless ENV.has_key?(option.
|
39
|
-
value = ENV[option.
|
68
|
+
next if option.environment_variable.nil?
|
69
|
+
next unless ENV.has_key?(option.environment_variable)
|
70
|
+
value = ENV[option.environment_variable]
|
40
71
|
if option.flag?
|
41
|
-
# Set true if the
|
42
|
-
send("#{option.attribute_name}=", value
|
72
|
+
# Set true if the environment value is truthy.
|
73
|
+
send("#{option.attribute_name}=", TRUTHY_ENVIRONMENT_VALUES.include?(value))
|
43
74
|
else
|
44
75
|
send("#{option.attribute_name}=", value)
|
45
76
|
end
|
data/lib/clamp/parameter.rb
CHANGED
@@ -18,6 +18,18 @@ module Clamp
|
|
18
18
|
|
19
19
|
end
|
20
20
|
|
21
|
+
def parse_environment_parameters
|
22
|
+
|
23
|
+
self.class.parameters.each do |parameter|
|
24
|
+
next if parameter.environment_variable.nil?
|
25
|
+
next unless ENV.has_key?(parameter.environment_variable)
|
26
|
+
# Set the parameter value if it's environment variable is present
|
27
|
+
value = ENV[parameter.environment_variable]
|
28
|
+
send("#{parameter.attribute_name}=", value)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
21
33
|
end
|
22
34
|
|
23
35
|
end
|
data/lib/clamp/version.rb
CHANGED
data/spec/clamp/command_spec.rb
CHANGED
@@ -119,6 +119,7 @@ describe Clamp::Command do
|
|
119
119
|
end
|
120
120
|
|
121
121
|
it "should use the default if neither flag nor env var are present" do
|
122
|
+
ENV.delete("PORT")
|
122
123
|
@command.parse([])
|
123
124
|
@command.port.should == 4321
|
124
125
|
end
|
@@ -156,16 +157,27 @@ describe Clamp::Command do
|
|
156
157
|
@command.enable?.should == false
|
157
158
|
end
|
158
159
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
160
|
+
Clamp::Option::Parsing::TRUTHY_ENVIRONMENT_VALUES.each do |value|
|
161
|
+
it "should use environment value '#{value}' to mean true" do
|
162
|
+
ENV["ENABLE"] = value
|
163
|
+
@command.parse([])
|
164
|
+
@command.enable?.should == true
|
165
|
+
end
|
163
166
|
end
|
164
167
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
168
|
+
# Make sure tests fail if ever the TRUTHY_ENVIRONMENT_VALUES loses a
|
169
|
+
# value. This is just a safety check to make sure maintainers update
|
170
|
+
# any relevant docs and aware that they could be breaking compatibility.
|
171
|
+
it "should accept only these values as 'truthy' environment values: 1, yes, enable, on, true" do
|
172
|
+
Clamp::Option::Parsing::TRUTHY_ENVIRONMENT_VALUES.should == %w(1 yes enable on true)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should use an env value other than truthy ones to mean false" do
|
176
|
+
[nil, "0", "no", "whatever"].each do |val|
|
177
|
+
ENV["ENABLE"] = val
|
178
|
+
@command.parse([])
|
179
|
+
@command.enable?.should == false
|
180
|
+
end
|
169
181
|
end
|
170
182
|
|
171
183
|
it "should use the the flag value if present (instead of env)" do
|
@@ -184,6 +196,46 @@ describe Clamp::Command do
|
|
184
196
|
|
185
197
|
end
|
186
198
|
|
199
|
+
describe "with :required value" do
|
200
|
+
|
201
|
+
before do
|
202
|
+
@command.class.option "--port", "PORT", "port to listen on", :required => true
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should fail if a required option is not provided" do
|
206
|
+
expect { @command.parse([]) }.to raise_error(Clamp::UsageError)
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should succeed if a required option is provided" do
|
210
|
+
@command.parse(["--port", "12345"])
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "with :required value with :env" do
|
216
|
+
|
217
|
+
before do
|
218
|
+
@command.class.option "--port", "PORT", "port to listen on", :required => true, :env => "PORT"
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should fail if a required option is not provided" do
|
222
|
+
ENV.delete("PORT")
|
223
|
+
expect { @command.parse([]) }.to raise_error(Clamp::UsageError)
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should succeed if a required option is provided via arguments" do
|
227
|
+
ENV.delete("PORT")
|
228
|
+
@command.parse(["--port", "12345"])
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should succeed if a required option is provided via env" do
|
232
|
+
ENV["PORT"] = "12345"
|
233
|
+
@command.parse([])
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
|
187
239
|
describe "with a block" do
|
188
240
|
|
189
241
|
before do
|
@@ -512,6 +564,40 @@ describe Clamp::Command do
|
|
512
564
|
|
513
565
|
end
|
514
566
|
|
567
|
+
describe "with :env value" do
|
568
|
+
|
569
|
+
before do
|
570
|
+
@command.class.parameter "[FILE]", "a file", :env => "FILE",
|
571
|
+
:default => "default"
|
572
|
+
end
|
573
|
+
|
574
|
+
it "should use the default if neither flag nor env var are present" do
|
575
|
+
@command.parse([])
|
576
|
+
@command.file.should == "default"
|
577
|
+
end
|
578
|
+
|
579
|
+
it "should use the env value if present (instead of default)" do
|
580
|
+
ENV["FILE"] = "/etc/motd"
|
581
|
+
@command.parse([])
|
582
|
+
@command.file.should == ENV["FILE"]
|
583
|
+
end
|
584
|
+
|
585
|
+
it "should use the the flag value if present (instead of env)" do
|
586
|
+
ENV["FILE"] = "/etc/motd"
|
587
|
+
@command.parse(%w(/bin/sh))
|
588
|
+
@command.file.should == "/bin/sh"
|
589
|
+
end
|
590
|
+
|
591
|
+
describe "#help" do
|
592
|
+
|
593
|
+
it "describes the default value and env usage" do
|
594
|
+
@command.help.should include("a file (default: \"default\") (env: \"FILE\")")
|
595
|
+
end
|
596
|
+
|
597
|
+
end
|
598
|
+
|
599
|
+
end
|
600
|
+
|
515
601
|
end
|
516
602
|
|
517
603
|
describe "with no parameters declared" do
|
data/spec/clamp/option_spec.rb
CHANGED
@@ -145,5 +145,20 @@ describe Clamp::Option do
|
|
145
145
|
end
|
146
146
|
|
147
147
|
end
|
148
|
-
|
148
|
+
|
149
|
+
describe "a required option" do
|
150
|
+
it "rejects :default" do
|
151
|
+
expect do
|
152
|
+
Clamp::Option.new("--key-file", "FILE", "SSH identity",
|
153
|
+
:required => true, :default => "hello")
|
154
|
+
end.to raise_error(ArgumentError)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "rejects :flag options" do
|
158
|
+
expect do
|
159
|
+
Clamp::Option.new("--awesome", :flag, "Be awesome?", :required => true)
|
160
|
+
end.to raise_error(ArgumentError)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
149
164
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jls-clamp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.1
|
4
|
+
version: 0.3.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-30 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! "Clamp provides an object-model for command-line utilities. \nIt handles
|
15
15
|
parsing of command-line options, and generation of usage help.\n"
|