clamp 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -121,7 +121,7 @@ Parsing and validation of options and parameters
121
121
 
122
122
  When you `#run` a command, it will first attempt to `#parse` command-line arguments, and map them onto the declared options and parameters, before invoking your `#execute` method.
123
123
 
124
- If parameters are declared, Clamp will verify that all required (ie. non-optional) parameters are present, and signal a error if they aren't. Otherwise, arguments that remain after option parsing will be made available via `#arguments`.
124
+ Clamp will verify that all required (ie. non-optional) parameters are present, and signal a error if they aren't.
125
125
 
126
126
  ### Validation block
127
127
 
data/lib/clamp/command.rb CHANGED
@@ -35,8 +35,8 @@ module Clamp
35
35
 
36
36
  # @return [Array<String>] unconsumed command-line arguments
37
37
  #
38
- def arguments
39
- @arguments
38
+ def remaining_arguments
39
+ @remaining_arguments
40
40
  end
41
41
 
42
42
  # Parse command-line arguments.
@@ -45,10 +45,10 @@ module Clamp
45
45
  # @return [Array<String>] unconsumed arguments
46
46
  #
47
47
  def parse(arguments)
48
- @arguments = arguments.dup
48
+ @remaining_arguments = arguments.dup
49
49
  parse_options
50
50
  parse_parameters
51
- @arguments
51
+ @remaining_arguments
52
52
  end
53
53
 
54
54
  # Run the command, with the specified arguments.
data/lib/clamp/help.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'stringio'
2
+
1
3
  module Clamp
2
4
 
3
5
  module Help
@@ -11,7 +13,6 @@ module Clamp
11
13
 
12
14
  def derived_usage_description
13
15
  parts = parameters.map { |a| a.name }
14
- parts.unshift("SUBCOMMAND") if has_subcommands?
15
16
  parts.unshift("[OPTIONS]") if has_options?
16
17
  parts.join(" ")
17
18
  end
@@ -6,13 +6,13 @@ module Clamp
6
6
  protected
7
7
 
8
8
  def parse_options
9
- while arguments.first =~ /^-/
9
+ while remaining_arguments.first =~ /^-/
10
10
 
11
- switch = arguments.shift
11
+ switch = remaining_arguments.shift
12
12
  break if switch == "--"
13
13
 
14
14
  option = find_option(switch)
15
- value = option.extract_value(switch, arguments)
15
+ value = option.extract_value(switch, remaining_arguments)
16
16
 
17
17
  begin
18
18
  send("#{option.attribute_name}=", value)
@@ -7,18 +7,16 @@ module Clamp
7
7
 
8
8
  def parse_parameters
9
9
 
10
- return false if self.class.parameters.empty?
11
-
12
10
  self.class.parameters.each do |parameter|
13
11
  begin
14
- value = parameter.consume(arguments)
12
+ value = parameter.consume(remaining_arguments)
15
13
  send("#{parameter.attribute_name}=", value)
16
14
  rescue ArgumentError => e
17
15
  signal_usage_error "parameter '#{parameter.name}': #{e.message}"
18
16
  end
19
17
  end
20
18
 
21
- unless arguments.empty?
19
+ unless remaining_arguments.empty?
22
20
  signal_usage_error "too many arguments"
23
21
  end
24
22
 
@@ -13,6 +13,7 @@ module Clamp
13
13
  end
14
14
 
15
15
  def subcommand(name, description, subcommand_class = self, &block)
16
+ has_subcommands!
16
17
  if block
17
18
  # generate a anonymous sub-class
18
19
  subcommand_class = Class.new(subcommand_class, &block)
@@ -27,6 +28,13 @@ module Clamp
27
28
  def find_subcommand(name)
28
29
  recognised_subcommands.find { |sc| sc.name == name }
29
30
  end
31
+
32
+ def has_subcommands!
33
+ unless method_defined?(:subcommand_name)
34
+ parameter "SUBCOMMAND", "subcommand name", :attribute_name => :subcommand_name
35
+ parameter "[ARGS] ...", "subcommand arguments", :attribute_name => :subcommand_arguments
36
+ end
37
+ end
30
38
 
31
39
  end
32
40
 
@@ -6,12 +6,11 @@ module Clamp
6
6
  protected
