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
data/API.rdoc CHANGED
@@ -1,33 +1,6 @@
1
- = cog API docs
1
+ = cog API Docs
2
2
 
3
- +cog+ is a command line utility that makes it a bit easier to organize a project
4
- which uses code generation. Many of your interactions with +cog+ will be using
5
- the command line interface. However, to get any real mileage out of it you'll
6
- need to use the API (documented here). For more information on the command line
7
- interface see https://github.com/ktonon/cog#cog
3
+ +cog+ is a command line tool which helps you write code generators.
8
4
 
9
- +cog+ is configured with a +Cogfile+, which should be in the root of your
10
- project's file tree. The +Cogfile+ is just a ruby file and the commands
11
- available in it are defined in the Cog::Cogfile class. It is generated for you
12
- when you issue this command from a shell in the root directory of your project:
13
-
14
- cog init
15
-
16
- and it will look something like this:
17
-
18
- # All paths are relative to the directory containing this file.
19
-
20
- # The directory in which to place Ruby generators and +ERB+ templates.
21
- cog_dir 'cog'
22
-
23
- # The directory in which to place generated application code.
24
- app_dir 'src'
25
-
26
- # The default language in which to generate source code.
27
- language 'c++'
28
-
29
- == Testing
30
-
31
- The tests are written in +RSpec+ and can be found in the <tt>spec/</tt>
32
- directory. Custom matchers are available to make writing specs easier. See
33
- Cog::SpecHelpers for more details.
5
+ This is the API docs. For a more general introduction to +cog+ visit
6
+ https://github.com/ktonon/cog#readme
@@ -1,10 +1,13 @@
1
1
  # All paths are relative to the directory containing this file.
2
2
 
3
- # The directory in which to place Ruby generators and +ERB+ templates.
4
- cog_dir 'cog'
3
+ # Define the directory in which to find project generators
4
+ project_generators_path 'cog/generators'
5
5
 
6
- # The directory in which to place generated application code.
7
- app_dir 'src'
6
+ # Define the directory in which to find custom project templates
7
+ project_templates_path 'cog/templates'
8
8
 
9
- # The default language in which to generate source code.
9
+ # Define the directory to which project source code is generated
10
+ project_source_path 'src'
11
+
12
+ # Define the default language in which to generated application source code
10
13
  language 'c++'
data/bin/cog CHANGED
@@ -1,81 +1,91 @@
1
1
  #!/usr/bin/env ruby
2
- # 1.9 adds realpath to resolve symlinks; 1.8 doesn't
3
- # have this method, so we add it so we get resolved symlinks
4
- # and compatibility
5
- unless File.respond_to? :realpath
6
- class File #:nodoc:
7
- def self.realpath path
8
- return realpath(File.readlink(path)) if symlink?(path)
9
- path
10
- end
11
- end
12
- end
13
- $: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib')
14
- require 'rubygems'
15
- require 'active_support/core_ext'
16
- require 'cog'
17
- require 'cog_version'
18
2
  require 'gli'
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'cog'
5
+ require 'active_support/core_ext'
19
6
  require 'fileutils'
20
7
 
21
8
  include GLI::App
22
9
 
23
10
  program_desc 'This is a utility to help you write code generators.'
24
11
 
25
- version Cog::VERSION
26
-
27
- desc 'Write extra information'
28
- switch [:v,:verbose]
12
+ # version Cog::VERSION
29
13
 
30
- desc 'Add cog to a project by generating a Cogfile in the current directory'
14
+ desc 'Add cog to the project in the present working directory'
15
+ skips_pre
31
16
  command :init do |c|
32
- c.action do |g,o,a|
33
- puts "Generated Cogfile"
34
- FileUtils.cp File.join(Cog::Config.gem_dir, 'Default.cogfile'), 'Cogfile'
17
+
18
+ c.action do |global_options, options, args|
19
+ Cog.initialize_project
35
20
  end
36
21
  end
37
22
 
