cog 0.0.20 → 0.1.0
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.
- 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
|