cog 0.0.10 → 0.0.11

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.
Files changed (39) hide show
  1. data/API.rdoc +4 -31
  2. data/Default.cogfile +8 -5
  3. data/bin/cog +61 -51
  4. data/lib/cog.rb +18 -2
  5. data/lib/cog/config.rb +60 -42
  6. data/lib/cog/config/cogfile.rb +76 -0
  7. data/lib/cog/errors.rb +16 -0
  8. data/lib/cog/generator.rb +138 -0
  9. data/lib/cog/spec_helpers.rb +35 -0
  10. data/lib/cog/spec_helpers/matchers.rb +17 -17
  11. data/lib/cog/spec_helpers/matchers/match_maker.rb +51 -0
  12. data/lib/cog/spec_helpers/runner.rb +9 -5
  13. data/lib/cog/tool.rb +51 -0
  14. data/lib/cog/version.rb +3 -0
  15. data/templates/{snippets → cog/snippets}/c++/generated_warning.h.erb +0 -0
  16. data/templates/{snippets → cog/snippets}/generated_warning.txt +0 -0
  17. data/templates/cog/tool/API.rdoc.erb +7 -0
  18. data/templates/cog/tool/Gemfile.erb +4 -0
  19. data/templates/cog/tool/LICENSE.erb +18 -0
  20. data/templates/cog/tool/README.markdown.erb +18 -0
  21. data/templates/cog/tool/Rakefile.erb +15 -0
  22. data/templates/cog/tool/generator.rb.erb +5 -0
  23. data/templates/cog/tool/tool.gemspec.erb +18 -0
  24. data/templates/cog/tool/tool.rb.erb +4 -0
  25. data/templates/cog/tool/version.rb.erb +5 -0
  26. metadata +21 -19
  27. data/lib/cog/cogfile.rb +0 -65
  28. data/lib/cog/meta.rb +0 -9
  29. data/lib/cog/meta/gen_gen.rb +0 -85
  30. data/lib/cog/meta/mirror_gen.rb +0 -39
  31. data/lib/cog/mixins.rb +0 -13
  32. data/lib/cog/mixins/mirror.rb +0 -61
  33. data/lib/cog/mixins/uses_templates.rb +0 -152
  34. data/lib/cog_version.rb +0 -3
  35. data/templates/c++/mirror-abstract.cpp.erb +0 -0
  36. data/templates/c++/mirror-abstract.h.erb +0 -6
  37. data/templates/c++/mirror-impl.cpp.erb +0 -1
  38. data/templates/c++/mirror-impl.h.erb +0 -0
  39. 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
@@ -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
- class ShowHelp # :nodoc:
10
- def matches?(runner)
11
- @runner = runner
12
- @runner.exec do |i,o,e|
13
- @first_line = o.readline
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 output the default help text
27
- def show_help
28
- ShowHelp.new
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 App
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.unshift @cog
20
- Invocation.new args
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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Cog
2
+ VERSION = '0.0.11' unless const_defined? :VERSION
3
+ end
@@ -0,0 +1,7 @@
1
+ = <%= @name %>
2
+
3
+ These are the API docs for +<%= @name %>+, which is +cog+ tool.
4
+
5
+ Please see the <tt>README.markdown</tt> file for a introduction to the
6
+ +<%= @name %>+ tool. To find out more about +cog+ in general visit
7
+ https://github.com/ktonon/cog#readme
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ gem "cog", "~> <%= @cog_version %>"
@@ -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,18 @@
1
+ = <%= @name %>
2
+
3
+ <%= @description %>
4
+
5
+ Get it
6
+ ------
7
+
8
+ From a terminal
9
+
10
+ ```bash
11
+ gem install <%= @name %>
12
+ ```
13
+
14
+ or in your Gemfile
15
+
16
+ ```ruby
17
+ gem "<%= @name %>", "~> 0.0.1"
18
+ ```
@@ -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