cog 0.0.20 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/bin/cog +54 -53
  2. data/lib/cog.rb +4 -3
  3. data/lib/cog/built_in_tools/basic.rb +10 -0
  4. data/lib/cog/built_in_tools/basic/cog_tool.rb +15 -0
  5. data/lib/cog/config.rb +111 -33
  6. data/lib/cog/config/tool.rb +99 -0
  7. data/lib/cog/controllers.rb +13 -0
  8. data/lib/cog/controllers/generator_controller.rb +45 -0
  9. data/lib/cog/controllers/template_controller.rb +31 -0
  10. data/lib/cog/controllers/tool_controller.rb +53 -0
  11. data/lib/cog/errors.rb +51 -9
  12. data/lib/cog/generator.rb +1 -74
  13. data/lib/cog/helpers.rb +1 -0
  14. data/lib/cog/helpers/cascading_template_set.rb +75 -0
  15. data/lib/cog/helpers/string.rb +9 -3
  16. data/lib/cog/version.rb +1 -1
  17. data/templates/basic/generator.rb.erb +12 -0
  18. data/templates/{cog/generator/basic-template.txt.erb.erb → basic/template.txt.erb.erb} +0 -0
  19. data/templates/cog/{tool → custom_tool}/Gemfile.erb +4 -0
  20. data/templates/cog/{tool → custom_tool}/LICENSE.erb +1 -1
  21. data/templates/cog/custom_tool/README.markdown.erb +18 -0
  22. data/templates/cog/custom_tool/Rakefile.erb +15 -0
  23. data/templates/cog/custom_tool/cog_tool.rb.erb +15 -0
  24. data/templates/cog/custom_tool/generator.rb.erb.erb +9 -0
  25. data/templates/cog/{tool → custom_tool}/template.txt.erb.erb +0 -0
  26. data/templates/cog/custom_tool/tool.gemspec.erb +18 -0
  27. data/templates/cog/{tool → custom_tool}/tool.rb.erb +5 -13
  28. data/templates/cog/{tool → custom_tool}/version.rb.erb +1 -1
  29. metadata +24 -17
  30. data/lib/cog/tool.rb +0 -81
  31. data/templates/cog/generator/basic.rb.erb +0 -12
  32. data/templates/cog/tool/API.rdoc.erb +0 -7
  33. data/templates/cog/tool/README.markdown.erb +0 -18
  34. data/templates/cog/tool/Rakefile.erb +0 -15
  35. data/templates/cog/tool/generator.rb.erb.erb +0 -6
  36. data/templates/cog/tool/tool.gemspec.erb +0 -18
