Refactor the Compass commands to centralize and cleanup the project commands.

This commit is contained in:
Chris Eppstein 2009-01-25 14:27:08 -08:00
parent 911041f355
commit 1e5502159b
7 changed files with 142 additions and 90 deletions

View File

@ -13,18 +13,22 @@ module Compass
protected
def projectize(path)
File.join(project_directory, separate(path))
def relativize(path)
if path.index(working_directory+File::SEPARATOR) == 0
path[(working_directory+File::SEPARATOR).length..-1]
else
path
end
end
# create a directory and all the directories necessary to reach it.
def directory(subdir, options = nil)
def directory(dir, options = nil)
options ||= self.options
dir = subdir ? projectize(subdir) : project_directory
if File.exists?(dir) && File.directory?(dir) && options[:force]
print_action :exists, basename(dir) + File::SEPARATOR
elsif File.exists?(dir) && File.directory?(dir)
msg = "Directory #{basename(dir)} already exists. Run with --force to force project creation."
raise ::Compass::Exec::ExecError.new(msg)
msg = "Directory #{basename(dir)} already exists. Run with --force to force creation."
raise ::Compass::Exec::DirectoryExistsError.new(msg)
elsif File.exists?(dir)
msg = "#{basename(dir)} already exists and is not a directory."
raise ::Compass::Exec::ExecError.new(msg)
@ -34,9 +38,13 @@ module Compass
end
end
def absolute_path?(path)
# This is only going to work on unix, gonna need a better implementation.
path.index(File::SEPARATOR) == 0
end
# copy/process a template in the compass template directory to the project directory.
def template(from, to, options)
to = projectize(to)
from = File.join(templates_directory, separate(from))
if File.exists?(to) && !options[:force]
#TODO: Detect differences & provide an overwrite prompt
@ -75,9 +83,9 @@ module Compass
path.gsub(%r{/}, File::SEPARATOR)
end
def basename(file, extra = 0)
if file.length > (working_directory.length + extra)
file[(working_directory.length + extra + 1)..-1]
def basename(file)
if file.length > working_directory.length
relativize(file)
else
File.basename(file)
end

View File

@ -4,33 +4,41 @@ require File.join(File.dirname(__FILE__), 'update_project')
module Compass
module Commands
class CreateProject < Base
attr_accessor :project_directory, :project_name
class CreateProject < ProjectBase
def initialize(working_directory, options)
super(working_directory, options)
self.project_name = options[:project_name]
self.project_directory = File.expand_path File.join(working_directory, project_name)
end
# all commands must implement perform
def perform
begin
directory nil, options
rescue Compass::Exec::DirectoryExistsError
msg = "Project directory already exists. Run with -u to update or --force to force creation."
raise ::Compass::Exec::DirectoryExistsError.new(msg)
end
src_dir = options[:src_dir] || "src"
css_dir = options[:css_dir] || "stylesheets"
directory src_dir, options.merge(:force => true)
directory css_dir, options.merge(:force => true)
project_dir = File.join(templates_directory, "project")
templates = Dir.chdir(project_dir) do
Dir.glob("*")
end
templates.each do |t|
framework_templates.each do |t|
template "project/#{t}", "#{src_dir}/#{t}", options
end
UpdateProject.new(working_directory, options).perform
end
def framework_templates
framework_project_dir = File.join(templates_directory, "project")
Dir.chdir(framework_project_dir) do
Dir.glob("*")
end
end
def skip_project_directory_assertion?
true
end
end
end
end

View File

