cog 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/API.rdoc +4 -31
- data/Default.cogfile +8 -5
- data/bin/cog +61 -51
- data/lib/cog.rb +18 -2
- data/lib/cog/config.rb +60 -42
- data/lib/cog/config/cogfile.rb +76 -0
- data/lib/cog/errors.rb +16 -0
- data/lib/cog/generator.rb +138 -0
- data/lib/cog/spec_helpers.rb +35 -0
- data/lib/cog/spec_helpers/matchers.rb +17 -17
- data/lib/cog/spec_helpers/matchers/match_maker.rb +51 -0
- data/lib/cog/spec_helpers/runner.rb +9 -5
- data/lib/cog/tool.rb +51 -0
- data/lib/cog/version.rb +3 -0
- data/templates/{snippets → cog/snippets}/c++/generated_warning.h.erb +0 -0
- data/templates/{snippets → cog/snippets}/generated_warning.txt +0 -0
- data/templates/cog/tool/API.rdoc.erb +7 -0
- data/templates/cog/tool/Gemfile.erb +4 -0
- data/templates/cog/tool/LICENSE.erb +18 -0
- data/templates/cog/tool/README.markdown.erb +18 -0
- data/templates/cog/tool/Rakefile.erb +15 -0
- data/templates/cog/tool/generator.rb.erb +5 -0
- data/templates/cog/tool/tool.gemspec.erb +18 -0
- data/templates/cog/tool/tool.rb.erb +4 -0
- data/templates/cog/tool/version.rb.erb +5 -0
- metadata +21 -19
- data/lib/cog/cogfile.rb +0 -65
- data/lib/cog/meta.rb +0 -9
- data/lib/cog/meta/gen_gen.rb +0 -85
- data/lib/cog/meta/mirror_gen.rb +0 -39
- data/lib/cog/mixins.rb +0 -13
- data/lib/cog/mixins/mirror.rb +0 -61
- data/lib/cog/mixins/uses_templates.rb +0 -152
- data/lib/cog_version.rb +0 -3
- data/templates/c++/mirror-abstract.cpp.erb +0 -0
- data/templates/c++/mirror-abstract.h.erb +0 -6
- data/templates/c++/mirror-impl.cpp.erb +0 -1
- data/templates/c++/mirror-impl.h.erb +0 -0
- data/templates/mirror.rb.erb +0 -10
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'cog/config'
|
2
|
+
require 'cog/errors'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Cog
|
6
|
+
|
7
|
+
# Generators have the ability to #stamp templates into source code.
|
8
|
+
#
|
9
|
+
# This module defines a low-level interface for writing generators. To use it,
|
10
|
+
# just include the Generator module in your class or object.
|
11
|
+
module Generator
|
12
|
+
|
13
|
+
# A list of available project generators
|
14
|
+
def self.available
|
15
|
+
[:dummy1, :dummy2]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the template with the given name.
|
19
|
+
#
|
20
|
+
# ==== Parameters
|
21
|
+
# * +path+ - a path to a template file which is relative to
|
22
|
+
# one of the template directories
|
23
|
+
#
|
24
|
+
# ==== Options
|
25
|
+
# * <tt>:absolute</tt> - is the +path+ argument absolute? (default: +false+)
|
26
|
+
#
|
27
|
+
# ==== Returns
|
28
|
+
# An instance of ERB.
|
29
|
+
def get_template(path, opt={})
|
30
|
+
path += '.erb'
|
31
|
+
fullpath = if opt[:absolute]
|
32
|
+
path
|
33
|
+
else
|
34
|
+
Config.instance.template_paths.inject('') do |found, prefix|
|
35
|
+
x = File.join prefix, path
|
36
|
+
found.empty? && File.exists?(x) ? x : found
|
37
|
+
end
|
38
|
+
end
|
39
|
+
raise Errors::MissingTemplate.new fullpath unless File.exists? fullpath
|
40
|
+
ERB.new File.read(fullpath), 0, '>'
|
41
|
+
end
|
42
|
+
|
43
|
+
# Stamp a template +source+ onto a +destination+.
|
44
|
+
#
|
45
|
+
# ==== Arguments
|
46
|
+
# * +template_path+ - a path to a template file which is relative to one
|
47
|
+
# of the template directories
|
48
|
+
# * +destination+ - a path to which the generated file should be written
|
49
|
+
#
|
50
|
+
# ==== Options
|
51
|
+
# * <tt>:absolute_template_path</tt> - is the +template_path+ argument absolute? (default: +false+)
|
52
|
+
def stamp(template_path, destination, opt={})
|
53
|
+
t = get_template template_path, :absolute => opt[:absolute_template_path]
|
54
|
+
b = opt[:binding] || binding
|
55
|
+
FileUtils.mkpath File.dirname(destination) unless File.exists? destination
|
56
|
+
scratch = "#{destination}.scratch"
|
57
|
+
File.open(scratch, 'w') {|file| file.write t.result(b)}
|
58
|
+
if same? destination, scratch
|
59
|
+
FileUtils.rm scratch
|
60
|
+
else
|
61
|
+
puts "Generated #{destination}"
|
62
|
+
FileUtils.mv scratch, destination
|
63
|
+
end
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
# Copy a file from +src+ to +dest+, but only if +dest+ does not already exist.
|
68
|
+
def copy_if_missing(src, dest)
|
69
|
+
unless File.exists? dest
|
70
|
+
FileUtils.cp src, dest
|
71
|
+
puts "Created #{dest}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Recursively create directories in the given path if they are missing.
|
76
|
+
def touch_path(*path_components)
|
77
|
+
path = File.join path_components
|
78
|
+
unless File.exists? path
|
79
|
+
FileUtils.mkdir_p path
|
80
|
+
puts "Created #{path}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# File extension for a snippet of the given source code language.
|
85
|
+
# ==== Example
|
86
|
+
# snippet_extension 'c++' # => 'h'
|
87
|
+
def snippet_extension(lang = 'text')
|
88
|
+
case lang
|
89
|
+
when /(c\+\+|c|objc)/i
|
90
|
+
'h'
|
91
|
+
else
|
92
|
+
'txt'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# A warning that indicates a file is maintained by a generator
|
97
|
+
def generated_warning
|
98
|
+
lang = Config.instance.language
|
99
|
+
t = get_template "snippets/#{lang}/generated_warning.#{snippet_extension lang}", :cog_template => true
|
100
|
+
t.result(binding)
|
101
|
+
end
|
102
|
+
|
103
|
+
def include_guard_begin(name)
|
104
|
+
full = "COG_INCLUDE_GUARD_#{name.upcase}"
|
105
|
+
"#ifndef #{full}\n#define #{full}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def include_guard_end
|
109
|
+
"#endif // COG_INCLUDE_GUARD_[...]"
|
110
|
+
end
|
111
|
+
|
112
|
+
def namespace_begin(name)
|
113
|
+
return if name.nil?
|
114
|
+
case Config.instance.language
|
115
|
+
when /c\+\+/
|
116
|
+
"namespace #{name} {"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def namespace_end(name)
|
121
|
+
return if name.nil?
|
122
|
+
case Config.instance.language
|
123
|
+
when /c\+\+/
|
124
|
+
"} // namespace #{name}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
def same?(original, scratch) # :nodoc:
|
130
|
+
if File.exists? original
|
131
|
+
File.read(original) == File.read(scratch)
|
132
|
+
else
|
133
|
+
false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
data/lib/cog/spec_helpers.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'cog/spec_helpers/runner'
|
2
2
|
require 'cog/spec_helpers/matchers'
|
3
|
+
require 'fileutils'
|
3
4
|
|
4
5
|
module Cog
|
5
6
|
|
@@ -24,6 +25,40 @@ module Cog
|
|
24
25
|
#
|
25
26
|
# end
|
26
27
|
module SpecHelpers
|
28
|
+
|
29
|
+
# Absolute path to the root spec directory
|
30
|
+
def spec_root
|
31
|
+
File.expand_path File.join(File.dirname(__FILE__), '..', '..', 'spec')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Directory of an active spec fixture.
|
35
|
+
def active_fixture_dir
|
36
|
+
File.join spec_root, 'active_fixture'
|
37
|
+
end
|
38
|
+
|
39
|
+
# Path to the Cogfile in the active spec fixture
|
40
|
+
def cogfile_path
|
41
|
+
File.join active_fixture_dir, 'Cogfile'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Path to the cog directory in the active spec fixture
|
45
|
+
def cog_directory
|
46
|
+
File.join active_fixture_dir, 'cog'
|
47
|
+
end
|
48
|
+
|
49
|
+
# The next cog spec will execute in a fresh copy of the given fixture directory.
|
50
|
+
# Fixture directories are stored in <tt>spec/fixtures</tt>.
|
51
|
+
def use_fixture(name)
|
52
|
+
path = File.join spec_root, 'fixtures', name.to_s
|
53
|
+
if File.exists?(path) && File.directory?(path)
|
54
|
+
FileUtils.rmtree active_fixture_dir if File.exists? active_fixture_dir
|
55
|
+
FileUtils.cp_r path, active_fixture_dir
|
56
|
+
Dir.chdir active_fixture_dir
|
57
|
+
else
|
58
|
+
throw :invalid_fixture_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
27
62
|
end
|
28
63
|
|
29
64
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'cog/spec_helpers/matchers/match_maker'
|
1
2
|
require 'rspec'
|
2
3
|
|
3
4
|
module Cog
|
@@ -6,26 +7,25 @@ module Cog
|
|
6
7
|
# Extra should or should_not matchers for RSpec.
|
7
8
|
module Matchers
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@second_line = o.readline
|
15
|
-
/help.*code gen/ =~ @second_line
|
16
|
-
end
|
17
|
-
end
|
18
|
-
def failure_message
|
19
|
-
"expected #{@runner} to show the default help text, got #{@first_line.inspect}"
|
20
|
-
end
|
21
|
-
def negative_failure_message
|
22
|
-
"expected #{@runner} to not show the default help text, got #{@first_line.inspect}"
|
10
|
+
# The target Invocation should output the default help text
|
11
|
+
def show_help
|
12
|
+
match_maker do
|
13
|
+
message { "to [show|not show] the default help text, got #{lines.first.inspect}" }
|
14
|
+
test { (/help.*code gen/ =~ lines[1]) }
|
23
15
|
end
|
24
16
|
end
|
25
17
|
|
26
|
-
# The target Invocation should
|
27
|
-
def
|
28
|
-
|
18
|
+
# The target Invocation should create a +Cogfile+ where none existed before
|
19
|
+
def make(path)
|
20
|
+
match_maker do
|
21
|
+
message { "to [create|not create] the #{path}" }
|
22
|
+
before do
|
23
|
+
@existed = File.exists? path
|
24
|
+
end
|
25
|
+
test do
|
26
|
+
!@existed && File.exists?(path)
|
27
|
+
end
|
28
|
+
end
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Cog
|
2
|
+
module SpecHelpers
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
class MatchMaker
|
6
|
+
attr_reader :lines
|
7
|
+
|
8
|
+
# Define the failure message
|
9
|
+
def message(&block)
|
10
|
+
@msg_block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
# Define a block which runs before the Invocation
|
14
|
+
def before(&block)
|
15
|
+
@before_block = block
|
16
|
+
end
|
17
|
+
|
18
|
+
# Define the test which runs after the Invocation
|
19
|
+
def test(&block)
|
20
|
+
@test_block = block
|
21
|
+
end
|
22
|
+
|
23
|
+
def matches?(runner) # :nodoc:
|
24
|
+
@runner = runner
|
25
|
+
instance_eval &@before_block unless @before_block.nil?
|
26
|
+
@runner.exec do |input, output, error|
|
27
|
+
@lines = output.readlines
|
28
|
+
end
|
29
|
+
instance_eval &@test_block
|
30
|
+
end
|
31
|
+
def failure_message # :nodoc:
|
32
|
+
msg = instance_eval &@msg_block
|
33
|
+
msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\1'
|
34
|
+
"expected #{@runner} #{msg}"
|
35
|
+
end
|
36
|
+
def negative_failure_message # :nodoc:
|
37
|
+
msg = instance_eval &@msg_block
|
38
|
+
msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\2'
|
39
|
+
"expected #{@runner} #{msg}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def match_maker(&block)
|
44
|
+
m = MatchMaker.new
|
45
|
+
m.instance_eval &block
|
46
|
+
m
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -4,10 +4,10 @@ module Cog
|
|
4
4
|
module SpecHelpers
|
5
5
|
|
6
6
|
# Points to the +cog+ command-line app
|
7
|
-
class
|
7
|
+
class Runner
|
8
8
|
|
9
9
|
def initialize(path_to_cl_app)
|
10
|
-
@cog = path_to_cl_app
|
10
|
+
@cog = File.expand_path path_to_cl_app
|
11
11
|
end
|
12
12
|
|
13
13
|
# Run cog with the given arguments
|
@@ -16,8 +16,8 @@ module Cog
|
|
16
16
|
# An instance of Invocation configured with the arguments. Use should and
|
17
17
|
# should_not with the custom Matchers
|
18
18
|
def run(*args)
|
19
|
-
args
|
20
|
-
Invocation.new
|
19
|
+
args = ['bundle', 'exec', @cog] + args
|
20
|
+
Invocation.new(args.collect {|x| x.to_s})
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -30,11 +30,15 @@ module Cog
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def exec(*args, &block) # :nodoc:
|
33
|
+
@s = ([File.basename @cmd[2]] + @cmd.slice(3..-1)).join ' '
|
33
34
|
Open3.popen3 *@cmd do |i,o,e,t|
|
34
35
|
block.call i,o,e
|
35
36
|
end
|
36
37
|
end
|
37
|
-
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
"`#{@s}`"
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
end
|
data/lib/cog/tool.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'cog/config'
|
2
|
+
require 'cog/generator'
|
3
|
+
|
4
|
+
module Cog
|
5
|
+
|
6
|
+
class Tool
|
7
|
+
|
8
|
+
# Lower case command-line version of the name
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# Capitalized module name
|
12
|
+
attr_reader :module_name
|
13
|
+
|
14
|
+
# Name of the person who will be given copyright for the generated code
|
15
|
+
attr_reader :author
|
16
|
+
|
17
|
+
# Email address of the author
|
18
|
+
attr_reader :email
|
19
|
+
|
20
|
+
# A one-line description of the tool
|
21
|
+
attr_reader :description
|
22
|
+
|
23
|
+
# A list of available tools
|
24
|
+
def self.available
|
25
|
+
# TODO: use paths to instantiate a list of Tool objects
|
26
|
+
paths = ENV['COG_TOOLS'] || []
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.generate_tool(name)
|
30
|
+
Object.new.instance_eval do
|
31
|
+
class << self ; include Generator ; end
|
32
|
+
@name = name.to_s.downcase
|
33
|
+
@module_name = name.to_s.capitalize
|
34
|
+
@author = '<Your name goes here>'
|
35
|
+
@email = 'youremail@...'
|
36
|
+
@description = 'A one-liner'
|
37
|
+
@cog_version = Cog::VERSION
|
38
|
+
stamp 'cog/tool/tool.rb', "#{@name}/lib/#{@name}.rb"
|
39
|
+
stamp 'cog/tool/version.rb', "#{@name}/lib/#{@name}/version.rb"
|
40
|
+
stamp 'cog/tool/generator.rb', "#{@name}/cog/templates/#{@name}/generator.rb.erb"
|
41
|
+
stamp 'cog/tool/Gemfile', "#{@name}/Gemfile"
|
42
|
+
stamp 'cog/tool/Rakefile', "#{@name}/Rakefile"
|
43
|
+
stamp 'cog/tool/tool.gemspec', "#{@name}/#{@name}.gemspec"
|
44
|
+
stamp 'cog/tool/API.rdoc', "#{@name}/API.rdoc"
|
45
|
+
stamp 'cog/tool/LICENSE', "#{@name}/LICENSE"
|
46
|
+
stamp 'cog/tool/README.markdown', "#{@name}/README.markdown"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/lib/cog/version.rb
ADDED
File without changes
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2012 <%= @author %>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
|
+
subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
require 'rdoc/task'
|
5
|
+
|
6
|
+
Rake::RDocTask.new do |rd|
|
7
|
+
rd.main = "API.rdoc"
|
8
|
+
rd.rdoc_files.include("API.rdoc", "lib/**/*.rb")
|
9
|
+
rd.title = '<%= @module_name %> API Docs'
|
10
|
+
end
|
11
|
+
|
12
|
+
spec = eval(File.read('<%= @name %>.gemspec'))
|
13
|
+
|
14
|
+
Gem::PackageTask.new(spec) do |pkg|
|
15
|
+
end
|