@@ -0,0 +1,13 @@
1
+ require 'cog/controllers/generator_controller'
2
+ require 'cog/controllers/template_controller'
3
+ require 'cog/controllers/tool_controller'
4
+ require 'cog/errors'
5
+
6
+ module Cog
7
+
8
+ # Contains controllers for managing basic +cog+ objects like generators, templates, and tools
9
+ module Controllers
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,45 @@
1
+ require 'cog/config'
2
+ require 'cog/errors'
3
+ require 'cog/helpers'
4
+ require 'rainbow'
5
+
6
+ module Cog
7
+ module Controllers
8
+
9
+ # Manage a project's generators
10
+ module GeneratorController
11
+
12
+ # Create a new generator
13
+ # @param name [String] the name to use for the new generator
14
+ # @return [Boolean] was the generator successfully created?
15
+ def self.create(name)
16
+ raise Errors::ActionRequiresProject.new('create generator') unless Config.instance.project?
17
+ generator_dest = File.join Config.instance.project_generators_path, "#{name}.rb"
18
+ raise Errors::DuplicateGenerator.new(generator_dest) if File.exists?(generator_dest)
19
+ gs = Config.instance.active_tool.generator_stamper
20
+ gs.stamp_generator name, generator_dest, Config.instance
21
+ end
22
+
23
+ # List the available project generators
24
+ # @option opt [Boolean] :verbose (false) list full paths to generator files
25
+ # @return [Array<String>] a list of generators
26
+ def self.list(opt={})
27
+ raise Errors::ActionRequiresProject.new('list generators') unless Config.instance.project?
28
+ x = Dir.glob(File.join Config.instance.project_generators_path, '*.rb')
29
+ opt[:verbose] ? x : (x.collect {|path| File.basename(path).slice(0..-4)})
30
+ end
31
+
32
+ # Run the generator with the given name
33
+ # @param name [String] name of the generator as returned by {GeneratorController.list}
34
+ # @return [nil]
35
+ def self.run(name)
36
+ raise Errors::ActionRequiresProject.new('run generator') unless Config.instance.project?
37
+ path = File.join Config.instance.project_generators_path, "#{name}.rb"
38
+ raise Errors::NoSuchGenerator.new(name) unless File.exists?(path)
39
+ require path
40
+ nil
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,31 @@
1
+ require 'cog/config'
2
+ require 'cog/errors'
3
+ require 'cog/helpers'
4
+ require 'rainbow'
5
+
6
+ module Cog
7
+ module Controllers
8
+
9
+ # Manage a project's templates
10
+ module TemplateController
11
+
12
+ # List the available templates
13
+ # @option opt [Boolean] :verbose (false) list full template paths
14
+ # @return [Array<String>] a list of templates
15
+ def self.list(opt={})
16
+ cts = Helpers::CascadingTemplateSet.new
17
+ cts.add_templates 'built-in', :built_in, Config.cog_templates_path, opt
18
+ Config.instance.tools.each do |tool|
19
+ unless tool.templates_path.nil?
20
+ cts.add_templates tool.name, :tool, tool.templates_path, opt
21
+ end
22
+ end
23
+ if Config.instance.project?
24
+ cts.add_templates 'project', :project, Config.instance.project_templates_path, opt
25
+ end
26
+ cts.to_a
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ require 'cog/config'
2
+ require 'cog/errors'
3
+ require 'cog/generator'
4
+ require 'rainbow'
5
+
6
+ module Cog
7
+ module Controllers
8
+
9
+ # Manage +cog+ tools
10
+ #
11
+ # @see https://github.com/ktonon/cog#tools Introduction to Tools
12
+ module ToolController
13
+
14
+ # Generate a new tool with the given name
15
+ # @param name [String] name of the tool to create. Should not conflict with other tool names
16
+ # @return [nil]
17
+ def self.create(name)
18
+ raise Errors::DestinationAlreadyExists.new(name) if File.exists?(name)
19
+ raise Errors::DuplicateTool.new(name) if Config.instance.tool_registered?(name)
20
+ Object.new.instance_eval do
21
+ extend Generator
22
+ @tool_name = name.to_s.downcase
23
+ @tool_module = name.to_s.capitalize
24
+ @tool_author = '<Your name goes here>'
25
+ @tool_email = 'youremail@...'
26
+ @tool_description = 'A one-liner'
27
+ @cog_version = Cog::VERSION
28
+ stamp 'cog/custom_tool/tool.rb', "#{@tool_name}/lib/#{@tool_name}.rb", :absolute_destination => true
29
+ stamp 'cog/custom_tool/cog_tool.rb', "#{@tool_name}/lib/#{@tool_name}/cog_tool.rb", :absolute_destination => true
30
+ stamp 'cog/custom_tool/version.rb', "#{@tool_name}/lib/#{@tool_name}/version.rb", :absolute_destination => true
31
+ stamp 'cog/custom_tool/generator.rb.erb', "#{@tool_name}/cog/templates/#{@tool_name}/generator.rb.erb", :absolute_destination => true
32
+ stamp 'cog/custom_tool/template.txt.erb', "#{@tool_name}/cog/templates/#{@tool_name}/#{@tool_name}.txt.erb", :absolute_destination => true
33
+ stamp 'cog/custom_tool/Gemfile', "#{@tool_name}/Gemfile", :absolute_destination => true
34
+ stamp 'cog/custom_tool/Rakefile', "#{@tool_name}/Rakefile", :absolute_destination => true
35
+ stamp 'cog/custom_tool/tool.gemspec', "#{@tool_name}/#{@tool_name}.gemspec", :absolute_destination => true
36
+ stamp 'cog/custom_tool/LICENSE', "#{@tool_name}/LICENSE", :absolute_destination => true
37
+ stamp 'cog/custom_tool/README.markdown', "#{@tool_name}/README.markdown", :absolute_destination => true
38
+ end
39
+ nil
40
+ end
41
+
42
+ # @param opt [Boolean] :verbose (false) list full paths to tools
43
+ # @return [Array<String>] a list of available tools
44
+ def self.list(opt={})
45
+ Config.instance.tools.collect do |tool|
46
+ opt[:verbose] ? tool.path : tool.name
47
+ end
48
+ end
49
+
50
+
51
+ end
52
+ end
53
+ end
@@ -1,16 +1,58 @@
1
1
  module Cog