38
- # desc 'Create a new mirror class'
39
- # arg_name 'ClassName'
40
- # command :mirror do |c|
41
- # c.desc 'The target language (see languages command)'
42
- # c.arg_name 'language'
43
- # c.flag [:language, :l]
44
- #
45
- # c.desc 'Slash (/) separated prefix for generator, templates, and app code'
46
- # c.arg_name 'path'
47
- # c.flag [:package, :p]
48
- #
49
- # c.action do |g,opt,a|
50
- # a.each do |class_name|
51
- # mirror_gen = Cog::Meta::MirrorGen.new class_name
52
- # mirror_gen.stamp opt
53
- # end
54
- # end
55
- # end
23
+ desc 'Create a tool (or leave name blank to list available tools)'
24
+ arg_name 'name'
25
+ skips_pre
26
+ command :tool do |c|
27
+
28
+ c.action do |global_options, options, args|
29
+ if args.empty?
30
+ puts 'Available tools:'
31
+ puts (Cog::Tool.available.collect {|tool| " #{tool}"}.join "\n")
32
+ else
33
+ 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
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ desc 'Create a generator (or leave name blank to list project generators)'
45
+ 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
+
53
+ c.action do |global_options, options, args|
54
+ if args.empty?
55
+ puts 'Project generators:'
56
+ puts (Cog::Generator.available.collect {|gen| " #{gen}"}.join "\n")
57
+ else
58
+ args.each do |name|
59
+ # TODO: create the generator
60
+ end
61
+ end
62
+ end
63
+ end
56
64
 
57
65
  desc 'List supported languages'
66
+ skips_pre
58
67
  command :languages do |c|
59
- c.action do |g,o,a|
68
+
69
+ c.action do
60
70
  puts 'c++'
61
71
  end
62
72
  end
63
73
 
64
- pre do |global, command, options, args|
74
+ desc 'Run generators in the current project'
75
+ arg_name 'generator_name'
76
+ command :run do |c|
77
+ end
78
+
79
+ pre do |global_options, command, options, args|
65
80
  # Pre logic here
66
81
  # Return true to proceed; false to abort and not call the
67
82
  # chosen command
68
83
  # Use skips_pre before a command to skip this block
69
84
  # on that command only
70
- cogfile = Cog::Config.for_project
71
- if !cogfile && command && command.name != :init
72
- puts 'No Cogfile could be found'
73
- false
74
- elsif cogfile && command && command.name == :init
75
- puts "A Cogfile already exists at #{cogfile.cogfile_path.inspect}"
85
+ unless Cog::Config.instance.project?
86
+ puts 'No Cogfile could be found. Run `cog init` to prepare an existing project.'
76
87
  false
77
88
  else
78
- global[:cogfile] = cogfile
79
89
  true
80
90
  end
81
91
  end
data/lib/cog.rb CHANGED
@@ -1,6 +1,22 @@
1
1
  require 'cog/config'
2
- require 'cog/meta'
3
- require 'cog/mixins'
2
+ require 'cog/generator'
3
+ require 'cog/tool'
4
+ require 'cog/version'
5
+ require 'fileutils'
4
6
 
7
+ # The static methods on this top level module mirror the commands available to
8
+ # the +cog+ command line utility.
5
9
  module Cog
10
+
11
+ # Prepare the project in the present working directory for use with +cog+
12
+ def self.initialize_project
13
+ Object.new.instance_eval do
14
+ class << self ; include Generator ; end
15
+ copy_if_missing File.join(Config.gem_dir, 'Default.cogfile'), 'Cogfile'
16
+ config = Config.instance
17
+ touch_path config.project_generators_path
18
+ touch_path config.project_templates_path
19
+ end
20
+ end
21
+
6
22
  end
@@ -1,45 +1,60 @@
1
- require 'rubygems'
1
+ require 'cog/config/cogfile'
2
2
  require 'singleton'
3
- require 'cog/cogfile'
4
3
 
5
4
  module Cog
6
5
 
