Keep on moving

あんまりまとまってないことを書きますよ

ファイル更新でブラウザをリロードする(*BSD版)

近頃プライベートでJavaScriptを書く際に、QUnitを使ってテストをしながら書く用にしてます。
QUnitのテストはファイル変更の度に、ブラウザで画面を更新しなければならないのがちょっと面倒です。
MozReplっていうFirefox Add-on を使うことでtelnet経由でFirefoxを操作できることが分かりました。
そして検索したら、既に同じようなことをしている方を見つけました。 > ファイルの更新があったら Firefox で今開いてるページをリロード - Djangoへの片思い日記
Macでのファイル監視にkqueueっていうものがあるらしいってことも分かったので、少々ソースをアレンジさせていただいて試してみました。

ソース

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys,os,telnetlib,time
from select import *

'''
事前にMozReplを入れて、Add-on画面でStartしておくこと。
'''

# 元ソース
# ファイルの更新があったら Firefox で今開いてるページをリロード - Djangoへの片思い日記
# http://d.hatena.ne.jp/jYoshiori/20090121/1232526865
class MozRepl:

    def __init__(self, host='localhost',port=4242):
        self.tn = telnetlib.Telnet(host,port)
        self.tn.read_until("repl>")

    def reload(self):
        self.tn.write('content.location.reload(true)')

    def close(self):
        self.tn.write('repl.quit()')
        self.tn.close()

if __name__ == '__main__':
    # FreeBSD / NetBSD / OpenBSD / MacOSX only
    filename = sys.argv[1]
    print('start - ' + filename)

    mozrepl = MozRepl()

    file = open(filename, 'r')
    #kqueueで監視
    kq = kqueue()
    change = kevent(file.fileno(), KQ_FILTER_VNODE,\
        KQ_EV_ADD|KQ_EV_ENABLE|KQ_EV_ONESHOT,\
        KQ_NOTE_DELETE|KQ_NOTE_EXTEND|KQ_NOTE_WRITE|KQ_NOTE_ATTRIB,\
            0, 0)
    changes = [change]

    active = True
    while active:
        events = kq.control(changes, len(changes))
        for k in events:
            if (k.fflags & KQ_NOTE_EXTEND) or (k.fflags & KQ_NOTE_WRITE):
                mozrepl.reload()
                print ('File reload\n')
                time.sleep(1)

    mozrepl.close()
    print 'end'

まとめ

ファイル変更でブラウザをリロードしてくれるので、テストがかなり楽になりました!うれしい!
本当はフォルダを指定して、その下のファイルすべてを監視したいので、そのうち更新する予定です。
ところで、kqueueって実はTornadoなどのwebサーバなどでよく使われているみたいですね。
機会があったらもう少し使い方を調べてみます。

(2010/10/26追記)
vimで保存(:w)するとkqueueがKQ_NOTE_DELETEになるようで、ブラウザが更新されません。原因が分からない(;_;)。Emacsだときちんと検知するようなのでEmacsでこのスクリプトを使っています。