7
7
 
8
8
  def execute_subcommand
9
- signal_usage_error "no subcommand specified" if arguments.empty?
10
- subcommand_name = arguments.shift
9
+ signal_usage_error "no subcommand specified" unless subcommand_name
11
10
  subcommand_class = find_subcommand_class(subcommand_name)
12
11
  subcommand = subcommand_class.new("#{invocation_path} #{subcommand_name}", context)
13
12
  subcommand.parent_command = self
14
- subcommand.run(arguments)
13
+ subcommand.run(subcommand_arguments)
15
14
  end
16
15
 
17
16
  private
data/lib/clamp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Clamp
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.1.1".freeze
3
3
  end
@@ -14,7 +14,7 @@ describe Clamp::Command do
14
14
  given_command("cmd") do
15
15
 
16
16
  def execute
17
- print arguments.inspect
17
+ puts "Hello, world"
18
18
  end
19
19
 
20
20
  end
@@ -30,18 +30,13 @@ describe Clamp::Command do
30
30
  describe "#run" do
31
31
 
32
32
  before do
33
- @abc = %w(a b c)
34
- @command.run(@abc)
33
+ @command.run([])
35
34
  end
36
35
 
37
36
  it "executes the #execute method" do
38
37
  stdout.should_not be_empty
39
38
  end
40
39
 
41
- it "provides access to the argument list" do
42
- stdout.should == @abc.inspect
43
- end
44
-
45
40
  end
46
41
 
47
42
  describe ".option" do
@@ -122,6 +117,7 @@ describe Clamp::Command do
122
117
  @command.class.option "--flavour", "FLAVOUR", "Flavour of the month"
123
118
  @command.class.option "--color", "COLOR", "Preferred hue"
124
119
  @command.class.option "--[no-]nuts", :flag, "Nuts (or not)"
120
+ @command.class.parameter "[ARG] ...", "extra arguments", :attribute_name => :arguments
125
121
  end
126
122
 
127
123
  describe "#parse" do
@@ -139,7 +135,7 @@ describe Clamp::Command do
139
135
  describe "with options" do
140
136
 
141
137
  before do
142
- @command.parse(%w(--flavour strawberry --nuts --color blue a b c))
138
+ @command.parse(%w(--flavour strawberry --nuts --color blue))
143
139
  end
144
140
 
145
141
  it "maps the option values onto the command object" do
@@ -148,10 +144,6 @@ describe Clamp::Command do
148
144
  @command.nuts?.should == true
149
145
  end
150
146
 
151
- it "retains unconsumed arguments" do
152
- @command.arguments.should == %w(a b c)
153
- end
154
-
155
147
  end
156
148
 
157
149
  describe "with option-like things beyond the arguments" do
@@ -282,9 +274,14 @@ describe Clamp::Command do
282
274
 
283
275
  describe "#parse" do
284
276
 
285
- it "retains arguments for handling by #execute" do
286
- @command.parse(["crash", "bang", "wallop"])
287
- @command.arguments.should == ["crash", "bang", "wallop"]
277
+ describe "with arguments" do
278
+
279
+ it "raises a UsageError" do
280
+ lambda do
281
+ @command.parse(["crash"])
282
+ end.should raise_error(Clamp::UsageError, "too many arguments")
283
+ end
284
+
288
285
  end
289
286
 
290
287
  end
@@ -313,10 +310,6 @@ describe Clamp::Command do
313
310
  @command.z.should == "wallop"
314
311
  end
315
312
 
316
- it "consumes all the arguments" do
317
- @command.arguments.should == []
318
- end
319
-
320
313
  end
321
314
 
322
315
  describe "with insufficient arguments" do
@@ -395,6 +388,12 @@ describe Clamp::Command do
395
388
  describe ".run" do
396
389
 
397
390
  it "creates a new Command instance and runs it" do
391
+ @command.class.class_eval do
392
+ parameter "WORD ...", "words"
393
+ def execute
394
+ print word_list.inspect
395
+ end
396
+ end
398
397
  @xyz = %w(x y z)
399
398
  @command.class.run("cmd", @xyz)
400
399
  stdout.should == @xyz.inspect
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clamp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Mike Williams