7
- # This interface is intended for use within generators. Instances of this type
8
- # are initialized via Cogfile files.
6
+ # This interface is intended for use within generators. Apps can customize
7
+ # Instances of this type
8
+ # can be configured via Cogfile files.
9
9
  class Config
10
10
 
11
- # Directory to which application source code is generated.
12
- attr_reader :app_dir
13
-
14
- # Path to the +Cogfile+.
11
+ # Path to the project's +Cogfile+.
15
12
  attr_reader :cogfile_path
16
13
 
17
- # Directory in which to find Ruby source files. These are files which
18
- # control exactly how the code is going to be generated.
19
- attr_reader :generator_dir
20
-
21
- # Default language in which to generated application source code.
14
+ # Default language in which to generated application source code
22
15
  attr_reader :language
23
16
 
24
- # Directory in which the +Cogfile+ is found.
17
+ # Directory in which to find project generators
18
+ attr_reader :project_generators_path
19
+
20
+ # Directory in which the project's +Cogfile+ is found
25
21
  attr_reader :project_root
26
22
 
27
- # Directory in which to find ERB template files.
28
- attr_reader :template_dir
23
+ # Directory to which project source code is generated
24
+ attr_reader :project_source_path
25
+
26
+ # Directory in which to find custom project templates
27
+ attr_reader :project_templates_path
29
28
 
30
- # Initialize from a +Cogfile+ at the given path.
31
- # ==== Arguments
32
- # * +path+ - A file system path to a +Cogfile+. The file must exists.
33
- def initialize(path)
34
- @cogfile_path = File.expand_path path
35
- @project_root = File.dirname @cogfile_path
36
- cogfile = Cogfile.new self
37
- cogfile.interpret
29
+ # Are we operating in the context of a project?
30
+ # That is, could a Cogfile be found?
31
+ def project?
32
+ !@project_root.nil?
38
33
  end
39
-
40
- # The default configuration for the project.
34
+
35
+ # A list of directories in which to find ERB template files.
36
+ # Priority should be given first to last.
37
+ def template_paths
38
+ [@project_templates_path, @tool_templates_path, File.join(Config.gem_dir, 'templates')].compact
39
+ end
40
+
41
+ # Location of the installed cog gem
42
+ def self.gem_dir # :nodoc:
43
+ spec = Gem.loaded_specs['cog']
44
+ if spec.nil?
45
+ # The current __FILE__ is:
46
+ # ${COG_GEM_ROOT}/lib/cog/config.rb
47
+ File.expand_path File.join(File.dirname(__FILE__), '..', '..')
48
+ else
49
+ spec.gem_dir
50
+ end
51
+ end
52
+
53
+ # The singleton instance.
54
+ #
55
+ # Initialized using the +Cogfile+ for the current project, if any can be
56
+ # found. If not, then #project? will be +false+.
41
57
  #
42
- # Initialized using the +Cogfile+ for the current project.
43
58
  # The +Cogfile+ will be looked for in the present working directory. If none
44
59
  # is found there the parent directory will be checked, and then the
45
60
  # grandparent, and so on.
@@ -47,8 +62,11 @@ module Cog
47
62
  # ==== Returns
48
63
  # An instance of Cogfile which has been configured with a +Cogfile+. If no
49
64
  # such file was found then +nil+.
50
- def self.for_project
51
- return @for_project if @for_project
65
+ def self.instance
66
+ return @instance if @instance
67
+ @instance = self.new
68
+
69
+ # Attempt to find a Cogfile
52
70
  parts = Dir.pwd.split File::SEPARATOR
53
71
  i = parts.length
54
72
  while i >= 0 && !File.exists?(File.join(parts.slice(0, i) + ['Cogfile']))
@@ -56,22 +74,22 @@ module Cog
56
74
  end
57
75
  path = File.join(parts.slice(0, i) + ['Cogfile']) if i >= 0
58
76
  if path && File.exists?(path)
