11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ファイルの更新を検知して、自動的にCoffeeやSassをコンパイルしたり、ブラウザをリロードしたりするスクリプト

11
Last updated at Posted at 2012-12-26

:warning: この記事の内容はかなり古いです。gulpやlivereloadなどの別のツールを使ってください


拡張子がcoffee, less, sass, scssのファイルの更新を検知すると、コンパイラを呼び出します。
拡張子がhtml, css, jsのファイルの更新を検知すると、ブラウザをリロードします。

インストールの方法と使い方
  1. easy_installでseleniumとwatchdogをインストールします。
  2. ChromeDriverをPATHの通っているところに置きます。
  3. $ python watcher.py --dir=path/to/dir
watcher.py
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import time
import commands
from os.path import splitext, extsep, abspath
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

try:
    from selenium import webdriver
    selenium_enabled = True
except ImportError:
    selenium_enabled = False

try:
    import pynotify
except ImportError:
    def notify(*args):
        """ dummy """
else:
    pynotify.init("Watcher")
    def notify(filename, error):
        notify = pynotify.Notification(filename, error, "dialog-warning")
        notify.set_timeout(1000)
        notify.show()

def get_ext(filename):
    return splitext(filename)[1].lstrip(extsep).lower()


class Compiler(FileSystemEventHandler):
    def __init__(self):
        self.compilers = {}

    def on_modified(self, event):
        ext = get_ext(event.src_path)
        if ext in self.compilers:
            status, output = self.compilers[ext](event.src_path)
            if status != 0:
                self.fail(event.src_path, output)
            else:
                self.success(event.src_path)

    def fail(self, filename, error):
        print "\x1b[31mError!: %s" % filename
        print error, "\x1b[39m"
        notify(filename, error)

    def success(self, filename):
        print "\x1b[32mCompiled: %s\x1b[39m" % filename

    def register(self, ext):
        def _register(compiler):
            self.compilers[ext] = compiler
            return compiler
        return _register

default_compiler = Compiler()
@default_compiler.register("coffee")
def coffee_compiler(path):
    return commands.getstatusoutput("coffee -c %s" % path)

@default_compiler.register("sass")
def sass_compiler(path):
    return commands.getstatusoutput("sass --update %s" % path)

@default_compiler.register("scss")
def sass_compiler(path):
    return commands.getstatusoutput("scss --update %s" % path)

@default_compiler.register("less")
def sass_compiler(path):
    out = splitext(path)[0]
    return commands.getstatusoutput("lessc %s > %s.css" % (path, out))


class BrowserReloader(FileSystemEventHandler):
    watch_ext = ["html", "js", "css"]

    def __init__(self, browser_name, url):
        super(BrowserReloader, self).__init__()

        if browser_name == "Chrome":
            self.browser = webdriver.Chrome()
        elif browser_name == "Firefox":
            self.browser = webdriver.Firefox()
        else:
            raise ValueError("Unknown browser '%s'" % browser_name)
        self.browser.get(url)

    def on_modified(self, event):
        ext = get_ext(event.src_path)
        if ext in self.watch_ext:
            self.browser.refresh()

def watch(dir, url, browser):
    observer = Observer()
    if selenium_enabled:
        reloader = BrowserReloader(browser.title(), url)
        observer.schedule(reloader, path=dir, recursive=True)
    observer.schedule(default_compiler, path=dir, recursive=True)

    print "Watching for %s" % abspath(dir)
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

if __name__ == '__main__':
    import optparse
    parser = optparse.OptionParser()
    parser.add_option("-d", "--dir", default=".")
    parser.add_option("-u", "--url", default="http://localhost/")
    parser.add_option("-b", "--browser", default="Chrome")
    options, args = parser.parse_args()
    watch(options.dir, options.url, options.browser)
11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?