lib/cog/dsl/cogfile.rb
module Cog
module DSL
# In your project's +Cogfile+, +self+ has been set to an instance of this class.
# Typing <tt>cog init</tt> will create a +Cogfile+ in the present working directory.
class Cogfile
include Generator
# Initialize with an instance of {Config}
# @api developer
# @param config [Config] the object which will be configured by this Cogfile
# @param path [String] path to the cogfile
# @option opt [Boolean] :project (false) is this the project cogfile?
# @option opt [Boolean] :plugin_path_only (false) only process +plugin_path+ calls in the given cogfile
# @option opt [Plugin] :plugin (nil) indicate that the cogfile is for the given plugin
def initialize(config, path, opt={})
@cogfile_context = {
:config => config,
:cogfile_path => path,
:cogfile_dir => File.dirname(path),
:project => opt[:project],
:plugin_path_only => opt[:plugin_path_only],
:plugin => opt[:plugin],
}
end
# Interpret the +Cogfile+ at {Config::ProjectConfig#cogfile_path}
# @api developer
# @return [nil]
def interpret
eval File.read(cogfile_path), binding
nil
end
# Define the directory in which to generate code. A call to this method will be ignored if the containing cogfile is being treated as a plugin.
# @param path [String] a file system path to a directory
# @param absolute [Boolean] if +false+, the path is relative to {Config::ProjectConfig#project_root}
# @return [nil]
def project_path(path, absolute=false)
return if plugin_path_only? || plugin?
path = File.join @cogfile_context[:cogfile_dir], path unless absolute
config_eval { @project_path = path }
end
# Define a directory in which to find generators
# @param path [String] a file system path
# @param absolute [Boolean] if +false+, the path is relative to {Config::ProjectConfig#project_root}
# @return [nil]
def generator_path(path, absolute=false)
return if plugin_path_only?
add_config_path :generator, path, absolute
end
# Define a directory in which to find templates
# @param path [String] a file system path
# @param absolute [Boolean] if +false+, the path is relative to {Config::ProjectConfig#project_root}
# @return [nil]
def template_path(path, absolute=false)
return if plugin_path_only?
add_config_path :template, path, absolute
end
# Define a directory in which to find plugins. A call to this method will be ignored if the containing cogfile is itself being treated as a plugin.
# @param path [String] a file system path
# @param absolute [Boolean] if +false+, the path is relative to {Config::ProjectConfig#project_root}
# @return [nil]
def plugin_path(path, absolute=false)
return if plugin?
path = add_config_path :plugin, path, absolute
if path && File.exists?(path)
raise Errors::PluginPathIsNotADirectory.new path unless File.directory?(path)
@cogfile_context[:config].register_plugins path
end
end
# Explicitly specify a mapping from file extensions to languages
# @param map [Hash] key-value pairs from this mapping will override the default language map supplied by +cog+
# @return [nil]
def language_extensions(map)
return if plugin_path_only?
config_eval do
map.each_pair do |key, value|
@language_extension_map[key.to_s.downcase] = value.to_s.downcase
end
end
end
# Define and register a language with cog
# @param key [String] unique case-insensitive identifier
# @yieldparam lang [LanguageDSL] an interface for defining the language
# @return [Object] the return value of the block
def language(key, &block)
return if plugin_path_only?
dsl = LanguageDSL.new key
r = block.call dsl
lang = dsl.finalize
config_eval do
@language[lang.key] = lang
end
r
end
# Register an autoload variable in the class {GeneratorSandbox}. That way when generators are run as instances of a sandbox, they will be able to load plugins just by referencing them using the provided +identifier_name+. A call to this method will be ignored unless the containing cogfile is being treated as a plugin.
# @param identifier_name [String] identifier by which the plugin can be referenced in generators
# @param path [String] path to the ruby file to load when the identifier is referenced (relative to the cogfile)
# @return [nil]
def autoload_plugin(identifier_name, path)
if plugin?
GeneratorSandbox.autoload_plugin(identifier_name, File.join(plugin.path, path))
end
end
# Define a block to call when stamping a generator for a plugin. A call to this method will be ignored unless the containing cogfile is being treated as a plugin.
# @yieldparam name [String] name of the generator to stamp
# @yieldparam dest [String] file system path where the file will be created
# @yieldreturn [nil]
# @return [nil]
def stamp_generator(&block)
plugin.stamp_generator_block = block if plugin?
end
private
# @return [Plugin,nil] the plugin description
def plugin
@cogfile_context[:plugin]
end
# @return [Boolean] is this a plugin cogfile?
def plugin?
!@cogfile_context[:plugin].nil?
end
# @return [Boolean] should only the {#plugin_path} call be processed?
def plugin_path_only?
@cogfile_context[:plugin_path_only]
end
# @return [String] path to the cogfile
def cogfile_path
@cogfile_context[:cogfile_path]
end
# @return [nil]
def config_eval(&block)
@cogfile_context[:config].instance_eval &block
nil
end
# @return [String,nil] absolute path
def add_config_path(name, path, absolute)
return if path.nil?
path = File.join @cogfile_context[:cogfile_dir], path unless absolute
is_project = @cogfile_context[:project]
config_eval do
instance_variable_set("@project_#{name}_path", path) if is_project
instance_variable_get("@#{name}_path") << path
end
path
end
end
end
end