From 0a232bd922695f6f659fac9f90466745d4425839 Mon Sep 17 00:00:00 2001 From: Chris Eppstein Date: Sat, 27 Jun 2009 18:29:47 -0700 Subject: [PATCH] [Compiler] Rewrite of the watch command that adds the following improvements: 1. For robustness, recompile is now based on comparison of corresponding css/sass file timestamps. 2. If a sass file is removed, the corresponding css file is automatically deleted. 3. CSS files will be automatically recompiled if removed. It is no longer necessary to resave the sass file. 4. First time compile is not performed if not necessary. --- lib/compass/actions.rb | 7 +++ lib/compass/commands/update_project.rb | 4 +- lib/compass/commands/watch_project.rb | 59 +++++++++++++------------- lib/compass/compiler.rb | 14 +++++- 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/lib/compass/actions.rb b/lib/compass/actions.rb index 10fd7c5f..95b9b06b 100644 --- a/lib/compass/actions.rb +++ b/lib/compass/actions.rb @@ -73,6 +73,13 @@ module Compass end end + def remove(file_name) + if File.exists?(file_name) + File.unlink file_name + logger.record :remove, basename(file_name) + end + end + def basename(file) relativize(file) {|f| File.basename(file)} end diff --git a/lib/compass/commands/update_project.rb b/lib/compass/commands/update_project.rb index 821a94ed..e00e7a8f 100644 --- a/lib/compass/commands/update_project.rb +++ b/lib/compass/commands/update_project.rb @@ -21,12 +21,12 @@ module Compass end end - def new_compiler_instance(options = {}) + def new_compiler_instance(additional_options = {}) Compass::Compiler.new(working_path, projectize(Compass.configuration.sass_dir), projectize(Compass.configuration.css_dir), Compass.sass_engine_options.merge(:quiet => options[:quiet], - :force => options[:force]).merge(options)) + :force => options[:force]).merge(additional_options)) end end diff --git a/lib/compass/commands/watch_project.rb b/lib/compass/commands/watch_project.rb index 698d9be9..97eb2fe9 100644 --- a/lib/compass/commands/watch_project.rb +++ b/lib/compass/commands/watch_project.rb @@ -7,45 +7,44 @@ module Compass module Commands class WatchProject < UpdateProject - attr_accessor :last_update_time + attr_accessor :last_update_time, :last_sass_files def perform - puts ">>> Compiling all stylesheets." - super - self.last_update_time = most_recent_update_time - puts ">>> Compass is now watching for changes. Press Ctrl-C to Stop." + Signal.trap("INT") do + puts "" + exit 0 + end + puts ">>> Compass is watching for changes. Press Ctrl-C to Stop." loop do # TODO: Make this efficient by using filesystem monitoring. + compiler = new_compiler_instance(:quiet => true) + remove_obsolete_css(compiler) + recompile(compiler) + sleep 1 + end + end + + def remove_obsolete_css(compiler) + sass_files = compiler.sass_files + deleted_sass_files = (last_sass_files || []) - sass_files + deleted_sass_files.each do |deleted_sass_file| + css_file = compiler.corresponding_css_file(deleted_sass_file) + remove(css_file) if File.exists?(css_file) + end + self.last_sass_files = sass_files + end + + def recompile(compiler) + if file = compiler.out_of_date? begin - sleep 1 - rescue Interrupt - puts "" - exit 0 - end - file, t = should_update? - if t - begin - puts ">>> Change detected to: #{file}" - super - rescue StandardError => e - ::Compass::Exec.report_error(e, options) - end - self.last_update_time = t + puts ">>> Change detected to: #{file}" + compiler.run + rescue StandardError => e + ::Compass::Exec.report_error(e, options) end end end - def most_recent_update_time - Dir.glob(separate("#{projectize(Compass.configuration.sass_dir)}/**/*.sass")).map {|sass_file| File.stat(sass_file).mtime}.max - end - - def should_update? - t = most_recent_update_time - if t > last_update_time - file = Dir.glob(separate("#{projectize(Compass.configuration.sass_dir)}/**/*.sass")).detect {|sass_file| File.stat(sass_file).mtime >= t} - [file, t] - end - end end end end \ No newline at end of file diff --git a/lib/compass/compiler.rb b/lib/compass/compiler.rb index 9134553e..84fb3945 100644 --- a/lib/compass/compiler.rb +++ b/lib/compass/compiler.rb @@ -22,13 +22,25 @@ module Compass end def css_files - @css_files ||= sass_files.map{|sass_file| "#{to}/#{stylesheet_name(sass_file)}.css"} + @css_files ||= sass_files.map{|sass_file| corresponding_css_file(sass_file)} + end + + def corresponding_css_file(sass_file) + "#{to}/#{stylesheet_name(sass_file)}.css" end def target_directories css_files.map{|css_file| File.dirname(css_file)}.uniq.sort.sort_by{|d| d.length } end + def out_of_date? + sass_files.zip(css_files).each do |sass_filename, css_filename| + return sass_filename unless File.exists?(css_filename) + return sass_filename if File.stat(sass_filename).mtime > File.stat(css_filename).mtime + end + false + end + def run Compass.configure_sass_plugin! target_directories.each do |dir|