59
- @for_project = self.new path
77
+ @instance.instance_eval do
78
+ @cogfile_path = File.expand_path path
79
+ @project_root = File.dirname @cogfile_path
80
+ cogfile = Cogfile.new self
81
+ cogfile.interpret
82
+ end
60
83
  end
84
+
85
+ @instance
61
86
  end
62
87
 
63
- # Location of the installed cog gem
64
- def self.gem_dir # :nodoc:
65
- spec = Gem.loaded_specs['cog']
66
- if spec.nil?
67
- # The current __FILE__ is:
68
- # ${COG_GEM_ROOT}/lib/cog/config.rb
69
- File.expand_path File.join(File.dirname(__FILE__), '..', '..')
70
- else
71
- spec.gem_dir
72
- end
88
+ private
89
+
90
+ def initialize
91
+ @project_root = nil
73
92
  end
74
-
93
+
75
94
  end
76
-
77
95
  end
@@ -0,0 +1,76 @@
1
+ module Cog
2
+ class Config
3
+
4
+ # In your project's +Cogfile+, +self+ has been set to an instance of this class.
5
+ #
6
+ # ==== Example +Cogfile+
7
+ # project_generators_path 'cog/generators'
8
+ # project_templates_path 'cog/templates'
9
+ # project_source_path 'src'
10
+ # language 'c++'
11
+ #
12
+ # Typing `cog init` will create a +Cogfile+ in the present working directory.
13
+ #
14
+ # +Cogfile+ files are used to configure an instance of Config.
15
+ class Cogfile
16
+
17
+ def initialize(config) # :nodoc:
18
+ @config = config
19
+ end
20
+
21
+ # Interpret the Cogfile and initialize @config
22
+ def interpret # :nodoc:
23
+ eval File.read(@config.cogfile_path), binding
24
+ rescue Exception => e
25
+ raise CogfileError.new(e.to_s)
26
+ end
27
+
28
+ # Define the directory in which to find project generators
29
+ # ==== Arguments
30
+ # * +path+ - A file system path
31
+ # * +absolute+ - If false, the path is relative to the directory containing the +Cogfile+
32
+ def project_generators_path(path, absolute=false)
33
+ @config.instance_eval do
34
+ @project_generators_path = absolute ? path : File.join(project_root, path)
35
+ end
36
+ end
37
+
38
+ # Define the directory in which to find custom project templates
39
+ # ==== Arguments
40
+ # * +path+ - A file system path
41
+ # * +absolute+ - If false, the path is relative to the directory containing the +Cogfile+
42
+ def project_templates_path(path, absolute=false)
43
+ @config.instance_eval do
44
+ @project_templates_path = absolute ? path : File.join(project_root, path)
45
+ end
46
+ end
47
+
48
+ # Define the directory to which project source code is generated
49
+ # ==== Arguments
50
+ # * +path+ - A file system path
51
+ # * +absolute+ - If false, the path is relative to the directory containing the +Cogfile+
52
+ def project_source_path(path, absolute=false)
53
+ @config.instance_eval do
54
+ @project_source_path = absolute ? path : File.join(project_root, path)
55
+ end
56
+ end
57
+
58
+ # Define the default language in which to generated application source code
59
+ # ==== Arguments
60
+ # * +lang+ - A code for the language. Acceptable values are <tt>c++</tt>.
61
+ def language(lang)
62
+ @config.instance_eval do
63
+ @language = lang
64
+ end
65
+ end
66
+ end
67
+
68
+ # For wrapping errors which occur during the processing of a +Cogfile+.
69
+ class CogfileError < StandardError
70
+ def message
71
+ "in Cogfile, " + super
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,16 @@
1
+ module Cog
2
+
3
+ module Errors
4
+ # Indiciates an attempt to use a non-existant template.
5
+ class MissingTemplate < Exception
6
+ def initialize(template_path)
7
+ @template_path = template_path
8
+ end
9
+
10
+ def message
11
+ "could not find the template '#{@template_path}'\n#{super}"
12
+ end
13
+ end
14
+ end
15
+
16
+ end