clamp 0.1.0 → 0.1.1

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 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