ccp 0.1.0

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 ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'must', '>= 0.2.5'
4
+ gem 'dsl_accessor', '>= 0.4.0'
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/ccp.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ccp/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ccp"
7
+ s.version = Ccp::VERSION
8
+ s.authors = ["maiha"]
9
+ s.email = ["maiha@wota.jp"]
10
+ s.homepage = "http://github.com/maiha/ccp"
11
+ s.summary = %q{A Ruby library for Composite Command Programming}
12
+ s.description = %q{CCP}
13
+
14
+ s.rubyforge_project = "ccp"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "activesupport"
22
+ s.add_dependency "must", ">= 0.2.5"
23
+ s.add_dependency "dsl_accessor", ">= 0.4.0"
24
+
25
+ s.add_development_dependency "rspec"
26
+ end
data/lib/ccp.rb ADDED
@@ -0,0 +1,11 @@
1
+ require "must"
2
+ require "active_support/core_ext"
3
+ require "ccp/version"
4
+ require "ccp/data"
5
+
6
+ module Ccp
7
+ autoload :Colorize, 'ccp/colorize'
8
+ autoload :Commands, 'ccp/commands'
9
+ autoload :Invokers, 'ccp/invokers'
10
+ autoload :Receivers, 'ccp/receivers'
11
+ end
@@ -0,0 +1,13 @@
1
+ module Ccp
2
+ module Colorize
3
+ def colorize(text, ansi); "#{ansi}#{text}\e[0m"; end
4
+ def red (text); colorize(text, "\e[31m"); end
5
+ def green (text); colorize(text, "\e[32m"); end
6
+ def yellow(text); colorize(text, "\e[33m"); end
7
+ def blue (text); colorize(text, "\e[34m"); end
8
+ def pink (text); colorize(text, "\e[35m"); end
9
+ def aqua (text); colorize(text, "\e[36m"); end
10
+
11
+ extend self
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Ccp
2
+ module Commands
3
+ autoload :CommandNotFound, 'ccp/commands/command_not_found'
4
+ autoload :Composite , 'ccp/commands/composite'
5
+ autoload :Executable , 'ccp/commands/executable'
6
+ autoload :Receivable , 'ccp/commands/receivable'
7
+ autoload :RuntimeArgs , 'ccp/commands/runtime_args'
8
+ autoload :Commentable , 'ccp/commands/commentable'
9
+ autoload :Core , 'ccp/commands/core'
10
+ autoload :Resolvable , 'ccp/commands/resolvable'
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ module Ccp
2
+ module Commands
3
+ CommandNotFound = Class.new(RuntimeError)
4
+ end
5
+ end
6
+
@@ -0,0 +1,21 @@
1
+ module Ccp
2
+ module Commands
3
+ module Commentable
4
+ def MEMO(*messages)
5
+ from = caller.is_a?(Array) ? caller.first : self.class
6
+ receiver.comment("MEMO: #{_build_comment(*messages)}\n #{from}")
7
+ end
8
+
9
+ def TODO(*messages)
10
+ from = caller.is_a?(Array) ? caller.first : self.class
11
+ receiver.comment("TODO: #{_build_comment(*messages)}\n #{from}", :warn)
12
+ end
13
+
14
+ private
15
+ def _build_comment(*objs)
16
+ objs = objs.first if objs.size == 1
17
+ objs.is_a?(String) ? objs : objs.inspect
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,93 @@
1
+ module Ccp
2
+ module Commands
3
+ module Composite
4
+ def self.included(base)
5
+ base.class_eval do
6
+ extend ClassMethods
7
+ end
8
+ end
9
+
10
+ CommandClass = Struct.new(:klass, :args, :cond) unless defined?(CommandClass)
11
+ class CommandClass
12
+ def inspect
13
+ name = klass.name.split(/Commands::/,2).last
14
+ "<%s args=%s cond=%s>" % [name, args.inspect, cond.inspect]
15
+ end
16
+
17
+ def to_s
18
+ inspect
19
+ end
20
+ end
21
+
22
+ ######################################################################
23
+ ### Class Methods
24
+
25
+ module ClassMethods
26
+ include Resolvable
27
+
28
+ def prepend_command(klass, *args, &block)
29
+ commands.unshift CommandClass.new(resolve(klass), args, block)
30
+ end
31
+
32
+ def append_command(klass, *args, &block)
33
+ klass = resolve(klass)
34
+ if commands.find{|cc| cc.klass == klass}
35
+ # ignore: already added
36
+ else
37
+ commands << CommandClass.new(klass, args, block)
38
+ end
39
+ end
40
+
41
+ def command(*args)
42
+ append_command(*args)
43
+ end
44
+
45
+ def commands
46
+ @commands ||= []
47
+ end
48
+ end
49
+
50
+ ######################################################################
51
+ ### Instance Methods
52
+
53
+ include Core
54
+ include Enumerable
55
+
56
+ ######################################################################
57
+ ### Enumerable
58
+
59
+ def <<(command)
60
+ command = command.new if command.is_a?(Class) and command.ancestors.include?(Core)
61
+ command.must(Core)
62
+ commands << command
63
+ end
64
+
65
+ def commands
66
+ @commands ||= build_commands.must(Array)
67
+ end
68
+
69
+ ######################################################################
70
+ ### Commands
71
+
72
+ def execute
73
+ benchmark
74
+ end
75
+
76
+ def benchmark
77
+ pre if respond_to?(:pre)
78
+ commands.each(&:benchmark)
79
+ post if respond_to?(:post)
80
+ end
81
+
82
+ private
83
+ def build_commands
84
+ array = self.class.commands.select{|c| c.cond.nil? or instance_eval(&c.cond)}
85
+ array.map{|c|
86
+ c = c.klass.new(*c.args)
87
+ c.receiver = receiver
88
+ c
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,14 @@
1
+ module Ccp
2
+ module Commands
3
+ module Core
4
+ include Receivable
5
+ include Executable
6
+ include Commentable
7
+
8
+ def inspect
9
+ klass_name = self.class.name.to_s.split(/::/).last
10
+ "#<#{klass_name}>"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Ccp
2
+ module Commands
3
+ module Executable
4
+
5
+ ### Command
6
+
7
+ def execute
8
+ end
9
+
10
+ ### Profiling
11
+
12
+ def benchmark(method = :execute)
13
+ receiver.profile(self, method)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Ccp
2
+ module Commands
3
+ module Receivable
4
+ ######################################################################
5
+ ### Receiver Methods
6
+
7
+ def receiver
8
+ @receiver ||= Ccp::Receivers::None.new
9
+ end
10
+
11
+ def receiver=(value)
12
+ @receiver = value.must(Ccp::Receivers::Base)
13
+ end
14
+
15
+ ######################################################################
16
+ ### Delegate Methods
17
+
18
+ delegate :data, :data?, :to=>"receiver"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Ccp
2
+ module Commands
3
+ module Resolvable
4
+ def resolve(klass)
5
+ klass.must.coerced(Class, Module) {
6
+ raise CommandNotFound, "expected Class or Module, but got #{klass.class}"
7
+ }
8
+
9
+ if klass.ancestors.include?(Commands::Core)
10
+ return klass # ok
11
+ end
12
+
13
+ if klass.must.duck?("#execute")
14
+ # dynamically assign core
15
+ klass.class_eval{ include Commands::Core }
16
+ return klass
17
+ end
18
+
19
+ raise CommandNotFound, "#{klass} found but it misses 'execute' method"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+ # map options to data
3
+
4
+ module Ccp
5
+ module Commands
6
+ class RuntimeArgs
7
+ include Core
8
+
9
+ def initialize(options = {})
10
+ @options = (options || {}).must(Hash)
11
+ end
12
+
13
+ def execute
14
+ @options.each_pair do |key, val|
15
+ data[key] = val
16
+ end
17
+ end
18
+
19
+ def inspect
20
+ super.sub(/>$/, " #{@options.inspect}>")
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/ccp/data.rb ADDED
@@ -0,0 +1,107 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'pathname'
4
+
5
+ module Ccp
6
+ module Data
7
+ NotDefined = Class.new(RuntimeError)
8
+
9
+ class KVS
10
+ delegate :[]=, :to=>"@hash"
11
+
12
+ LazyValue = Struct.new(:block)
13
+
14
+ class Default
15
+ def initialize(kvs)
16
+ @kvs = kvs
17
+ end
18
+
19
+ def []=(key, val)
20
+ return if @kvs.exist?(key)
21
+ @kvs[key] = val
22
+ end
23
+
24
+ def regsiter_lazy(key, block)
25
+ return if @kvs.exist?(key)
26
+ raise ArgumentError, "Lazy default value needs block: #{key}" unless block
27
+ @kvs[key] = LazyValue.new(block)
28
+ end
29
+ end
30
+
31
+ def initialize
32
+ @hash = {}
33
+ @default = Default.new(self)
34
+ end
35
+
36
+ ######################################################################
37
+ ### Default values
38
+
39
+ def default(key = nil, &block)
40
+ if key
41
+ @default.regsiter_lazy(key, block)
42
+ else
43
+ @default
44
+ end
45
+ end
46
+
47
+ ######################################################################
48
+ ### Accessor
49
+
50
+ def [](key)
51
+ if exist?(key)
52
+ return load(key)
53
+ else
54
+ from = caller.is_a?(Array) ? caller.first : self.class
55
+ raise NotDefined, "'#{key}' is not initialized\n#{from}"
56
+ end
57
+ end
58
+
59
+ ######################################################################
60
+ ### Testing
61
+
62
+ def exist?(key)
63
+ @hash.has_key?(key)
64
+ end
65
+
66
+ def set?(key)
67
+ !! (exist?(key) && self[key])
68
+ end
69
+
70
+ def check(key, type)
71
+ self[key].must.struct(type) {
72
+ summary = self[key].inspect
73
+ summary = summary[0,200] + "..." if summary.size > 200
74
+ raise TypeError, "'#{key}' expects '#{type.inspect}', but got #{summary}"
75
+ }
76
+ end
77
+
78
+ ######################################################################
79
+ ### Utils
80
+
81
+ def path(key)
82
+ self[key].must.coerced(Pathname, String=>proc{|i| Pathname(i)})
83
+ end
84
+
85
+ def inspect
86
+ keys = @hash.keys.map(&:to_s).sort.join(',')
87
+ "{#{keys}}"
88
+ end
89
+
90
+ private
91
+ def load(key)
92
+ # LazyValue should be evaluated at runtime
93
+ value = @hash[key]
94
+ value = value.block.call if value.is_a?(LazyValue)
95
+ return value
96
+ end
97
+ end
98
+
99
+ def data
100
+ @data ||= KVS.new
101
+ end
102
+
103
+ def data?(key)
104
+ data.set?(key)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,5 @@
1
+ module Ccp
2
+ module Invokers
3
+ autoload :Base , 'ccp/invokers/base'
4
+ end
5
+ end
@@ -0,0 +1,62 @@
1
+ require 'logger'
2
+
3
+ module Ccp
4
+ module Invokers
5
+ class Base
6
+ include Commands::Composite
7
+
8
+ dsl_accessor :receiver, Receivers::Base
9
+ delegate :show_profiles, :profiles, :to=>"receiver"
10
+ delegate :show_comments, :comments, :to=>"receiver"
11
+
12
+ DEFAULT_OPTIONS = {
13
+ :profile => false,
14
+ :comment => true,
15
+ }
16
+
17
+ ######################################################################
18
+ ### Instance Methods
19
+
20
+ def initialize(options = nil)
21
+ self.receiver = self.class.receiver.new
22
+ self.class.prepend_command Commands::RuntimeArgs, options
23
+ set_default_options
24
+ end
25
+
26
+ def set_default_options
27
+ self.class::DEFAULT_OPTIONS.each_pair do |key,val|
28
+ data.default[key] = val
29
+ end
30
+ data.default(:logger) { Logger.new($stderr) }
31
+ end
32
+
33
+ def execute
34
+ benchmark
35
+ end
36
+
37
+ def benchmark
38
+ before
39
+ super
40
+ after
41
+ return true
42
+ end
43
+
44
+ def receiver
45
+ @receiver.must(Receivers::Base)
46
+ end
47
+
48
+ def receiver=(value)
49
+ @receiver = value.must(Receivers::Base)
50
+ end
51
+
52
+ private
53
+ def before
54
+ end
55
+
56
+ def after
57
+ show_profiles if data?(:profile)
58
+ show_comments if data?(:comment)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,8 @@
1
+ module Ccp
2
+ module Receivers
3
+ autoload :Base , 'ccp/receivers/base'
4
+ autoload :None , 'ccp/receivers/none'
5
+ autoload :Commentable , 'ccp/receivers/commentable'
6
+ autoload :Profileable , 'ccp/receivers/profileable'
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ module Ccp
2
+ module Receivers
3
+ class Base
4
+ include Ccp::Data
5
+ include Profileable
6
+ include Commentable
7
+
8
+ def inspect
9
+ klass_name = self.class.name.to_s.split(/::/).last
10
+
11
+ "#<Receivers::#{klass_name} data:#{data.inspect}>"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ module Ccp
2
+ module Receivers
3
+ module Commentable
4
+
5
+ Comment = Struct.new(:text, :level)
6
+ class Comment
7
+ include Colorize
8
+ def colorized
9
+ case level
10
+ when :warn ; yellow(text)
11
+ when :error, :fatal ; red(text)
12
+ when :info ; green(text)
13
+ else ; text
14
+ end
15
+ end
16
+ end
17
+
18
+ def comment(text, level = nil)
19
+ comments[text] ||= Comment.new(text, level)
20
+ end
21
+
22
+ def comments
23
+ @comments ||= ActiveSupport::OrderedHash.new
24
+ end
25
+
26
+ def show_comments(*args)
27
+ opts = Optionize.new(args, :output)
28
+ output = opts[:output] || $stderr
29
+ comments.each_value do |comment|
30
+ output.puts comment.colorized
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ module Ccp
2
+ module Receivers
3
+ class None < Base
4
+ def self.new
5
+ @instance ||= super
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,57 @@
1
+ module Ccp
2
+ module Receivers
3
+ module Profileable
4
+ include Colorize
5
+
6
+ Profile = Struct.new(:target, :method, :time)
7
+ class Profile
8
+ def name
9
+ target.is_a?(Class) ? "#{target.name}.#{method}" : "#{target.class}##{method}"
10
+ end
11
+
12
+ def profile(total)
13
+ "[%4.1f%%] %.7f %s" % [(time*100/total), time, name]
14
+ end
15
+ end
16
+
17
+ def profile(target, method)
18
+ start = Time.new
19
+ target.pre if target.must.duck?(:pre)
20
+ target.__send__(method)
21
+ target.post if target.must.duck?(:post)
22
+ target.must.duck(:no_bench) {
23
+ profiles << Profile.new(target, method, (Time.new - start).to_f)
24
+ }
25
+ end
26
+
27
+ def profiles
28
+ @profiles ||= []
29
+ end
30
+
31
+ def show_profiles(*args, &block)
32
+ opts = Optionize.new(args, :benchs, :output)
33
+ benchs = opts[:benchs] || profiles
34
+ output = opts[:output] || $stderr
35
+
36
+ # search worst item
37
+ total = 0
38
+ worst = nil
39
+ benchs.each do |bench|
40
+ total += bench.time
41
+ worst = bench if !worst or bench.time > worst.time
42
+ end
43
+
44
+ benchs.each do |bench|
45
+ colorize = (bench == worst) ? :pink : :aqua
46
+ profiled = __send__(colorize, bench.profile(total))
47
+ if block
48
+ block.call(profiled)
49
+ else
50
+ output.puts profiled
51
+ end
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,3 @@
1
+ module Ccp
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Commands::Core do
4
+ subject { Object.new.extend Ccp::Commands::Core }
5
+
6
+ # data container
7
+ it { should respond_to(:data?) }
8
+ it { should respond_to(:data) }
9
+ its(:data) { should be_kind_of(Ccp::Data::KVS) }
10
+
11
+ # executable
12
+ it { should respond_to(:execute) }
13
+ it { should respond_to(:benchmark) }
14
+
15
+ # receivable
16
+ it { should respond_to(:receiver) }
17
+ its(:receiver) { should be_kind_of(Ccp::Receivers::Base) }
18
+ end
@@ -0,0 +1,85 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Commands::Composite do
4
+ module Breadcrumbing
5
+ BREADCRUMBS = []
6
+
7
+ def this
8
+ "%s#%s" % [self.class.name, caller[0].to_s.scan(/`(.*?)'/).first]
9
+ end
10
+
11
+ def breadcrumbs
12
+ BREADCRUMBS
13
+ end
14
+ end
15
+
16
+ class Cmd1
17
+ include Ccp::Commands::Core
18
+ include Breadcrumbing
19
+
20
+ def execute
21
+ breadcrumbs << this
22
+ data[:foo] = []
23
+ end
24
+
25
+ def post
26
+ breadcrumbs << this
27
+ end
28
+ end
29
+
30
+ class Cmd2
31
+ include Ccp::Commands::Core
32
+ include Breadcrumbing
33
+
34
+ def pre
35
+ breadcrumbs << this
36
+ end
37
+
38
+ def execute
39
+ breadcrumbs << this
40
+ data[:foo] << "cmd2"
41
+ end
42
+
43
+ def post
44
+ breadcrumbs << this
45
+ end
46
+ end
47
+
48
+ class Cmd3
49
+ include Ccp::Commands::Core
50
+ include Breadcrumbing
51
+
52
+ def pre
53
+ breadcrumbs << this
54
+ end
55
+
56
+ def execute
57
+ breadcrumbs << this
58
+ data[:foo] << "cmd3"
59
+ end
60
+ end
61
+
62
+ class Program
63
+ include Ccp::Commands::Composite
64
+
65
+ command Cmd1
66
+ command Cmd2
67
+ command Cmd3
68
+ end
69
+
70
+ subject { Program.new }
71
+
72
+ it { should be_kind_of(Ccp::Commands::Core) }
73
+
74
+ it "should call sub commands's {pre,execute,post} in declared order" do
75
+ Breadcrumbing::BREADCRUMBS.clear
76
+ subject.execute
77
+ Breadcrumbing::BREADCRUMBS.should ==
78
+ ["Cmd1#execute", "Cmd1#post", "Cmd2#pre", "Cmd2#execute", "Cmd2#post", "Cmd3#pre", "Cmd3#execute"]
79
+ end
80
+
81
+ it "should share same data storage in each sub commands" do
82
+ subject.execute
83
+ subject.data[:foo].should == ["cmd2", "cmd3"]
84
+ end
85
+ end
data/spec/data_spec.rb ADDED
@@ -0,0 +1,129 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Data::KVS do
4
+ ######################################################################
5
+ ### Accessor
6
+
7
+ it "should behave like hash" do
8
+ subject[:foo] = 1
9
+ subject[:foo].should == 1
10
+ end
11
+
12
+ describe "#[]" do
13
+ it "should raise NotDefined if no data exist for the key" do
14
+ lambda {
15
+ subject[:foo]
16
+ }.should raise_error(Ccp::Data::NotDefined)
17
+ end
18
+ end
19
+
20
+ describe "#[]=" do
21
+ it "can override values" do
22
+ subject[:foo] = 1
23
+ subject[:foo] = 2
24
+ subject[:foo].should == 2
25
+ end
26
+ end
27
+
28
+ ######################################################################
29
+ ### Testing
30
+
31
+ describe "#exist?" do
32
+ it "should return true if the value is set" do
33
+ subject[:foo] = 1
34
+ subject.exist?(:foo).should == true
35
+ end
36
+
37
+ it "should return false if the value is not set" do
38
+ subject.exist?(:foo).should == false
39
+ end
40
+ end
41
+
42
+ describe "#set?" do
43
+ it "should return true if the value is set and not (nil|false)" do
44
+ subject[:foo] = 0
45
+ subject.set?(:foo).should == true
46
+
47
+ subject.default[:bar] = 0
48
+ subject.set?(:bar).should == true
49
+
50
+ subject.default(:baz) { 0 }
51
+ subject.set?(:baz).should == true
52
+ end
53
+
54
+ it "should return false if the value is set but (nil|false)" do
55
+ subject[:foo] = nil
56
+ subject.set?(:foo).should == false
57
+
58
+ subject[:foo] = false
59
+ subject.set?(:foo).should == false
60
+ end
61
+ end
62
+
63
+ describe "#check" do
64
+ it "should satisfy its type" do
65
+ subject[:foo] = 1
66
+ lambda {
67
+ subject.check(:foo, Integer)
68
+ }.should_not raise_error
69
+ end
70
+
71
+ it "should satisfy its struct" do
72
+ subject[:foo] = {:a => "text"}
73
+ lambda {
74
+ subject.check(:foo, {Symbol => String})
75
+ }.should_not raise_error
76
+ end
77
+
78
+ it "should raise TypeError if not satisfied" do
79
+ subject[:foo] = {:a => "text"}
80
+ lambda {
81
+ subject.check(:foo, Integer)
82
+ }.should raise_error(TypeError)
83
+ end
84
+ end
85
+
86
+ ######################################################################
87
+ ### Default values
88
+
89
+ describe "#default" do
90
+ it "should set default value" do
91
+ subject.default[:foo] = 1
92
+ subject.exist?(:foo).should == true
93
+ subject[:foo].should == 1
94
+ end
95
+
96
+ it "should be overriden by []=" do
97
+ subject.default[:foo] = 1
98
+ subject[:foo] = 2
99
+ subject[:foo].should == 2
100
+ end
101
+
102
+ it "should not affect data when already set" do
103
+ subject[:foo] = 1
104
+ subject.default[:foo] = 2
105
+ subject[:foo].should == 1
106
+ end
107
+ end
108
+
109
+ describe "#default(&block)" do
110
+ it "should set lazy default value" do
111
+ @a = 1
112
+ subject.default(:foo) { @a }
113
+ @a = 2
114
+ subject[:foo].should == 2
115
+ end
116
+ end
117
+
118
+ ######################################################################
119
+ ### Utils
120
+
121
+ describe "#path" do
122
+ it "should return pathname" do
123
+ subject[:foo] = __FILE__
124
+ subject.path(:foo).should be_kind_of(Pathname)
125
+ subject.path(:foo).basename.should == Pathname("data_spec.rb")
126
+ end
127
+ end
128
+ end
129
+
@@ -0,0 +1,5 @@
1
+ # $:.unshift File.expand_path('..', __FILE__)
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'rspec'
5
+ require 'ccp'
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ccp
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - maiha
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-02-09 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: must
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 29
44
+ segments:
45
+ - 0
46
+ - 2
47
+ - 5
48
+ version: 0.2.5
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: dsl_accessor
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 15
60
+ segments:
61
+ - 0
62
+ - 4
63
+ - 0
64
+ version: 0.4.0
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: rspec
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id004
81
+ description: CCP
82
+ email:
83
+ - maiha@wota.jp
84
+ executables: []
85
+
86
+ extensions: []
87
+
88
+ extra_rdoc_files: []
89
+
90
+ files:
91
+ - .gitignore
92
+ - Gemfile
93
+ - README
94
+ - Rakefile
95
+ - ccp.gemspec
96
+ - lib/ccp.rb
97
+ - lib/ccp/colorize.rb
98
+ - lib/ccp/commands.rb
99
+ - lib/ccp/commands/command_not_found.rb
100
+ - lib/ccp/commands/commentable.rb
101
+ - lib/ccp/commands/composite.rb
102
+ - lib/ccp/commands/core.rb
103
+ - lib/ccp/commands/executable.rb
104
+ - lib/ccp/commands/receivable.rb
105
+ - lib/ccp/commands/resolvable.rb
106
+ - lib/ccp/commands/runtime_args.rb
107
+ - lib/ccp/data.rb
108
+ - lib/ccp/invokers.rb
109
+ - lib/ccp/invokers/base.rb
110
+ - lib/ccp/receivers.rb
111
+ - lib/ccp/receivers/base.rb
112
+ - lib/ccp/receivers/commentable.rb
113
+ - lib/ccp/receivers/none.rb
114
+ - lib/ccp/receivers/profileable.rb
115
+ - lib/ccp/version.rb
116
+ - spec/commands_spec.rb
117
+ - spec/composite_spec.rb
118
+ - spec/data_spec.rb
119
+ - spec/spec_helper.rb
120
+ has_rdoc: true
121
+ homepage: http://github.com/maiha/ccp
122
+ licenses: []
123
+
124
+ post_install_message:
125
+ rdoc_options: []
126
+
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ hash: 3
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 3
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ requirements: []
148
+
149
+ rubyforge_project: ccp
150
+ rubygems_version: 1.3.7
151
+ signing_key:
152
+ specification_version: 3
153
+ summary: A Ruby library for Composite Command Programming
154
+ test_files: []
155
+