cog 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
data/bin/cog CHANGED
@@ -20,43 +20,45 @@ command :init do |c|
20
20
  end
21
21
  end
22
22
 
23
- desc 'Create a tool (or leave name blank to list available tools)'
23
+ desc 'Create a generator (or leave name blank to list project generators)'
24
24
  arg_name 'name'
25
- skips_pre
26
- command :tool do |c|
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
- puts 'Available tools:'
31
- puts (Cog::Tool.available.collect {|tool| " #{tool}"}.join "\n")
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
- unless File.exists? name
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 generator (or leave name blank to list project generators)'
46
+ desc 'Create a tool (or leave name blank to list available tools)'
45
47
  arg_name 'name'
46
- command :generator do |c|
47
-
48
- c.desc 'which tool to use to create the generator'
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 'Project generators:'
56
- puts (Cog::Generator.available.collect {|gen| " #{gen}"}.join "\n")
53
+ puts 'Available tools:'
54
+ puts (Cog::Tool.list.collect {|tool| " #{tool}"}.join "\n")
57
55
  else
58
56
  args.each do |name|
59
- # TODO: create the generator
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|
@@ -3,9 +3,10 @@ require 'singleton'
3
3
 
4
4
  module Cog
5
5
 
6
- # This interface is intended for use within generators. Apps can customize
7
- # Instances of this type
8
- # can be configured via Cogfile files.
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 +Cogfile+ for the current project, if any can be
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 +Cogfile+ will be looked for in the present working directory. If none
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 Cogfile which has been configured with a +Cogfile+. If no
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
@@ -4,15 +4,46 @@ require 'erb'
4
4
 
5
5
  module Cog
6
6
 
7
- # Generators have the ability to #stamp templates into source code.
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
- # 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
+ # 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.available
15
- [:dummy1, :dummy2]
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\+\+/
@@ -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::App#run
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::App.new 'bin/cog'
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 output the default help text
11
- def show_help
11
+ # The target Invocation should complain about a missing +Cogfile+
12
+ def complain_about_missing_cogfile
12
13
  match_maker do
13
- message { "to [show|not show] the default help text, got #{lines.first.inspect}" }
14
- test { (/help.*code gen/ =~ lines[1]) }
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] the #{path}" }
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 the failure message
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
@@ -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.available
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
- def self.generate_tool(name)
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
@@ -1,3 +1,3 @@
1
1
  module Cog
2
- VERSION = '0.0.11' unless const_defined? :VERSION
2
+ VERSION = '0.0.12' unless const_defined? :VERSION
3
3
  end
@@ -0,0 +1,11 @@
1
+ require 'cog'
2
+
3
+ class <%= @class_name %>
4
+ include Cog::Generator
5
+
6
+ def generate
7
+ # TODO: create a template and use stamp here to generate source code
8
+ end
9
+ end
10
+
11
+ <%= @class_name %>.new.generate
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: 9
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 11
10
- version: 0.0.11
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-03 00:00:00 Z
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