clamp 0.0.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.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ .yardoc
4
+ doc
5
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "rake"
7
+ gem "rspec", "~> 2.0.1"
8
+ gem "rr", "~> 1.0.0"
9
+ end
@@ -0,0 +1,30 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ clamp (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.2)
10
+ rake (0.8.7)
11
+ rr (1.0.0)
12
+ rspec (2.0.1)
13
+ rspec-core (~> 2.0.1)
14
+ rspec-expectations (~> 2.0.1)
15
+ rspec-mocks (~> 2.0.1)
16
+ rspec-core (2.0.1)
17
+ rspec-expectations (2.0.1)
18
+ diff-lcs (>= 1.1.2)
19
+ rspec-mocks (2.0.1)
20
+ rspec-core (~> 2.0.1)
21
+ rspec-expectations (~> 2.0.1)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ clamp!
28
+ rake
29
+ rr (~> 1.0.0)
30
+ rspec (~> 2.0.1)
@@ -0,0 +1,40 @@
1
+ Clamp
2
+ =====
3
+
4
+ "Clamp" is a minimal framework for command-line utilities.
5
+
6
+ It handles boring stuff like parsing the command-line, and generating help, so you can get on with making your command actually do stuff.
7
+
8
+ Not another one!
9
+ ----------------
10
+
11
+ Yeah, sorry. There are a bunch of existing command-line parsing libraries out there, and Clamp draws inspiration from a variety of sources, including [Thor], [optparse], and [Clip]. In the end, though, I wanted a slightly rounder wheel.
12
+
13
+ [optparse]: http://ruby-doc.org/stdlib/libdoc/optparse/rdoc/index.html
14
+ [Thor]: http://github.com/wycats/thor
15
+ [Clip]: http://clip.rubyforge.org/
16
+
17
+ Quick Start
18
+ -----------
19
+
20
+ Clamp models a command as a Ruby class, and command invocations as instances of that class.
21
+
22
+ "Command classes" are subclasses of `Clamp::Command`. They look like this:
23
+
24
+ class InstallCommand < Clamp::Command
25
+
26
+ option "--force", :flag, ""
27
+
28
+ def execute
29
+ # do something
30
+ end
31
+
32
+ end
33
+
34
+ Class-level methods are available to declare command-line options, and document usage.
35
+
36
+ Clamp commands are invoked like so:
37
+
38
+ InstallCommand.run
39
+
40
+ This will instantiate a new `InstallCommand`, handle command-line args, and finally call the `#execute` method to do the real work.
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require "rspec/core/rake_task"
6
+
7
+ task "default" => "spec"
8
+
9
+ RSpec::Core::RakeTask.new do |t|
10
+ t.pattern = 'spec/**/*_spec.rb'
11
+ t.rspec_opts = ["--colour", "--format", "nested"]
12
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "clamp/version"
4
+
5
+ Gem::Specification.new do |s|
6
+
7
+ s.name = "clamp"
8
+ s.version = Clamp::VERSION.dup
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Mike Williams"]
11
+ s.email = "mdub@dogbiscuit.org"
12
+ s.homepage = "http://github.com/mdub/clamp"
13
+
14
+ s.summary = %q{a minimal framework for command-line utilities}
15
+ s.description = <<EOF
16
+ Clamp makes provides an object-model for command-line utilities.
17
+ It handles parsing of command-line options, and generation of usage help.
18
+ EOF
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.require_paths = ["lib"]
23
+
24
+ end
@@ -0,0 +1,35 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require "clamp"
4
+
5
+ class Rename < Clamp::Command
6
+
7
+ usage "[OPTIONS] TRANSFORM FILE ..."
8
+
9
+ argument "TRANSFORM", "a Ruby expression"
10
+ argument "FILE", "a file to rename"
11
+
12
+ option ["-v", "--verbose"], :flag, "be verbose"
13
+
14
+ option ["-n", "--times"], "TIMES", "repetitions" do |n|
15
+ n = Integer(n)
16
+ raise ArgumentError, "too big" if n > 9
17
+ n
18
+ end
19
+
20
+ help_option
21
+
22
+ def initialize(name)
23
+ super
24
+ @times = 1
25
+ end
26
+
27
+ def execute
28
+ @times.times do
29
+ puts "Blah blah blah" if verbose?
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ Rename.run
@@ -0,0 +1,3 @@
1
+ require 'clamp/version'
2
+
3
+ require 'clamp/command'
@@ -0,0 +1,6 @@
1
+ module Clamp
2
+
3
+ class Argument < Struct.new(:name, :description)
4
+ end
5
+
6
+ end
@@ -0,0 +1,196 @@
1
+ require 'clamp/argument'
2
+ require 'clamp/option'
3
+
4
+ module Clamp
5
+
6
+ class Command
7
+
8
+ def initialize(name)
9
+ @name = name
10
+ end
11
+
12
+ attr_reader :name
13
+ attr_reader :arguments
14
+
15
+ def parse(arguments)
16
+ while arguments.first =~ /^-/
17
+ case (switch = arguments.shift)
18
+
19
+ when /\A--\z/
20
+ break
21
+
22
+ else
23
+ option = find_option(switch)
24
+ value = if option.flag?
25
+ option.flag_value(switch)
26
+ else
27
+ arguments.shift
28
+ end
29
+ begin
30
+ send("#{option.attribute_name}=", value)
31
+ rescue ArgumentError => e
32
+ signal_usage_error "option '#{switch}': #{e.message}"
33
+ end
34
+
35
+ end
36
+ end
37
+ @arguments = arguments
38
+ end
39
+
40
+ def execute
41
+ raise "you need to define #execute"
42
+ end
43
+
44
+ def run(arguments)
45
+ parse(arguments)
46
+ execute
47
+ end
48
+
49
+ def help
50
+ self.class.help.gsub("__COMMAND__", name)
51
+ end
52
+
53
+ private
54
+
55
+ def find_option(switch)
56
+ self.class.find_option(switch) ||
57
+ signal_usage_error("Unrecognised option '#{switch}'")
58
+ end
59
+
60
+ def signal_usage_error(message)
61
+ e = UsageError.new(message, self)
62
+ e.set_backtrace(caller)
63
+ raise e
64
+ end
65
+
66
+ class << self
67
+
68
+ def options
69
+ @options ||= []
70
+ end
71
+
72
+ def option(switches, argument_type, description, opts = {}, &block)
73
+ option = Clamp::Option.new(switches, argument_type, description, opts)
74
+ self.options << option
75
+ declare_option_reader(option)
76
+ declare_option_writer(option, &block)
77
+ end
78
+
79
+ def help_option(switches = ["-h", "--help"])
80
+ option(switches, :flag, "print help", :attribute_name => :help_requested) do
81
+ raise Clamp::HelpWanted.new(self)
82
+ end
83
+ end
84
+
85
+ def has_options?
86
+ !options.empty?
87
+ end
88
+
89
+ def find_option(switch)
90
+ options.find { |o| o.handles?(switch) }
91
+ end
92
+
93
+ def usage(usage)
94
+ @usages ||= []
95
+ @usages << usage
96
+ end
97
+
98
+ def arguments
99
+ @arguments ||= []
100
+ end
101
+
102
+ def argument(name, description)
103
+ arguments << Argument.new(name, description)
104
+ end
105
+
106
+ def derived_usage
107
+ parts = arguments.map { |a| a.name }
108
+ parts.unshift("[OPTIONS]") if has_options?
109
+ parts.join(" ")
110
+ end
111
+
112
+ def help
113
+ help = StringIO.new
114
+ help.puts "Usage:"
115
+ usages = @usages || [derived_usage]
116
+ usages.each_with_index do |usage, i|
117
+ help.puts " __COMMAND__ #{usage}".rstrip
118
+ end
119
+ detail_format = " %-29s %s"
120
+ unless arguments.empty?
121
+ help.puts "\nArguments:"
122
+ arguments.each do |argument|
123
+ help.puts detail_format % [argument.name, argument.description]
124
+ end
125
+ end
126
+ unless options.empty?
127
+ help.puts "\nOptions:"
128
+ options.each do |option|
129
+ help.puts detail_format % option.help
130
+ end
131
+ end
132
+ help.string
133
+ end
134
+
135
+ def run(name = $0, args = ARGV)
136
+ begin
137
+ new(name).run(args)
138
+ rescue Clamp::UsageError => e
139
+ $stderr.puts "ERROR: #{e.message}"
140
+ $stderr.puts ""
141
+ $stderr.puts e.command.help
142
+ exit(1)
143
+ rescue Clamp::HelpWanted => e
144
+ puts e.command.help
145
+ end
146
+ end
147
+
148
+ private
149
+
150
+ def declare_option_reader(option)
151
+ reader_name = option.attribute_name
152
+ reader_name += "?" if option.flag?
153
+ class_eval <<-RUBY
154
+ def #{reader_name}
155
+ @#{option.attribute_name}
156
+ end
157
+ RUBY
158
+ end
159
+
160
+ def declare_option_writer(option, &block)
161
+ define_method("#{option.attribute_name}=") do |value|
162
+ if block
163
+ value = instance_exec(value, &block)
164
+ end
165
+ instance_variable_set("@#{option.attribute_name}", value)
166
+ end
167
+ end
168
+
169
+ end
170
+
171
+ end
172
+
173
+ class Error < StandardError
174
+
175
+ def initialize(message, command)
176
+ super(message)
177
+ @command = command
178
+ end
179
+
180
+ attr_reader :command
181
+
182
+ end
183
+
184
+ # raise to signal incorrect command usage
185
+ class UsageError < Error; end
186
+
187
+ # raise to request usage help
188
+ class HelpWanted < Error
189
+
190
+ def initialize(command)
191
+ super("I need help", command)
192
+ end
193
+
194
+ end
195
+
196
+ end
@@ -0,0 +1,54 @@
1
+ module Clamp
2
+
3
+ class Option
4
+
5
+ def initialize(switches, argument_type, description, options = {})
6
+ @switches = Array(switches)
7
+ @argument_type = argument_type
8
+ @description = description
9
+ @attribute_name = options[:attribute_name].to_s if options.has_key?(:attribute_name)
10
+ end
11
+
12
+ attr_reader :switches, :argument_type, :description
13
+
14
+ def attribute_name
15
+ @attribute_name ||= long_switch.sub(/^--(\[no-\])?/, '').tr('-', '_')
16
+ end
17
+
18
+ def long_switch
19
+ switches.find { |switch| switch =~ /^--/ }
20
+ end
21
+
22
+ def handles?(switch)
23
+ recognised_switches.member?(switch)
24
+ end
25
+
26
+ def flag?
27
+ @argument_type == :flag
28
+ end
29
+
30
+ def flag_value(switch)
31
+ !(switch =~ /^--no-(.*)/ && switches.member?("--\[no-\]#{$1}"))
32
+ end
33
+
34
+ def help
35
+ lhs = switches.join(", ")
36
+ lhs += " " + argument_type unless flag?
37
+ [lhs, description]
38
+ end
39
+
40
+ private
41
+
42
+ def recognised_switches
43
+ switches.map do |switch|
44
+ if switch =~ /^--\[no-\](.*)/
45
+ ["--#{$1}", "--no-#{$1}"]
46
+ else
47
+ switch
48
+ end
49
+ end.flatten
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,3 @@
1
+ module Clamp
2
+ VERSION = "0.0.1".freeze
3
+ end
@@ -0,0 +1,385 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ describe Clamp::Command do
5
+
6
+ before do
7
+ $stdout = @out = StringIO.new
8
+ $stderr = @err = StringIO.new
9
+ end
10
+
11
+ after do
12
+ $stdout = STDOUT
13
+ $stderr = STDERR
14
+ end
15
+
16
+ def stdout
17
+ @out.string
18
+ end
19
+
20
+ def stderr
21
+ @err.string
22
+ end
23
+
24
+ def self.given_command(name, &block)
25
+ before do
26
+ @command = Class.new(Clamp::Command, &block).new(name)
27
+ end
28
+ end
29
+
30
+ given_command("cmd") do
31
+
32
+ def execute
33
+ print arguments.inspect
34
+ end
35
+
36
+ end
37
+
38
+ describe "#help" do
39
+
40
+ it "describes usage" do
41
+ @command.help.should include("Usage:\n cmd\n")
42
+ end
43
+
44
+ end
45
+
46
+ describe "#parse" do
47
+
48
+ it "sets arguments" do
49
+ @command.parse(%w(a b c))
50
+ @command.arguments.should == %w(a b c)
51
+ end
52
+
53
+ describe "with an unrecognised option" do
54
+
55
+ it "raises a UsageError" do
56
+ lambda do
57
+ @command.parse(%w(--foo bar))
58
+ end.should raise_error(Clamp::UsageError)
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ describe "#run" do
66
+
67
+ before do
68
+ @abc = %w(a b c)
69
+ @command.run(@abc)
70
+ end
71
+
72
+ it "executes the #execute method" do
73
+ stdout.should_not be_empty
74
+ end
75
+
76
+ it "provides access to the argument list" do
77
+ stdout.should == @abc.inspect
78
+ end
79
+
80
+ end
81
+
82
+ describe ".option" do
83
+
84
+ before do
85
+ @command.class.option "--flavour", "FLAVOUR", "Flavour of the month"
86
+ end
87
+
88
+ it "declares option argument accessors" do
89
+ @command.flavour.should == nil
90
+ @command.flavour = "chocolate"
91
+ @command.flavour.should == "chocolate"
92
+ end
93
+
94
+ end
95
+
96
+ describe ".option", "with explicit :attribute_name" do
97
+
98
+ before do
99
+ @command.class.option "--foo", "FOO", "A foo", :attribute_name => :bar
100
+ end
101
+
102
+ it "uses the specified attribute_name name to name accessors" do
103
+ @command.bar = "chocolate"
104
+ @command.bar.should == "chocolate"
105
+ end
106
+
107
+ it "does not attempt to create the default accessors" do
108
+ @command.should_not respond_to(:foo)
109
+ @command.should_not respond_to(:foo=)
110
+ end
111
+
112
+ end
113
+
114
+ describe "with options declared" do
115
+
116
+ before do
117
+ @command.class.option "--flavour", "FLAVOUR", "Flavour of the month"
118
+ @command.class.option "--color", "COLOR", "Preferred hue"
119
+ end
120
+
121
+ describe "#parse" do
122
+
123
+ describe "with options" do
124
+
125
+ before do
126
+ @command.parse(%w(--flavour strawberry --color blue a b c))
127
+ end
128
+
129
+ it "extracts the option values" do
130
+ @command.flavour.should == "strawberry"
131
+ @command.color.should == "blue"
132
+ end
133
+
134
+ it "retains unconsumed arguments" do
135
+ @command.arguments.should == %w(a b c)
136
+ end
137
+
138
+ end
139
+
140
+ describe "with option-like things beyond the arguments" do
141
+
142
+ it "treats them as positional arguments" do
143
+ @command.parse(%w(a b c --flavour strawberry))
144
+ @command.arguments.should == %w(a b c --flavour strawberry)
145
+ end
146
+
147
+ end
148
+
149
+ describe "with an option terminator" do
150
+
151
+ it "considers everything after the terminator to be an argument" do
152
+ @command.parse(%w(--color blue -- --flavour strawberry))
153
+ @command.arguments.should == %w(--flavour strawberry)
154
+ end
155
+
156
+ end
157
+
158
+ end
159
+
160
+ describe "#help" do
161
+
162
+ it "indicates that there are options" do
163
+ @command.help.should include("cmd [OPTIONS]")
164
+ end
165
+
166
+ it "includes option details" do
167
+ @command.help.should =~ %r(--flavour FLAVOUR +Flavour of the month)
168
+ @command.help.should =~ %r(--color COLOR +Preferred hue)
169
+ end
170
+
171
+ end
172
+
173
+ end
174
+
175
+ describe "with a flag option declared" do
176
+
177
+ before do
178
+ @command.class.option "--verbose", :flag, "Be heartier"
179
+ end
180
+
181
+ it "declares a predicate-style reader" do
182
+ @command.should respond_to(:verbose?)
183
+ @command.should_not respond_to(:verbose)
184
+ end
185
+
186
+ describe "#parse" do
187
+
188
+ describe "with option" do
189
+
190
+ before do
191
+ @command.parse(%w(--verbose foo))
192
+ end
193
+
194
+ it "sets the flag" do
195
+ @command.should be_verbose
196
+ end
197
+
198
+ it "does not consume an argument" do
199
+ @command.arguments.should == %w(foo)
200
+ end
201
+
202
+ end
203
+
204
+ end
205
+
206
+ end
207
+
208
+ describe "with a negatable flag option declared" do
209
+
210
+ before do
211
+ @command.class.option "--[no-]sync", :flag, "Synchronise"
212
+ end
213
+
214
+ describe "#parse" do
215
+
216
+ describe "with --flag" do
217
+
218
+ before do
219
+ @command.parse(%w(--sync))
220
+ end
221
+
222
+ it "sets the flag" do
223
+ @command.sync?.should be_true
224
+ end
225
+
226
+ end
227
+
228
+ describe "with --no-flag" do
229
+
230
+ before do
231
+ @command.sync = true
232
+ @command.parse(%w(--no-sync))
233
+ end
234
+
235
+ it "clears the flag" do
236
+ @command.sync?.should be_false
237
+ end
238
+
239
+ end
240
+
241
+ end
242
+
243
+ end
244
+
245
+ describe ".option, with a block" do
246
+
247
+ before do
248
+ @command.class.option "--port", "PORT", "Port to listen on" do |port|
249
+ Integer(port)
250
+ end
251
+ end
252
+
253
+ it "uses the block to validate and convert the option argument" do
254
+ lambda do
255
+ @command.port = "blah"
256
+ end.should raise_error(ArgumentError)
257
+ @command.port = "1234"
258
+ @command.port.should == 1234
259
+ end
260
+
261
+ describe "#parse" do
262
+
263
+ describe "with a valid option argument" do
264
+
265
+ it "stores the converted value" do
266
+ @command.parse(%w(--port 4321))
267
+ @command.port.should == 4321
268
+ end
269
+
270
+ end
271
+
272
+ describe "with an invalid option argument" do
273
+
274
+ it "raises a UsageError" do
275
+ lambda do
276
+ @command.parse(%w(--port blah))
277
+ end.should raise_error(Clamp::UsageError, /^option '--port': invalid value/)
278
+ end
279
+
280
+ end
281
+
282
+ end
283
+
284
+ end
285
+
286
+ describe "with explicit usage" do
287
+
288
+ given_command("blah") do
289
+
290
+ usage "FOO BAR ..."
291
+
292
+ end
293
+
294
+ describe "#help" do
295
+
296
+ it "includes the explicit usage" do
297
+ @command.help.should include("blah FOO BAR ...\n")
298
+ end
299
+
300
+ end
301
+
302
+ end
303
+
304
+ describe "with multiple usages" do
305
+
306
+ given_command("put") do
307
+
308
+ usage "THIS HERE"
309
+ usage "THAT THERE"
310
+
311
+ end
312
+
313
+ describe "#help" do
314
+
315
+ it "includes both potential usages" do
316
+ @command.help.should include("put THIS HERE\n")
317
+ @command.help.should include("put THAT THERE\n")
318
+ end
319
+
320
+ end
321
+
322
+ end
323
+
324
+ describe ".run" do
325
+
326
+ it "creates a new Command instance and runs it" do
327
+ @xyz = %w(x y z)
328
+ @command.class.run("cmd", @xyz)
329
+ stdout.should == @xyz.inspect
330
+ end
331
+
332
+ describe "when there's a UsageError" do
333
+
334
+ before do
335
+
336
+ @command.class.class_eval do
337
+ def execute
338
+ signal_usage_error "bad dog!"
339
+ end
340
+ end
341
+
342
+ begin
343
+ @command.class.run("cmd", [])
344
+ rescue SystemExit => e
345
+ @system_exit = e
346
+ end
347
+
348
+ end
349
+
350
+ it "outputs the error message" do
351
+ stderr.should include "ERROR: bad dog!"
352
+ end
353
+
354
+ it "outputs help" do
355
+ stderr.should include "Usage:"
356
+ end
357
+
358
+ it "exits with a non-zero status" do
359
+ @system_exit.should_not be_nil
360
+ @system_exit.status.should == 1
361
+ end
362
+
363
+ end
364
+
365
+ describe "when help is requested" do
366
+
367
+ before do
368
+
369
+ @command.class.class_eval do
370
+ help_option "--help"
371
+ end
372
+
373
+ @command.class.run("cmd", ["--help"])
374
+
375
+ end
376
+
377
+ it "outputs help" do
378
+ stdout.should include "Usage:"
379
+ end
380
+
381
+ end
382
+
383
+ end
384
+
385
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe Clamp::Option do
4
+
5
+ describe "with String argument" do
6
+
7
+ before do
8
+ @option = Clamp::Option.new("--key-file", "FILE", "SSH identity")
9
+ end
10
+
11
+ it "has a long_switch" do
12
+ @option.long_switch.should == "--key-file"
13
+ end
14
+
15
+ it "has an argument_type" do
16
+ @option.argument_type.should == "FILE"
17
+ end
18
+
19
+ it "has a description" do
20
+ @option.description.should == "SSH identity"
21
+ end
22
+
23
+ describe "#attribute_name" do
24
+
25
+ it "is derived from the (long) switch" do
26
+ @option.attribute_name.should == "key_file"
27
+ end
28
+
29
+ it "can be overridden" do
30
+ @option = Clamp::Option.new("--key-file", "FILE", "SSH identity", :attribute_name => "ssh_identity")
31
+ @option.attribute_name.should == "ssh_identity"
32
+ end
33
+
34
+ end
35
+
36
+ describe "#help" do
37
+
38
+ it "combines switch, argument_type and description" do
39
+ @option.help.should == ["--key-file FILE", "SSH identity"]
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ describe "flag" do
47
+
48
+ before do
49
+ @option = Clamp::Option.new("--verbose", :flag, "Blah blah blah")
50
+ end
51
+
52
+ describe "#help" do
53
+
54
+ it "excludes option argument" do
55
+ @option.help.should == ["--verbose", "Blah blah blah"]
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ describe "negatable flag" do
63
+
64
+ before do
65
+ @option = Clamp::Option.new("--[no-]force", :flag, "Force installation")
66
+ end
67
+
68
+ it "handles both positive and negative forms" do
69
+ @option.handles?("--force").should be_true
70
+ @option.handles?("--no-force").should be_true
71
+ end
72
+
73
+ describe "#flag_value" do
74
+
75
+ it "returns true for the positive variant" do
76
+ @option.flag_value("--force").should be_true
77
+ @option.flag_value("--no-force").should be_false
78
+ end
79
+
80
+ end
81
+
82
+ describe "#attribute_name" do
83
+
84
+ it "is derived from the (long) switch" do
85
+ @option.attribute_name.should == "force"
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ describe "with both short and long switches" do
93
+
94
+ before do
95
+ @option = Clamp::Option.new(["-k", "--key-file"], "FILE", "SSH identity")
96
+ end
97
+
98
+ it "handles both switches" do
99
+ @option.handles?("--key-file").should be_true
100
+ @option.handles?("-k").should be_true
101
+ end
102
+
103
+ describe "#help" do
104
+
105
+ it "includes both switches" do
106
+ @option.help.should == ["-k, --key-file FILE", "SSH identity"]
107
+ end
108
+
109
+ end
110
+
111
+ end
112
+
113
+ end
@@ -0,0 +1,8 @@
1
+ require "rspec"
2
+ require "clamp"
3
+
4
+ Rspec.configure do |config|
5
+
6
+ config.mock_with :rr
7
+
8
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clamp
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Mike Williams
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-02 00:00:00 +11:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: |
23
+ Clamp makes provides an object-model for command-line utilities.
24
+ It handles parsing of command-line options, and generation of usage help.
25
+
26
+ email: mdub@dogbiscuit.org
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - Gemfile.lock
37
+ - README.markdown
38
+ - Rakefile
39
+ - clamp.gemspec
40
+ - examples/rename
41
+ - lib/clamp.rb
42
+ - lib/clamp/argument.rb
43
+ - lib/clamp/command.rb
44
+ - lib/clamp/option.rb
45
+ - lib/clamp/version.rb
46
+ - spec/clamp/command_spec.rb
47
+ - spec/clamp/option_spec.rb
48
+ - spec/spec_helper.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/mdub/clamp
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: a minimal framework for command-line utilities
83
+ test_files:
84
+ - spec/clamp/command_spec.rb
85
+ - spec/clamp/option_spec.rb
86
+ - spec/spec_helper.rb