2
2
 
3
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}"
4
+
5
+ # Root type for all cog errors
6
+ class CogError < Exception
7
+ end
8
+
9
+ # Define a +cog+ error class
10
+ # @api developer
11
+ #
12
+ # @param class_name [String] name of the error class
13
+ # @param arg [String] name of the argument to the constructor, will appear in error messages
14
+ # @yield +self+ will be set to an instance of the error class and <tt>@msg</tt> will contain
15
+ def self.define_error(class_name, arg, &block)
16
+ cls = Class.new CogError
17
+ Errors.instance_eval { const_set class_name, cls }
18
+ cls.instance_eval do
19
+ define_method(:initialize) {|value| @value = value}
20
+ define_method :message do
21
+ msg = if block.nil?
22
+ class_name.to_s.underscore.gsub '_', ' '
23
+ else
24
+ instance_eval &block
25
+ end
26
+ "#{msg} (#{arg} => #{@value})"
27
+ end
12
28
  end
13
29
  end
14
- end
15
30
 
31
+ define_error :ActionRequiresProject, 'action' do
32
+ "the action requires a project, but no Cogfile was found"
33
+ end
34
+
35
+ define_error :CouldNotLoadTool, 'tool'
36
+
37
+ define_error :DestinationAlreadyExists, 'path' do
38
+ "a file or directory at the given path already exists, cannot create anything there"
39
+ end
40
+
41
+ define_error :DuplicateGenerator, 'generator name'
42
+
43
+ define_error :DuplicateTool, 'tool'
44
+
45
+ define_error :InvalidToolConfiguration, 'path to cog_tool.rb file' do
46
+ "invalid directory structure for a cog tool"
47
+ end
48
+
49
+ define_error :NoSuchGenerator, 'generator'
50
+
51
+ define_error :NoSuchTemplate, 'template'
52
+
53
+ define_error :NoSuchTool, 'tool' do
54
+ "no such tool, make sure it appears in the COG_TOOLS environment variable"
55
+ end
56
+
57
+ end
16
58
  end
@@ -13,79 +13,6 @@ module Cog
13
13
  # @see https://github.com/ktonon/cog#generators Introduction to Generators
14
14
  module Generator
15
15
 
