cp 0.0.1.pre1
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/cp.gemspec +22 -0
- data/examples/net.rb +81 -0
- data/lib/cp.rb +22 -0
- data/lib/cp/app.rb +28 -0
- data/lib/cp/command.rb +23 -0
- data/lib/cp/commands.rb +15 -0
- data/lib/cp/option.rb +86 -0
- data/lib/cp/options.rb +15 -0
- data/lib/cp/runners/cmd_parse.rb +56 -0
- data/lib/cp/version.rb +3 -0
- data/spec/app_spec.rb +50 -0
- data/spec/command_spec.rb +48 -0
- data/spec/cp_spec.rb +26 -0
- data/spec/option_spec.rb +171 -0
- data/spec/options_spec.rb +10 -0
- data/spec/runners/cmd_parse_spec.rb +47 -0
- data/spec/support/shared_helper.rb +47 -0
- data/spec/support/singleton_helper.rb +17 -0
- data/spec/support/spec_helper.rb +32 -0
- metadata +105 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/cp.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "cp/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "cp"
|
7
|
+
s.version = CP::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Rick Fletcher"]
|
10
|
+
s.email = ["fletch@pobox.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{An alternative API for CmdParse}
|
13
|
+
s.description = %q{CP provides a less verbose API for the CmdParse gem.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency(%q<cmdparse>, [">= 2.0.2"])
|
21
|
+
s.add_runtime_dependency(%q<cmdparse>, [">= 2.0.2"])
|
22
|
+
end
|
data/examples/net.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
##
|
2
|
+
# A port of the CmdParse tutorial app, net.rb
|
3
|
+
# original: http://cmdparse.rubyforge.org/tutorial.html
|
4
|
+
#
|
5
|
+
|
6
|
+
$: << File.join( ".", File.dirname( __FILE__ ), "..", "lib" )
|
7
|
+
|
8
|
+
require "cp"
|
9
|
+
|
10
|
+
include CP
|
11
|
+
|
12
|
+
$ipaddrs = []
|
13
|
+
$verbose = false
|
14
|
+
|
15
|
+
app :name, "net"
|
16
|
+
app :version, "0.1.1"
|
17
|
+
|
18
|
+
# global options
|
19
|
+
option( "--verbose", "Be verbose when outputting info" ) { |t| $verbose = true }
|
20
|
+
|
21
|
+
# add the top-level "ipaddr" command
|
22
|
+
command :ipaddr do |c|
|
23
|
+
# c.allow_partial! # partial commands aren't implemented
|
24
|
+
c.summary = "Manage IP addresses"
|
25
|
+
|
26
|
+
# add the "add" subcommand
|
27
|
+
c.command( :add ) do |s|
|
28
|
+
s.summary = "Add an IP address"
|
29
|
+
|
30
|
+
s.execute do |*args|
|
31
|
+
puts "Adding IP addresses: #{args.join(', ')}" if $verbose
|
32
|
+
$ipaddrs += args
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# add the "del" subcommand
|
37
|
+
c.command :del do |s|
|
38
|
+
s.summary = "Delete IP addresses"
|
39
|
+
|
40
|
+
s.option( "-a", "--all", "Delete all IP addresses" ){ $deleteAll = true }
|
41
|
+
|
42
|
+
s.execute do |*args|
|
43
|
+
if $deleteAll
|
44
|
+
$ipaddrs = []
|
45
|
+
else
|
46
|
+
puts "Deleting IP addresses: #{args.join(', ')}" if $verbose
|
47
|
+
args.each { |ip| $ipaddrs.delete( ip ) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# add the "list" subcommand
|
53
|
+
c.command :list do |s|
|
54
|
+
# s.default! # make :list the default subcommand
|
55
|
+
s.summary = "List all IP addresses"
|
56
|
+
|
57
|
+
s.execute do |*args|
|
58
|
+
puts "Listing IP addresses:" if $verbose
|
59
|
+
puts $ipaddrs.to_yaml
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# add the "stat" subcommand
|
64
|
+
c.command :stat do |s|
|
65
|
+
s.summary = "Show network statistics"
|
66
|
+
s.description = "This command shows very useful network statistics - eye catching!!!"
|
67
|
+
|
68
|
+
s.execute do |*args|
|
69
|
+
puts "Showing network statistics" if $verbose
|
70
|
+
puts
|
71
|
+
puts "Yeah, I will do something now..."
|
72
|
+
puts
|
73
|
+
1.upto(10) do |row|
|
74
|
+
puts " "*(20-row) + "#"*(row*2 - 1)
|
75
|
+
end
|
76
|
+
puts
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
run
|
data/lib/cp.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "cmdparse"
|
3
|
+
|
4
|
+
require "cp/runners/cmd_parse"
|
5
|
+
require "cp/commands"
|
6
|
+
require "cp/options"
|
7
|
+
require "cp/command"
|
8
|
+
require "cp/version"
|
9
|
+
require "cp/option"
|
10
|
+
require "cp/app"
|
11
|
+
|
12
|
+
module CP
|
13
|
+
def self.included( scope )
|
14
|
+
scope.extend( self )
|
15
|
+
end
|
16
|
+
|
17
|
+
[:app, :command, :option, :run].each do |method|
|
18
|
+
define_method( method ) { |*args, &block|
|
19
|
+
App.instance.send( method, *args, &block )
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
data/lib/cp/app.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "singleton"
|
2
|
+
|
3
|
+
module CP
|
4
|
+
class App
|
5
|
+
include ::Singleton
|
6
|
+
|
7
|
+
include CP::Commands
|
8
|
+
include CP::Options
|
9
|
+
|
10
|
+
attr_accessor :name, :version, :runner
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
self.runner = CP::Runners::CmdParse
|
14
|
+
end
|
15
|
+
|
16
|
+
def app( attr, value )
|
17
|
+
begin
|
18
|
+
self.send( "#{attr}=", value )
|
19
|
+
rescue NoMethodError
|
20
|
+
raise ArgumentError.new( "no such property: #{attr}" )
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
self.runner.new( self ).run
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/cp/command.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module CP
|
2
|
+
class Command
|
3
|
+
include CP::Commands
|
4
|
+
include CP::Options
|
5
|
+
|
6
|
+
attr_reader :block, :name
|
7
|
+
attr_accessor :description, :summary
|
8
|
+
|
9
|
+
def initialize( name )
|
10
|
+
unless name.respond_to?( :to_sym )
|
11
|
+
raise ArgumentError.new( "parameter must be a Symbol (or respond to .to_sym)")
|
12
|
+
end
|
13
|
+
|
14
|
+
@name = name.to_sym
|
15
|
+
|
16
|
+
yield self if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute( &block )
|
20
|
+
@block = block
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/cp/commands.rb
ADDED
data/lib/cp/option.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require "optparse"
|
2
|
+
|
3
|
+
module CP
|
4
|
+
class Option
|
5
|
+
attr_accessor :allowed, :type, :block, :description, :required
|
6
|
+
attr_reader :arg, :short, :long
|
7
|
+
|
8
|
+
# see: OptionsParser#make_switch
|
9
|
+
def initialize( *args )
|
10
|
+
parsed = parse_args( args )
|
11
|
+
|
12
|
+
yield self if block_given?
|
13
|
+
|
14
|
+
# pick up any args we dropped the first time
|
15
|
+
parse_args( self.to_option_parser_args + args ) unless parsed
|
16
|
+
|
17
|
+
unless self.short || self.long
|
18
|
+
raise ArgumentError.new( "no switch given" )
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def long=( val )
|
23
|
+
set_switch( :long, val )
|
24
|
+
end
|
25
|
+
|
26
|
+
def name
|
27
|
+
if self.long
|
28
|
+
name = self.long.sub( /^-+(\[no-\])?/, '' )
|
29
|
+
else
|
30
|
+
name = self.short.sub( /^-/, '' ).sub( /\[(.-.)\]/, '\\1' )
|
31
|
+
end
|
32
|
+
name.gsub( "-", "_" ).to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
def short=( val )
|
36
|
+
set_switch( :short, val )
|
37
|
+
end
|
38
|
+
|
39
|
+
def switches
|
40
|
+
[self.short, self.long].inject( [] ) { |acc, s|
|
41
|
+
unless s.nil?
|
42
|
+
s += self.arg unless self.arg.nil?
|
43
|
+
acc << s
|
44
|
+
end
|
45
|
+
acc
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_option_parser_args
|
50
|
+
args = self.switches + [self.type, self.allowed, self.description, self.block]
|
51
|
+
args.find_all { |a| !a.nil? }
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def parse_args( args )
|
57
|
+
switch = OptionParser.new.make_switch( args ).first
|
58
|
+
if !switch.kind_of?( OptionParser::Switch )
|
59
|
+
false
|
60
|
+
else
|
61
|
+
self.allowed = args.find { |a| a.is_a?( Hash ) || a.is_a?( Array ) }
|
62
|
+
self.type = args.find { |a| a.is_a?( Class ) }
|
63
|
+
self.description = switch.desc.first rescue nil
|
64
|
+
self.block = switch.block
|
65
|
+
self.long = switch
|
66
|
+
self.short = switch
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def set_switch( which, switch )
|
71
|
+
other = self.send( [:short, :long].find_all { |s| s != which }.first )
|
72
|
+
other = other ? other + ( self.arg || "" ) : nil
|
73
|
+
|
74
|
+
unless switch.kind_of?( OptionParser::Switch )
|
75
|
+
switch = OptionParser.new.make_switch( [ switch, other ] ).first
|
76
|
+
end
|
77
|
+
|
78
|
+
unless switch.kind_of?( OptionParser::Switch ) || switch.send( which ).empty?
|
79
|
+
raise ArgumentError.new( "invalid #{which} switch: #{switch.first}" )
|
80
|
+
end
|
81
|
+
|
82
|
+
@arg = switch.arg
|
83
|
+
instance_variable_set( :"@#{which}", switch.send( which ).first )
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/cp/options.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "cmdparse"
|
3
|
+
|
4
|
+
module CP
|
5
|
+
module Runners
|
6
|
+
class CmdParse
|
7
|
+
attr_reader :runner
|
8
|
+
|
9
|
+
def initialize( app )
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
@runner = ::CmdParse::CommandParser.new
|
15
|
+
@runner.program_name = @app.name
|
16
|
+
@runner.program_version = @app.version.split( "." )
|
17
|
+
|
18
|
+
add_options( @runner, @app.options )
|
19
|
+
add_commands( @runner, @app.commands )
|
20
|
+
|
21
|
+
@runner.parse
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def add_options( target, options )
|
27
|
+
unless options.empty?
|
28
|
+
target.options = ::CmdParse::OptionParserWrapper.new do |o|
|
29
|
+
o.separator "Global Options:"
|
30
|
+
options.each { |opt| o.on( *opt.to_option_parser_args ) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_commands( target, commands )
|
36
|
+
unless commands.empty?
|
37
|
+
commands.each do |c|
|
38
|
+
cmd = ::CmdParse::Command.new( c.name.to_s, !c.commands.empty? )
|
39
|
+
cmd.description = c.description
|
40
|
+
cmd.short_desc = c.summary
|
41
|
+
|
42
|
+
cmd.set_execution_block do |args|
|
43
|
+
c.block.call( args ) if c.block
|
44
|
+
end
|
45
|
+
|
46
|
+
add_options( cmd, c.options )
|
47
|
+
add_commands( cmd, c.commands )
|
48
|
+
|
49
|
+
target.add_command( cmd )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/cp/version.rb
ADDED
data/spec/app_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
|
2
|
+
|
3
|
+
describe CP::App do
|
4
|
+
before( :each ) do
|
5
|
+
@target = CP::App.instance
|
6
|
+
end
|
7
|
+
|
8
|
+
it_should_behave_like "it accepts commands"
|
9
|
+
it_should_behave_like "it accepts options"
|
10
|
+
|
11
|
+
describe "#instance" do
|
12
|
+
it "should always return the same object" do
|
13
|
+
@target.should == CP::App.instance
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#parser" do
|
18
|
+
it "should default to CmdParser" do
|
19
|
+
@target.parser.should == CP::Parsers::CmdParse
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#run" do
|
24
|
+
it "should exist" do
|
25
|
+
@target.methods.include?( :run ).should be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not take any parameters" do
|
29
|
+
@target.method( :run ).arity.should === 0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "properties" do
|
34
|
+
[:name, :version].each do |prop_name|
|
35
|
+
it "should accept a #{prop_name} property" do
|
36
|
+
prop_val = "0.1.1"
|
37
|
+
|
38
|
+
lambda {
|
39
|
+
@target.app prop_name, prop_val
|
40
|
+
}.should change( @target, prop_name ).from( nil ).to( prop_val )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should raise a ArgumentError when setting other properties" do
|
45
|
+
lambda {
|
46
|
+
test_app.app :foo, "bar"
|
47
|
+
}.should raise_error( ArgumentError, /no such property/ )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
|
2
|
+
|
3
|
+
describe CP::Command do
|
4
|
+
before( :each ) do
|
5
|
+
@target = test_command
|
6
|
+
end
|
7
|
+
|
8
|
+
it_should_behave_like "it accepts commands"
|
9
|
+
it_should_behave_like "it accepts options"
|
10
|
+
|
11
|
+
describe "attributes" do
|
12
|
+
[
|
13
|
+
[:description, "description"],
|
14
|
+
[:summary, "summary"],
|
15
|
+
[:execute, lambda {}],
|
16
|
+
].each { |(attr, val)|
|
17
|
+
it "defines a ##{attr} accessor" do
|
18
|
+
lambda {
|
19
|
+
@target.send( :"#{attr}=", val )
|
20
|
+
}.should change( @target, attr ).from( @target.send( attr ) ).to( val )
|
21
|
+
end
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#new" do
|
26
|
+
it "takes one parameter" do
|
27
|
+
CP::Command.instance_method( :initialize ).arity.should === 1
|
28
|
+
end
|
29
|
+
|
30
|
+
it "takes a symbol" do
|
31
|
+
lambda {
|
32
|
+
CP::Command.new( 1 )
|
33
|
+
}.should raise_error( ArgumentError, /Symbol/ )
|
34
|
+
end
|
35
|
+
|
36
|
+
it "saves the param as the name" do
|
37
|
+
CP::Command.new( :test ).name.should === :test
|
38
|
+
end
|
39
|
+
|
40
|
+
it "yields itself" do
|
41
|
+
yielded = nil
|
42
|
+
c = CP::Command.new( :test ) do |cmd|
|
43
|
+
yielded = cmd
|
44
|
+
end
|
45
|
+
c.should === yielded
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/cp_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
|
2
|
+
|
3
|
+
describe CP do
|
4
|
+
describe "methods" do
|
5
|
+
def assert_method_added( method )
|
6
|
+
Object.new.methods.include?( method ).should be_false
|
7
|
+
App.new.methods.include?( method ).should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should define a app method" do
|
11
|
+
assert_method_added :app
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should define a command method" do
|
15
|
+
assert_method_added :command
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should define an option method" do
|
19
|
+
assert_method_added :option
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not define class methods" do
|
23
|
+
Object.class.methods.include?( :command ).should be_false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/spec/option_spec.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
|
2
|
+
|
3
|
+
describe CP::Option do
|
4
|
+
before( :each ) do
|
5
|
+
@target = CP::Option.new( "-x" )
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
describe "attributes" do
|
10
|
+
[
|
11
|
+
[:allowed, ["foo", "bar"]],
|
12
|
+
[:block, lambda{}],
|
13
|
+
[:description, "description"],
|
14
|
+
[:long, "--short"],
|
15
|
+
[:required, true],
|
16
|
+
[:short, "-s"],
|
17
|
+
[:type, String]
|
18
|
+
].each { |(attr, val)|
|
19
|
+
it "defines a ##{attr} accessor" do
|
20
|
+
lambda {
|
21
|
+
@target.send( :"#{attr}=", val )
|
22
|
+
}.should change( @target, attr ).from( @target.send( attr ) ).to( val )
|
23
|
+
end
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "incompatible switch types" do
|
28
|
+
it "disallows them from accessors" do
|
29
|
+
lambda {
|
30
|
+
@target.long = "--switch FOO" # mandatory arg
|
31
|
+
@target.short = "-s[=FOO]" # optional arg
|
32
|
+
}.should raise_error( ArgumentError, /incompatible/i )
|
33
|
+
end
|
34
|
+
|
35
|
+
it "disallows them in the contructor" do
|
36
|
+
lambda {
|
37
|
+
CP::Option.new( "--switch FOO", "-s[=FOO]" )
|
38
|
+
}.should raise_error( ArgumentError, /incompatible/i )
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#name" do
|
43
|
+
it "returns a symbol" do
|
44
|
+
@target.name.is_a?( Symbol )
|
45
|
+
end
|
46
|
+
|
47
|
+
it "uses the long switch" do
|
48
|
+
@target.long = "--long"
|
49
|
+
@target.name.should === :long
|
50
|
+
end
|
51
|
+
|
52
|
+
it "uses the short switch" do
|
53
|
+
@target.short = "-s"
|
54
|
+
@target.name.should === :s
|
55
|
+
end
|
56
|
+
|
57
|
+
it "prefers the long switch" do
|
58
|
+
@target.short = "-s"
|
59
|
+
@target.long = "--long"
|
60
|
+
@target.name.should === :long
|
61
|
+
end
|
62
|
+
|
63
|
+
it "ignores the optional part of a boolean switch" do
|
64
|
+
@target.long = "--[no-]foo"
|
65
|
+
@target.name.should === :foo
|
66
|
+
end
|
67
|
+
|
68
|
+
it "ignores the brackets in a range switch" do
|
69
|
+
@target.short = "-[a-z]"
|
70
|
+
@target.name.should === :"a_z"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "converts dashes to underscores" do
|
74
|
+
@target.long = "--multi-word"
|
75
|
+
@target.name.should === :multi_word
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#new" do
|
80
|
+
it "accepts args like OptionParser.make_switch" do
|
81
|
+
lambda {
|
82
|
+
CP::Option.new( "-s" )
|
83
|
+
CP::Option.new( "-s", "--switch" )
|
84
|
+
CP::Option.new( "-s", "--switch[=OPTIONAL]" )
|
85
|
+
CP::Option.new( "-s", "--switch[=OPTIONAL]", "Do something switchy" )
|
86
|
+
CP::Option.new( "-s", "--switch[=OPTIONAL]", String, "Do something switchy" )
|
87
|
+
}.should_not raise_error
|
88
|
+
end
|
89
|
+
|
90
|
+
it "requires a switch" do
|
91
|
+
lambda {
|
92
|
+
CP::Option.new( "Description of the option" )
|
93
|
+
}.should raise_error( ArgumentError )
|
94
|
+
end
|
95
|
+
|
96
|
+
it "sets the description from arguments" do
|
97
|
+
CP::Option.new( "-s", "description" ).description.should === "description"
|
98
|
+
end
|
99
|
+
it "sets the short switch from arguments" do
|
100
|
+
CP::Option.new( "-s" ).short.should === "-s"
|
101
|
+
end
|
102
|
+
it "sets the long switch from arguments" do
|
103
|
+
CP::Option.new( "--switch" ).long.should === "--switch"
|
104
|
+
end
|
105
|
+
it "sets the type from arguments" do
|
106
|
+
CP::Option.new( "-s", String ).type.should == String
|
107
|
+
end
|
108
|
+
it "sets the block from arguments" do
|
109
|
+
ran = false
|
110
|
+
CP::Option.new( "-s", lambda{ ran = true } ).block.call
|
111
|
+
ran.should be_true
|
112
|
+
end
|
113
|
+
|
114
|
+
it "yields itself" do
|
115
|
+
yielded = nil
|
116
|
+
o = CP::Option.new( "-s" ) do |opt|
|
117
|
+
yielded = opt
|
118
|
+
end
|
119
|
+
o.should === yielded
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "combined arguments and attribute setting" do
|
123
|
+
it "doesn't raise an error if switches are set later" do
|
124
|
+
lambda {
|
125
|
+
CP::Option.new( "Description of the option" ) do |opt|
|
126
|
+
opt.short = "-v"
|
127
|
+
end
|
128
|
+
}.should_not raise_error( ArgumentError )
|
129
|
+
end
|
130
|
+
|
131
|
+
it "saves early args" do
|
132
|
+
o = CP::Option.new( String, "Do something switchy" ) { |o| o.short = "-s" }
|
133
|
+
o.type.should == String
|
134
|
+
o.description.should === "Do something switchy"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#long=" do
|
140
|
+
it "parses the option, separating the option argument" do
|
141
|
+
o = CP::Option.new do |opt|
|
142
|
+
opt.long = "--switch VALUE"
|
143
|
+
end
|
144
|
+
o.arg.should == " VALUE"
|
145
|
+
o.long.should == "--switch"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#short=" do
|
150
|
+
it "parses the option, separating the option argument" do
|
151
|
+
o = CP::Option.new do |opt|
|
152
|
+
opt.short = "-s VALUE"
|
153
|
+
end
|
154
|
+
o.arg.should == " VALUE"
|
155
|
+
o.short.should == "-s"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "#to_option_parser_args" do
|
160
|
+
it "includes switch with args" do
|
161
|
+
@target.short = "-s FOO"
|
162
|
+
@target.long = "--switch FOO"
|
163
|
+
@target.to_option_parser_args.include?( "-s FOO" ).should be_true
|
164
|
+
@target.to_option_parser_args.include?( "--switch FOO" ).should be_true
|
165
|
+
end
|
166
|
+
|
167
|
+
it "returns an array" do
|
168
|
+
@target.to_option_parser_args.should be_a( Array )
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
|
2
|
+
|
3
|
+
describe CP::Runners::CmdParse do
|
4
|
+
before( :each ) do
|
5
|
+
@target = test_app.parser
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#instance" do
|
9
|
+
it "should always return the same object" do
|
10
|
+
@target.should == CP::App.instance
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#parser" do
|
15
|
+
it "should default to CmdParser" do
|
16
|
+
@target.parser.should == CP::Parsers::CmdParse
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#run" do
|
21
|
+
it "should exist" do
|
22
|
+
@target.methods.include?( :run ).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should not take any parameters" do
|
26
|
+
@target.method( :run ).arity.should === 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "properties" do
|
31
|
+
[:name, :version].each do |prop_name|
|
32
|
+
it "should accept a #{prop_name} property" do
|
33
|
+
prop_val = "0.1.1"
|
34
|
+
|
35
|
+
lambda {
|
36
|
+
@target.app prop_name, prop_val
|
37
|
+
}.should change( @target, prop_name ).from( nil ).to( prop_val )
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should raise a ArgumentError when setting other properties" do
|
42
|
+
lambda {
|
43
|
+
test_app.app :foo, "bar"
|
44
|
+
}.should raise_error( ArgumentError, /no such property/ )
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
shared_examples_for "it accepts commands" do
|
2
|
+
describe "#command" do
|
3
|
+
it "should return a Command" do
|
4
|
+
@target.command( :test ).should be_an_instance_of( CP::Command )
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#commands" do
|
9
|
+
it "should return an array" do
|
10
|
+
@target.commands.should be_an_instance_of( Array )
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should increase with each defined command" do
|
14
|
+
lambda {
|
15
|
+
@target.command( :test )
|
16
|
+
}.should change(){ @target.commands.length}.by( 1 )
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should include each defined command" do
|
20
|
+
@target.commands.include?( @target.command( :test ) ).should be_true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
shared_examples_for "it accepts options" do
|
26
|
+
describe "#option" do
|
27
|
+
it "should return an Option" do
|
28
|
+
@target.option( "-s" ).should be_an_instance_of( CP::Option )
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#options" do
|
33
|
+
it "should return an array" do
|
34
|
+
@target.options.should be_an_instance_of( Array )
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should increase with each defined option" do
|
38
|
+
lambda {
|
39
|
+
@target.option( "-s" )
|
40
|
+
}.should change(){ @target.options.length}.by( 1 )
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should include each defined option" do
|
44
|
+
@target.options.include?( @target.option( "-s" ) ).should be_true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# from http://blog.ardes.com/2006/12/11/testing-singletons-with-ruby
|
2
|
+
|
3
|
+
require "singleton"
|
4
|
+
|
5
|
+
class << Singleton
|
6
|
+
def included_with_reset( klass )
|
7
|
+
included_without_reset( klass )
|
8
|
+
class << klass
|
9
|
+
def reset_instance
|
10
|
+
Singleton.send :__init__, self
|
11
|
+
self
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
alias_method :included_without_reset, :included
|
16
|
+
alias_method :included, :included_with_reset
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "singleton_helper" )
|
2
|
+
require File.join(File.dirname(__FILE__), "shared_helper")
|
3
|
+
|
4
|
+
# ensure we're at the front of the load path
|
5
|
+
$:.unshift( File.join( File.dirname( __FILE__ ), "..", "lib" ) )
|
6
|
+
|
7
|
+
# include the gem
|
8
|
+
require "cp"
|
9
|
+
|
10
|
+
# reset the App singleton before each test
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.before( :each ) {
|
13
|
+
CP::App.reset_instance
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
class App
|
19
|
+
include CP
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_app
|
23
|
+
a = App.new
|
24
|
+
yield a if block_given?
|
25
|
+
a
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_command
|
29
|
+
c = CP::Command.new( :test )
|
30
|
+
yield c if block_given?
|
31
|
+
c
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: 6
|
5
|
+
version: 0.0.1.pre1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rick Fletcher
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-06-08 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: cmdparse
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.0.2
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: cmdparse
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.0.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
description: CP provides a less verbose API for the CmdParse gem.
|
38
|
+
email:
|
39
|
+
- fletch@pobox.com
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
files:
|
47
|
+
- .gitignore
|
48
|
+
- Gemfile
|
49
|
+
- Rakefile
|
50
|
+
- cp.gemspec
|
51
|
+
- examples/net.rb
|
52
|
+
- lib/cp.rb
|
53
|
+
- lib/cp/app.rb
|
54
|
+
- lib/cp/command.rb
|
55
|
+
- lib/cp/commands.rb
|
56
|
+
- lib/cp/option.rb
|
57
|
+
- lib/cp/options.rb
|
58
|
+
- lib/cp/runners/cmd_parse.rb
|
59
|
+
- lib/cp/version.rb
|
60
|
+
- spec/app_spec.rb
|
61
|
+
- spec/command_spec.rb
|
62
|
+
- spec/cp_spec.rb
|
63
|
+
- spec/option_spec.rb
|
64
|
+
- spec/options_spec.rb
|
65
|
+
- spec/runners/cmd_parse_spec.rb
|
66
|
+
- spec/support/shared_helper.rb
|
67
|
+
- spec/support/singleton_helper.rb
|
68
|
+
- spec/support/spec_helper.rb
|
69
|
+
homepage: ""
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.3.1
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.8.4
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: An alternative API for CmdParse
|
96
|
+
test_files:
|
97
|
+
- spec/app_spec.rb
|
98
|
+
- spec/command_spec.rb
|
99
|
+
- spec/cp_spec.rb
|
100
|
+
- spec/option_spec.rb
|
101
|
+
- spec/options_spec.rb
|
102
|
+
- spec/runners/cmd_parse_spec.rb
|
103
|
+
- spec/support/shared_helper.rb
|
104
|
+
- spec/support/singleton_helper.rb
|
105
|
+
- spec/support/spec_helper.rb
|