@ -2,42 +2,26 @@ require File.join(File.dirname(__FILE__), 'base')
module Compass
module Commands
class InstallRails < Base
def initialize(working_directory, options)
wd = options[:project_name] ? File.join(working_directory, options.delete(:project_name)) : working_directory
super(wd, options)
class InstallRails < CreateProject
def initialize(*args)
super
end
def perform
set_install_location
set_output_location
directory options[:stylesheets_location]
template 'project/screen.sass', "#{options[:stylesheets_location]}/screen.sass", options
template 'project/print.sass', "#{options[:stylesheets_location]}/print.sass", options
template 'project/ie.sass', "#{options[:stylesheets_location]}/ie.sass", options
write_file projectize('config/initializers/compass.rb'), initializer_contents
framework_templates.each do |t|
template "project/#{t}", "#{options[:stylesheets_location]}/#{t}", options
end
write_file 'config/initializers/compass.rb', initializer_contents
if has_application_layout?
next_steps
else
write_file projectize('app/views/layouts/application.html.haml'), application_layout_contents
write_file 'app/views/layouts/application.html.haml', application_layout_contents
end
end
def initializer
init_file =
if File.exists?(init_file) && !options[:force]
msg = "File #{basename(init_file)} already exists. Run with --force to force project creation."
raise ::Compass::Exec::ExecError.new(msg)
end
if File.exists?(init_file)
print_action :overwrite, basename(init_file)
else
print_action :create, basename(init_file)
end
output = open(init_file,'w')
output.write(initializer_contents)
output.close
end
def initializer_contents
%Q{require 'compass'
# If you have any compass plugins, require them here.
@ -97,10 +81,6 @@ NEXTSTEPS
end
end
def project_directory
working_directory
end
def set_install_location
print "Compass recommends that you keep your stylesheets in app/stylesheets/ instead of the Sass default location of public/stylesheets/sass/.\nIs this OK? (Y/n) "
answer = gets

View File

@ -0,0 +1,89 @@
require 'rubygems'
require 'sass'
require 'fileutils'
require 'pathname'
require File.join(File.dirname(__FILE__), 'base')
module Compass
module Commands
class ProjectBase < Base
attr_accessor :project_directory, :project_name, :options, :project_src_subdirectory, :project_css_subdirectory
def initialize(working_directory, options = {})
super(working_directory, options)
self.project_name = determine_project_name(working_directory, options)
self.project_directory = determine_project_directory(working_directory, options)
assert_project_directory_exists!
end
protected
def directory(subdir, options = nil)
subdir ||= project_directory
subdir = projectize(subdir) unless absolute_path?(subdir)
super(subdir, options)
end
def template(from, to, options)
to = projectize(to) unless absolute_path?(to)
super(from, to, options)
end
def write_file(path, contents)
path = projectize(path) unless absolute_path?(path)
super(path, contents)
end
def projectize(path)
File.join(project_directory, separate(path))
end
# Read the configuration file for this project
def read_project_configuration
config_file = projectize('src/config.rb')
if File.exists?(config_file)
contents = open(config_file) {|f| f.read}
eval(contents, nil, config_file)
end
end
private
def determine_project_name(working_directory, options)
if options[:project_name]
File.basename(strip_trailing_separator(options[:project_name]))
else
File.basename(working_directory)
end
end
def determine_project_directory(working_directory, options)
if options[:project_name]
if absolute_path?(options[:project_name])
options[:project_name]
else
File.join(working_directory, options[:project_name])
end
else
working_directory
end
end
def assert_project_directory_exists!
if File.exists?(project_directory) && !File.directory?(project_directory)
raise Compass::Exec::ExecError.new("#{project_directory} is not a directory.")
elsif !File.directory?(project_directory) && !skip_project_directory_assertion?
raise ::Compass::Exec::ExecError.new("#{project_directory} does not exist.")
end
end
def skip_project_directory_assertion?
options[:force] || options[:dry_run]
end
def strip_trailing_separator(path)
(path[-1..-1] == File::SEPARATOR) ? path[0..-2] : path
end
end
end
end

View File

@ -1,40 +1,12 @@
require 'rubygems'
require 'sass'
require 'fileutils'
require 'pathname'
require File.join(File.dirname(__FILE__), 'base')
require File.join(File.dirname(__FILE__), 'project_base')
module Compass
module Commands
class UpdateProject < Base
class UpdateProject < ProjectBase
Base::ACTIONS << :compile
Base::ACTIONS << :overwrite
attr_accessor :project_directory, :project_name, :options, :project_src_subdirectory, :project_css_subdirectory
def initialize(working_directory, options = {})
super(working_directory, options)
if options[:project_name]
options[:project_name] = options[:project_name][0..-2] if options[:project_name][-1..-1] == File::SEPARATOR
self.project_name = File.basename(options[:project_name])
if options[:project_name][0] == File::SEPARATOR
self.project_directory = options[:project_name]
elsif File.directory?(File.join(working_directory, options[:project_name]))
self.project_directory = File.expand_path(File.join(working_directory, options[:project_name]))
else
if File.exists?(options[:project_name]) or File.exists?(File.join(working_directory, options[:project_name]))
raise ::Compass::Exec::ExecError.new("#{options[:project_name]} is not a directory.")
elsif !(options[:force] || options[:dry_run])
raise ::Compass::Exec::ExecError.new("#{options[:project_name]} does not exist.")
end
end
else
self.project_name = File.basename(working_directory)
self.project_directory = working_directory
end
end
def perform
read_project_configuration
Dir.glob(separate("#{project_src_directory}/**/[^_]*.sass")).each do |sass_file|
@ -77,15 +49,6 @@ module Compass
end
end
# Read the configuration file for this project
def read_project_configuration
config_file = projectize('src/config.rb')
if File.exists?(config_file)
contents = open(config_file) {|f| f.read}
eval(contents, nil, config_file)
end
end
# where to load sass files from
def sass_load_paths
@sass_load_paths ||= [project_src_directory] + Compass::Frameworks::ALL.map{|f| f.stylesheets_directory}

View File

@ -7,6 +7,9 @@ module Compass
class ExecError < StandardError
end
class DirectoryExistsError < ExecError
end
def report_error(e, options)
$stderr.puts "#{e.class} on line #{get_line e} of #{get_file e}: #{e.message}"

View File

@ -55,6 +55,7 @@ class CommandLineTest < Test::Unit::TestCase
assert_action_performed :create, "app/stylesheets/screen.sass"
assert_action_performed :create, "config/initializers/compass.rb"
assert_action_performed :create, "app/views/layouts/application.html.haml"
assert_action_performed :create, "config/initializers/compass.rb"
end
end
rescue LoadError