16
- # List the available project generators
17
- # @param verbose [Boolean] should full generator paths be listed?
18
- # @return [Array<String>] a list of generator names
19
- def self.list(verbose=false)
20
- if Config.instance.project?
21
- x = Dir.glob(File.join Config.instance.project_generators_path, '*.rb')
22
- verbose ? x : (x.collect {|path| File.basename(path).slice(0..-4)})
23
- else
24
- []
25
- end
26
- end
27
-
28
- # Create a new generator
29
- # @param name [String] the name to use for the new generator
30
- # @option opt [String] :tool ('basic') the name of the tool to use
31
- # @return [Boolean] was the generator successfully created?
32
- def self.create(name, opt={})
33
- return false unless Config.instance.project?
34
-
35
- gen_name = File.join Config.instance.project_generators_path, "#{name}.rb"
36
- if File.exists? gen_name
37
- STDERR.write "Generator '#{gen_name}' already exists\n".color(:red)
38
- return false
39
- end
40
-
41
- tool = (opt[:tool] || :basic).to_s
42
- template_name = File.join Config.instance.project_templates_path, "#{name}.txt.erb"
43
- if tool == 'basic' && File.exists?(template_name)
44
- STDERR.write "Template '#{template_name}' already exists\n".color(:red)
45
- return false
46
- end
47
-
48
- Object.new.instance_eval do
49
- extend Generator
50
- @name = name
51
- @class_name = name.to_s.camelize
52
- if tool == 'basic'
53
- stamp 'cog/generator/basic.rb', gen_name, :absolute_destination => true
54
- stamp 'cog/generator/basic-template.txt.erb', template_name, :absolute_destination => true
55
- else
56
- tool_path = Tool.find(tool)
57
- if tool_path.nil?
58
- STDERR.write "No such tool '#{tool}'"
59
- false
60
- else
61
- require tool_path
62
- @absolute_require = tool_path != tool
63
- @tool_parent_path = File.dirname(tool_path)
64
- stamp Config.instance.tool_generator_template, gen_name, :absolute_destination => true
65
- true
66
- end
67
- end
68
- end
69
- end
70
-
71
- # Run the generator with the given name
72
- # @param name [String] name of the generator as returned by {Generator.list}
73
- # @option opt [Boolean] :verbose (false) in the case of an exception, should a full stack trace be written?
74
- # @return [Boolean] was the generator run successfully?
75
- def self.run(name, opt={})
76
- filename = File.join Cog::Config.instance.project_generators_path, "#{name}.rb"
77
- if File.exists? filename
78
- require filename
79
- return true
80
- end
81
- STDERR.write "No such generator '#{name}'\n".color(:red)
82
- false
83
- rescue => e
84
- trace = opt[:verbose] ? "\n#{e.backtrace.join "\n"}" : ''
85
- STDERR.write "Generator '#{name}' failed: #{e}#{trace}\n".color(:red)
86
- false
87
- end
88
-
89
16
  # Get the template with the given name
90
17
  # @param path [String] path to template file relative one of the {Config#template_paths}
91
18
  # @option opt [Boolean] :absolute (false) is the +path+ argument absolute?
@@ -100,7 +27,7 @@ module Cog
100
27
  found.empty? && File.exists?(x) ? x : found
101
28
  end
102
29
  end
103
- raise Errors::MissingTemplate.new path unless File.exists? fullpath
30
+ raise Errors::NoSuchTemplate.new path unless File.exists? fullpath
104
31
  ERB.new File.read(fullpath), 0, '>'
105
32
  end
106
33
 
@@ -1 +1,2 @@
1
+ require 'cog/helpers/cascading_template_set'
1
2
  require 'cog/helpers/string'
