cog 0.0.20 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cog +54 -53
- data/lib/cog.rb +4 -3
- data/lib/cog/built_in_tools/basic.rb +10 -0
- data/lib/cog/built_in_tools/basic/cog_tool.rb +15 -0
- data/lib/cog/config.rb +111 -33
- data/lib/cog/config/tool.rb +99 -0
- data/lib/cog/controllers.rb +13 -0
- data/lib/cog/controllers/generator_controller.rb +45 -0
- data/lib/cog/controllers/template_controller.rb +31 -0
- data/lib/cog/controllers/tool_controller.rb +53 -0
- data/lib/cog/errors.rb +51 -9
- data/lib/cog/generator.rb +1 -74
- data/lib/cog/helpers.rb +1 -0
- data/lib/cog/helpers/cascading_template_set.rb +75 -0
- data/lib/cog/helpers/string.rb +9 -3
- data/lib/cog/version.rb +1 -1
- data/templates/basic/generator.rb.erb +12 -0
- data/templates/{cog/generator/basic-template.txt.erb.erb → basic/template.txt.erb.erb} +0 -0
- data/templates/cog/{tool → custom_tool}/Gemfile.erb +4 -0
- data/templates/cog/{tool → custom_tool}/LICENSE.erb +1 -1
- data/templates/cog/custom_tool/README.markdown.erb +18 -0
- data/templates/cog/custom_tool/Rakefile.erb +15 -0
- data/templates/cog/custom_tool/cog_tool.rb.erb +15 -0
- data/templates/cog/custom_tool/generator.rb.erb.erb +9 -0
- data/templates/cog/{tool → custom_tool}/template.txt.erb.erb +0 -0
- data/templates/cog/custom_tool/tool.gemspec.erb +18 -0
- data/templates/cog/{tool → custom_tool}/tool.rb.erb +5 -13
- data/templates/cog/{tool → custom_tool}/version.rb.erb +1 -1
- metadata +24 -17
- data/lib/cog/tool.rb +0 -81
- data/templates/cog/generator/basic.rb.erb +0 -12
- data/templates/cog/tool/API.rdoc.erb +0 -7
- data/templates/cog/tool/README.markdown.erb +0 -18
- data/templates/cog/tool/Rakefile.erb +0 -15
- data/templates/cog/tool/generator.rb.erb.erb +0 -6
- 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
|
data/lib/cog/errors.rb
CHANGED
@@ -1,16 +1,58 @@
|
|
1
1
|
module Cog
|
2
2
|
|
3
3
|
module Errors
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
data/lib/cog/generator.rb
CHANGED
@@ -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::
|
30
|
+
raise Errors::NoSuchTemplate.new path unless File.exists? fullpath
|
104
31
|
ERB.new File.read(fullpath), 0, '>'
|
105
32
|
end
|
106
33
|
|
data/lib/cog/helpers.rb
CHANGED
@@ -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
|
data/lib/cog/helpers/string.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
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
|
data/lib/cog/version.rb
CHANGED
File without changes
|