cog 0.0.11 → 0.0.12
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/bin/cog +37 -22
- data/lib/cog/config.rb +10 -8
- data/lib/cog/generator.rb +42 -11
- data/lib/cog/spec_helpers.rb +7 -2
- data/lib/cog/spec_helpers/matchers.rb +24 -7
- data/lib/cog/spec_helpers/matchers/match_maker.rb +33 -2
- data/lib/cog/spec_helpers/runner.rb +3 -2
- data/lib/cog/tool.rb +4 -17
- data/lib/cog/version.rb +1 -1
- data/templates/cog/generator/basic.rb.erb +11 -0
- metadata +5 -4
data/bin/cog
CHANGED
@@ -20,43 +20,45 @@ command :init do |c|
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
desc 'Create a
|
23
|
+
desc 'Create a generator (or leave name blank to list project generators)'
|
24
24
|
arg_name 'name'
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
command :generator do |c|
|
26
|
+
|
27
|
+
c.desc 'which tool to use to create the generator'
|
28
|
+
c.arg_name 'tool_name'
|
29
|
+
c.default_value 'basic'
|
30
|
+
c.flag :tool
|
31
|
+
|
28
32
|
c.action do |global_options, options, args|
|
29
33
|
if args.empty?
|
30
|
-
|
31
|
-
|
34
|
+
# List
|
35
|
+
x = Cog::Generator.list
|
36
|
+
puts x.collect {|gen| " #{gen}"}.join "\n" unless x.empty?
|
32
37
|
else
|
38
|
+
# Create
|
33
39
|
args.each do |name|
|
34
|
-
|
35
|
-
Cog::Tool.generate_tool name
|
36
|
-
else
|
37
|
-
puts "Could not create tool for '#{name}', a file or directory already exists with that name"
|
38
|
-
end
|
40
|
+
Cog::Generator.create name, options
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
|
-
desc 'Create a
|
46
|
+
desc 'Create a tool (or leave name blank to list available tools)'
|
45
47
|
arg_name 'name'
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
c.arg_name 'tool_name'
|
50
|
-
c.default_value 'generic'
|
51
|
-
c.flag :tool
|
52
|
-
|
48
|
+
skips_pre
|
49
|
+
command :tool do |c|
|
50
|
+
|
53
51
|
c.action do |global_options, options, args|
|
54
52
|
if args.empty?
|
55
|
-
puts '
|
56
|
-
puts (Cog::
|
53
|
+
puts 'Available tools:'
|
54
|
+
puts (Cog::Tool.list.collect {|tool| " #{tool}"}.join "\n")
|
57
55
|
else
|
58
56
|
args.each do |name|
|
59
|
-
|
57
|
+
unless File.exists? name
|
58
|
+
Cog::Tool.create name
|
59
|
+
else
|
60
|
+
puts "Could not create tool for '#{name}', a file or directory already exists with that name"
|
61
|
+
end
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
@@ -74,6 +76,19 @@ end
|
|
74
76
|
desc 'Run generators in the current project'
|
75
77
|
arg_name 'generator_name'
|
76
78
|
command :run do |c|
|
79
|
+
|
80
|
+
c.action do |global_options, options, args|
|
81
|
+
args = Cog::Generator.available if args.empty?
|
82
|
+
args.each do |gen|
|
83
|
+
filename = File.join Cog::Config.instance.project_generators_path, "#{gen}.rb"
|
84
|
+
if File.exists? filename
|
85
|
+
puts "Running generator #{gen}"
|
86
|
+
require filename
|
87
|
+
else
|
88
|
+
puts "No such generator #{gen}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
77
92
|
end
|
78
93
|
|
79
94
|
pre do |global_options, command, options, args|
|
data/lib/cog/config.rb
CHANGED
@@ -3,9 +3,10 @@ require 'singleton'
|
|
3
3
|
|
4
4
|
module Cog
|
5
5
|
|
6
|
-
# This interface is
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# This is a low level interface. It is mainly used by the Generator methods
|
7
|
+
# to determine where to find things, and where to put them. When +cog+ is used
|
8
|
+
# in a project the values of the singleton Config::instance should be configured using
|
9
|
+
# a Cogfile.
|
9
10
|
class Config
|
10
11
|
|
11
12
|
# Path to the project's +Cogfile+.
|
@@ -52,16 +53,16 @@ module Cog
|
|
52
53
|
|
53
54
|
# The singleton instance.
|
54
55
|
#
|
55
|
-
# Initialized using the
|
56
|
-
# found. If not, then #project? will be +false
|
56
|
+
# Initialized using the Cogfile for the current project, if any can be
|
57
|
+
# found. If not, then #project? will be +false+ and all the +project_...+
|
58
|
+
# attributes will be +nil+.
|
57
59
|
#
|
58
|
-
# The
|
60
|
+
# The Cogfile will be looked for in the present working directory. If none
|
59
61
|
# is found there the parent directory will be checked, and then the
|
60
62
|
# grandparent, and so on.
|
61
63
|
#
|
62
64
|
# ==== Returns
|
63
|
-
# An instance of
|
64
|
-
# such file was found then +nil+.
|
65
|
+
# An instance of Config.
|
65
66
|
def self.instance
|
66
67
|
return @instance if @instance
|
67
68
|
@instance = self.new
|
@@ -89,6 +90,7 @@ module Cog
|
|
89
90
|
|
90
91
|
def initialize
|
91
92
|
@project_root = nil
|
93
|
+
@language = 'c++'
|
92
94
|
end
|
93
95
|
|
94
96
|
end
|
data/lib/cog/generator.rb
CHANGED
@@ -4,15 +4,46 @@ require 'erb'
|
|
4
4
|
|
5
5
|
module Cog
|
6
6
|
|
7
|
-
#
|
7
|
+
# This module defines an interface which can be used by generator objects.
|
8
|
+
# Specifically, it makes it easy to find ERB templates and render them into
|
9
|
+
# generated source code files, using the #stamp method.
|
8
10
|
#
|
9
|
-
#
|
10
|
-
# just include the Generator module in your class or object.
|
11
|
+
# For more details on writing generators see https://github.com/ktonon/cog#generators
|
11
12
|
module Generator
|
12
13
|
|
13
14
|
# A list of available project generators
|
14
|
-
def self.
|
15
|
-
|
15
|
+
def self.list
|
16
|
+
if Config.instance.project?
|
17
|
+
Dir.glob(File.join Config.instance.project_generators_path, '*.rb').collect do |path|
|
18
|
+
File.basename(path).slice(0..-4)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create a new generator
|
26
|
+
#
|
27
|
+
# ==== Arguments
|
28
|
+
# * +name+ - the name to use for the new generator
|
29
|
+
#
|
30
|
+
# ==== Options
|
31
|
+
# * +tool+ - the name of the tool to use (default: basic)
|
32
|
+
#
|
33
|
+
# ==== Returns
|
34
|
+
# Whether or not the generator was created successfully
|
35
|
+
def self.create(name, opt={})
|
36
|
+
return false unless Config.instance.project?
|
37
|
+
filename = File.join Config.instance.project_generators_path, "#{name}.rb"
|
38
|
+
return false if File.exists? filename
|
39
|
+
tool = (opt[:tool] || :basic).to_s
|
40
|
+
Object.new.instance_eval do
|
41
|
+
extend Generator
|
42
|
+
@name = name
|
43
|
+
@class_name = name.to_s.camelize
|
44
|
+
stamp 'cog/generator/basic.rb', filename
|
45
|
+
end
|
46
|
+
true
|
16
47
|
end
|
17
48
|
|
18
49
|
# Get the template with the given name.
|
@@ -84,7 +115,7 @@ module Cog
|
|
84
115
|
# File extension for a snippet of the given source code language.
|
85
116
|
# ==== Example
|
86
117
|
# snippet_extension 'c++' # => 'h'
|
87
|
-
def snippet_extension(lang = 'text')
|
118
|
+
def snippet_extension(lang = 'text') # :nodoc:
|
88
119
|
case lang
|
89
120
|
when /(c\+\+|c|objc)/i
|
90
121
|
'h'
|
@@ -94,22 +125,22 @@ module Cog
|
|
94
125
|
end
|
95
126
|
|
96
127
|
# A warning that indicates a file is maintained by a generator
|
97
|
-
def generated_warning
|
128
|
+
def generated_warning # :nodoc:
|
98
129
|
lang = Config.instance.language
|
99
130
|
t = get_template "snippets/#{lang}/generated_warning.#{snippet_extension lang}", :cog_template => true
|
100
131
|
t.result(binding)
|
101
132
|
end
|
102
133
|
|
103
|
-
def include_guard_begin(name)
|
134
|
+
def include_guard_begin(name) # :nodoc:
|
104
135
|
full = "COG_INCLUDE_GUARD_#{name.upcase}"
|
105
136
|
"#ifndef #{full}\n#define #{full}"
|
106
137
|
end
|
107
138
|
|
108
|
-
def include_guard_end
|
139
|
+
def include_guard_end # :nodoc:
|
109
140
|
"#endif // COG_INCLUDE_GUARD_[...]"
|
110
141
|
end
|
111
142
|
|
112
|
-
def namespace_begin(name)
|
143
|
+
def namespace_begin(name) # :nodoc:
|
113
144
|
return if name.nil?
|
114
145
|
case Config.instance.language
|
115
146
|
when /c\+\+/
|
@@ -117,7 +148,7 @@ module Cog
|
|
117
148
|
end
|
118
149
|
end
|
119
150
|
|
120
|
-
def namespace_end(name)
|
151
|
+
def namespace_end(name) # :nodoc:
|
121
152
|
return if name.nil?
|
122
153
|
case Config.instance.language
|
123
154
|
when /c\+\+/
|
data/lib/cog/spec_helpers.rb
CHANGED
@@ -9,14 +9,14 @@ module Cog
|
|
9
9
|
# === Example
|
10
10
|
# Requiring the helpers will make extra SpecHelpers::Matchers available to
|
11
11
|
# your RSpec tests. These are useful for testing a SpecHelpers::Invocation,
|
12
|
-
# which is returned from a call to SpecHelpers::
|
12
|
+
# which is returned from a call to SpecHelpers::Runner#run
|
13
13
|
#
|
14
14
|
# require 'cog/spec_helpers'
|
15
15
|
#
|
16
16
|
# describe 'The command line interface' do
|
17
17
|
#
|
18
18
|
# before :all do
|
19
|
-
# @cog = Cog::SpecHelpers::
|
19
|
+
# @cog = Cog::SpecHelpers::Runner.new 'bin/cog'
|
20
20
|
# end
|
21
21
|
#
|
22
22
|
# it 'should print help when no args are passed' do
|
@@ -46,6 +46,11 @@ module Cog
|
|
46
46
|
File.join active_fixture_dir, 'cog'
|
47
47
|
end
|
48
48
|
|
49
|
+
# Path to the generator with the given name
|
50
|
+
def generator(name)
|
51
|
+
File.join active_fixture_dir, 'cog', 'generators', "#{name}.rb"
|
52
|
+
end
|
53
|
+
|
49
54
|
# The next cog spec will execute in a fresh copy of the given fixture directory.
|
50
55
|
# Fixture directories are stored in <tt>spec/fixtures</tt>.
|
51
56
|
def use_fixture(name)
|
@@ -5,20 +5,21 @@ module Cog
|
|
5
5
|
module SpecHelpers
|
6
6
|
|
7
7
|
# Extra should or should_not matchers for RSpec.
|
8
|
+
# Check out #match_maker for help writing new matchers.
|
8
9
|
module Matchers
|
9
10
|
|
10
|
-
# The target Invocation should
|
11
|
-
def
|
11
|
+
# The target Invocation should complain about a missing +Cogfile+
|
12
|
+
def complain_about_missing_cogfile
|
12
13
|
match_maker do
|
13
|
-
message { "to [
|
14
|
-
test { (/
|
14
|
+
message { "to [require|not require] a Cogfile. STDOUT: #{lines.inspect}" }
|
15
|
+
test { (/no cogfile could be found/i =~ lines.first) }
|
15
16
|
end
|
16
17
|
end
|
17
|
-
|
18
|
+
|
18
19
|
# The target Invocation should create a +Cogfile+ where none existed before
|
19
20
|
def make(path)
|
20
21
|
match_maker do
|
21
|
-
message { "to [create|not create]
|
22
|
+
message { "to [create|not create] #{path}. STDOUT: #{lines.inspect}" }
|
22
23
|
before do
|
23
24
|
@existed = File.exists? path
|
24
25
|
end
|
@@ -27,8 +28,24 @@ module Cog
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
31
|
+
|
32
|
+
# The target Invocation should do something, as determined by standard output
|
33
|
+
def do_something
|
34
|
+
match_maker do
|
35
|
+
message { "to [write something|not write anything] to stdout. STDOUT: #{lines.inspect}" }
|
36
|
+
test { !lines.empty? }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# The target Invocation should output the default help text
|
41
|
+
def show_help
|
42
|
+
match_maker do
|
43
|
+
message { "to [show|not show] the default help text, got #{lines.first.inspect}. STDOUT: #{lines.inspect}" }
|
44
|
+
test { (/help.*code gen/ =~ lines[1]) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
30
48
|
end
|
31
|
-
|
32
49
|
end
|
33
50
|
end
|
34
51
|
|
@@ -2,20 +2,39 @@ module Cog
|
|
2
2
|
module SpecHelpers
|
3
3
|
module Matchers
|
4
4
|
|
5
|
+
# Within Matchers#match_maker blocks, +self+ is set to an instance of this
|
6
|
+
# class.
|
5
7
|
class MatchMaker
|
8
|
+
# A list of lines read from standard output after executing the Invocation.
|
6
9
|
attr_reader :lines
|
7
10
|
|
8
|
-
# Define
|
11
|
+
# Define a block which runs after a test fails and should return
|
12
|
+
# a failure message template.
|
13
|
+
#
|
14
|
+
# The template is used for both positive and negative failures.
|
15
|
+
# Substrings which look like this <tt>"[positive|negative]</tt>" will
|
16
|
+
# be replaced with the appropriate section. For example
|
17
|
+
# message { "to [show|not show] the default help text" }
|
18
|
+
#
|
19
|
+
# would read "expected cog to show the default help text"
|
20
|
+
# for a positive failure and "expected cog to not show the
|
21
|
+
# default help text" for a negative failure. The "expected cog"
|
22
|
+
# part is inserted automatically.
|
9
23
|
def message(&block)
|
10
24
|
@msg_block = block
|
11
25
|
end
|
12
26
|
|
13
|
-
# Define a block which runs before the Invocation
|
27
|
+
# Define a block which runs before the Invocation.
|
28
|
+
#
|
29
|
+
# This is not required, but can be used to save context that is used
|
30
|
+
# the in post invocation #test.
|
14
31
|
def before(&block)
|
15
32
|
@before_block = block
|
16
33
|
end
|
17
34
|
|
18
35
|
# Define the test which runs after the Invocation
|
36
|
+
#
|
37
|
+
# This can make use of instance variables set during #before.
|
19
38
|
def test(&block)
|
20
39
|
@test_block = block
|
21
40
|
end
|
@@ -40,6 +59,18 @@ module Cog
|
|
40
59
|
end
|
41
60
|
end
|
42
61
|
|
62
|
+
# Makes it easy to write RSpec matchers
|
63
|
+
#
|
64
|
+
# Here is how the matcher for Matchers#show_help is written using this method
|
65
|
+
# #match_maker method.
|
66
|
+
# def show_help
|
67
|
+
# match_maker do
|
68
|
+
# message { "to [show|not show] the default help text, got #{lines.first.inspect}" }
|
69
|
+
# test { (/help.*code gen/ =~ lines[1]) }
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# Within the +match_maker+ block, +self+ is set to an instance of MatchMaker.
|
43
74
|
def match_maker(&block)
|
44
75
|
m = MatchMaker.new
|
45
76
|
m.instance_eval &block
|
@@ -22,7 +22,8 @@ module Cog
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# Represents a +cog+ command line invocation, which can be tested with
|
25
|
-
# +RSpec+ +should+ and +should_not+ custom Matchers
|
25
|
+
# +RSpec+ +should+ and +should_not+ custom Matchers. This is the kind of
|
26
|
+
# object returned by Runner#run.
|
26
27
|
class Invocation
|
27
28
|
|
28
29
|
def initialize(cmd) # :nodoc:
|
@@ -36,7 +37,7 @@ module Cog
|
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
39
|
-
def to_s
|
40
|
+
def to_s # :nodoc:
|
40
41
|
"`#{@s}`"
|
41
42
|
end
|
42
43
|
end
|
data/lib/cog/tool.rb
CHANGED
@@ -3,30 +3,17 @@ require 'cog/generator'
|
|
3
3
|
|
4
4
|
module Cog
|
5
5
|
|
6
|
+
# For more details on writing tools see https://github.com/ktonon/cog#tools
|
6
7
|
class Tool
|
7
8
|
|
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
9
|
# A list of available tools
|
24
|
-
def self.
|
10
|
+
def self.list
|
25
11
|
# TODO: use paths to instantiate a list of Tool objects
|
26
12
|
paths = ENV['COG_TOOLS'] || []
|
27
13
|
end
|
28
14
|
|
29
|
-
|
15
|
+
# Generate a new tool with the given name
|
16
|
+
def self.create(name)
|
30
17
|
Object.new.instance_eval do
|
31
18
|
class << self ; include Generator ; end
|
32
19
|
@name = name.to_s.downcase
|
data/lib/cog/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 12
|
10
|
+
version: 0.0.12
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kevin Tonon
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-11-
|
18
|
+
date: 2012-11-04 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rake
|
@@ -57,6 +57,7 @@ files:
|
|
57
57
|
- bin/cog
|
58
58
|
- Default.cogfile
|
59
59
|
- LICENSE
|
60
|
+
- templates/cog/generator/basic.rb.erb
|
60
61
|
- templates/cog/snippets/c++/generated_warning.h.erb
|
61
62
|
- templates/cog/snippets/generated_warning.txt
|
62
63
|
- templates/cog/tool/API.rdoc.erb
|