@@ -0,0 +1,75 @@
1
+ require 'cog/helpers/string'
2
+ require 'rainbow'
3
+
4
+ module Cog
5
+ module Helpers
6
+
7
+ # @api developer
8
+ class TemplateInfo
9
+ attr_reader :name
10
+ attr_accessor :path
11
+
12
+ def initialize(name)
13
+ @sources = []
14
+ @source_types = []
15
+ @name = name
16
+ end
17
+
18
+ def add_source(source, source_type)
19
+ @sources << source
20
+ @source_types << source_type
21
+ end
22
+
23
+ def style(text, type)
24
+ case type
25
+ when :built_in
26
+ text.color :cyan
27
+ when :tool
28
+ text.color :yellow
29
+ when :project
30
+ text.color(:white).bright
31
+ end
32
+ end
33
+
34
+ def override_s(width=nil)
35
+ colorless = "[#{@sources.join ' < '}]"
36
+ if width
37
+ x = @sources.zip(@source_types).collect {|s, t| style s, t}
38
+ "[#{x.join ' < '}]" + " " * (width - colorless.length)
39
+ else
40
+ colorless
41
+ end
42
+ end
43
+
44
+ def <=>(other)
45
+ (@path || @name) <=> (other.path || other.name)
46
+ end
47
+
48
+ def to_s(override_column_width)
49
+ "#{override_s override_column_width} #{style @path || @name, @source_types.last}"
50
+ end
51
+ end
52
+
53
+ # @api developer
54
+ class CascadingTemplateSet
55
+ def initialize
56
+ @templates = {}
57
+ end
58
+
59
+ def add_templates(source, source_type, root, opt={})
60
+ Dir.glob("#{root}/**/*.erb") do |path|
61
+ name = path.relative_to(root).slice(0..-5)
62
+ @templates[name] ||= TemplateInfo.new name
63
+ @templates[name].path = path if opt[:verbose]
64
+ @templates[name].add_source source, source_type
65
+ end
66
+ end
67
+
68
+ def to_a
69
+ w = @templates.values.collect {|t| t.override_s.length}.max
70
+ @templates.values.sort.collect {|t| t.to_s(w)}
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -4,8 +4,14 @@ class String
4
4
 
5
5
  # @return [String] strips {Cog::Config#project_root} from the beginning of this string
6
6
  def relative_to_project_root
7
- return unless Cog::Config.instance.project?
8
- root = Cog::Config.instance.project_root
9
- start_with?(root) ? slice(root.length+1..-1) : dup
7
+ return dup unless Cog::Config.instance.project?
8
+ relative_to Cog::Config.instance.project_root
9
+ end
10
+
11
+ # @param prefix [String] path prefix to strip from the beginning of this string
12
+ # @return [String] this string as a file system path relative to the +prefix+
13
+ def relative_to(prefix)
14
+ return dup if prefix.nil?
15
+ start_with?(prefix) ? slice(prefix.length+1..-1) : dup
10
16
  end
11
17
  end
@@ -1,5 +1,5 @@
1
1
  module Cog
2
2
  unless const_defined? :VERSION
3
- VERSION = '0.0.20'
3
+ VERSION = '0.1.0'
4
4
  end
5
5
  end
@@ -0,0 +1,12 @@
1
+ require 'cog'
2
+
3
+ class <%= camelized %>
4
+ include Cog::Generator
5
+
6
+ def generate
7
+ @some_context = :my_context_value
8
+ stamp '<%= name %>.txt', 'generated_<%= name %>.txt'
9
+ end
10
+ end
11
+
12
+ <%= camelized %>.new.generate
@@ -2,3 +2,7 @@ source :rubygems
2
2
  gemspec
3
3
 
4
4
  gem "cog", "~> <%= @cog_version %>"
5
+
6
+ # Documentation
7
+ gem "yard"
8
+ gem "redcarpet"
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 <%= @author %>
1
+ Copyright (c) 2012 <%= @tool_author %>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
  this software and associated documentation files (the "Software"), to deal in
@@ -0,0 +1,18 @@
1
+ = <%= @tool_name %>
2
+
3
+ <%= @tool_description %>
4
+
5
+ Get it
6
+ ------
7
+
8
+ From a terminal
9
+
10
+ ```bash
11
+ gem install <%= @tool_name %>
12
+ ```
13
+
14
+ or in your Gemfile
15
+
16
+ ```ruby
17
+ gem "<%= @tool_name %>", "~> 0.0.1"
18
+ ```