Skip to content

Instantly share code, notes, and snippets.

@EinLama
Created April 21, 2011 13:54
Show Gist options
  • Save EinLama/934533 to your computer and use it in GitHub Desktop.
Save EinLama/934533 to your computer and use it in GitHub Desktop.
Small helper script. Watches a folder and magically compiles HAML and Coffeescript-code :)
# magicWarden.rb - 2011 (c) Tobias Eilert
#
# Watches a folder recursively for changes and takes certain actions when files
# are changed. You can specify the directory you want to watch on startup.
# If no directory is passed, the magical warden will take care of the current place.
#
# $ magicWarden.rb some/path/to/some/place
# $ magicWarden.rb # same as magicWarden.rb .
#
# Runs on Mac OS X, Windows and GNU/Linux with Ruby >= 1.9.2
#
# Default settings: if a file ending on .haml is changed, warden compiles
# it to HTML. The compiled file is named "filename.html"
#
# .coffee-files are compiled to javascript files (.js).
# .scss and .sass-files are compiled to .css stylesheets.
#
# Dependencies:
# gems:
# * haml
# * coffee-script
class Array
include Enumerable
end
require 'haml'
require 'coffee-script'
require 'find'
unless ARGV.empty?
WATCH_DIR = ARGV.first
else
WATCH_DIR = '.'
end
def do_magic(patterns, file)
patterns.each do |pattern, action|
action.call(file) if pattern =~ file
end
end
def compile_to_html(file)
original_file = file
new_file = original_file.gsub(/\.haml$/i, '')
new_file += '.html' unless new_file =~ /\.html$/i
`haml #{original_file} #{new_file}`
end
def compile_to_javascript(file)
new_filename = file.gsub(/\.coffee$/i, '.js')
coffee_source = File.read(file)
javascript_source = CoffeeScript.compile coffee_source, :bare => true
File.open(new_filename, 'w') do |f|
f.write(javascript_source)
end
end
def compile_to_css(file)
new_filename = file.gsub(/(\.sass$)|(\.scss$)/i, '')
new_filename += '.css' unless new_filename =~ /\.css$/i
`sass #{file} #{new_filename}`
end
watched_files = {}
# Specify which files should not be modified. Provide regular expressions for
# filenames that should be ignored.
IGNORE_PATTERNS = [
/#{__FILE__}$/, # ignore this file
/^~/ # ignore temporary files
]
# Specify what should happen if a file matches a pattern:
WATCH_ACTION = {
/\.haml$/i => proc { |file| compile_to_html(file) },
/\.coffee$/i => proc { |file| compile_to_javascript(file) },
/\.sass$/i => proc { |file| compile_to_css(file) },
/\.scss$/i => proc { |file| compile_to_css(file) }
}
def ignore_file?(file)
IGNORE_PATTERNS.any? { |pattern| pattern =~ file }
end
def watch_file?(file)
WATCH_ACTION.any? { |pattern, action| pattern =~ file}
end
while true
begin
files_in_dir = []
Find.find(WATCH_DIR) do |file|
if File.file?(file)
files_in_dir.push(file)
# exclude certain patterns in filenames
next if ignore_file? file
next unless watch_file? file
mtime = File.mtime(file)
if !watched_files.include?(file)
watched_files[file] = mtime
puts "new file: #{file}"
else
unless watched_files[file] == mtime
# do your magic
puts "file changed: #{file}"
do_magic(WATCH_ACTION, file)
watched_files[file] = mtime
end
end
end
end
# no need to watch files that aren't existent
watched_files.keep_if { |key, value| files_in_dir.include?(key) }
rescue => e
puts e.message
end
sleep 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment