jls-clamp 0.3.1 → 0.3.1.2
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.
- 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"
|