cog 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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