vim でファイルを保存した時にGoogle Chrome で開いているページをリロードする

HTML を編集している時に必須の機能。今回試した方法は、

  1. AppleScript を使う
  2. ChromeReplを使う
  3. livereload

の3つです。最終的に、(不満ながらも)AppleScript 版を使っています。

1. AppleScript を使う

http://blog.cohtan.org/2008/03/vimhtmlyacss.htmlを参考にしました。

AppleScript の設置
tell application "Google Chrome" to activate
tell application "System Events" to keystroke "r" using {command down}
  • ~/bin/terminal_focus.scpt
tell application "Terminal" to activate
vim コマンドの定義
command! -bar ChromeReload silent !osascript $HOME/bin/chrome_reload.scpt && osascript $HOME/bin/terminal_focus.scpt
command! -bar ChromeStartObserve ChromeStopObserve | autocmd BufWritePost <buffer> ChromeReload
command! -bar ChromeStopObserve autocmd! BufWritePost <buffer>

id:tyru さんにご指摘いただき、ChromeStartObserve を複数回実行しても、リロードが一回しか行われないよう修正


スクリプトを2つに分けているのは、ひとつのスクリプトで、Chrome をactivate ⇒ リロード ⇒ Terminal をactivate とすると、たまにキーストロークが実行される前にTerminal に戻ってきてしまいリロードが走らないためです。
別の解決方法がある気がするのですが・・・。

使い方
  • :ChromeReload で現在開いているページをリロード
  • :ChromeStartObserve を実行すると、以降そのバッファの内容を保存した時にChrome のリロードが実行されるようになる
  • :ChromeStopObserve は、StartObserver の実行後、保存とリロードの連携を解除したい時に実行する


vim の方は、id:ursm さんの、Firefox を自動的にリロードする Vim スクリプト - ursmの日記を参考にしました。ursm++。

考察
  • メリット
    • 簡単
  • デメリット
    • OSX でしか動かない
    • activate の関係で、vim(Terminal)からフォーカスが奪われてしまい、保存直後にスムーズに編集を続けられない

2. ChromeReplを使う

blog.8-p.info: Google Chrome で「保存したらリロード」を参考にしました。

ChromeRepl のクライアントをインストール
gem install google-chrome-client
vim コマンドの定義

ChromeStartObserve、ChromeStopObserve コマンドはAppleScript の時と同じで、ChromeReload だけを書き換えてあげればOKです。

command! -bar ChromeReload silent !chrome-repl -e "chrome.tabs.getSelected(null, function (t) { chrome.tabs.executeScript(t.id, { code: 'location.reload()' }) });"
使い方
  • Chrome をオプションつきで起動
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-shell-port=9222


alias の例。

alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-shell-port=9222 > /dev/null 2>&1 &"
考察
  • メリット
    • フォーカスをChrome に奪われない
    • OSX でなくても動く
    • エディタ環境とブラウザ環境が別のホストにあっても平気
  • デメリット
    • OSX の場合、Chrome のデフォルトの起動オプションを指定できない(と思う)ので、Chrome を再起動する度に上記のコマンドを実行する必要があって面倒
    • リモートシェルを起動している状態で、Chromeデベロッパーツールを使うと、ページによってはリロード時に固まってしまった。デベロッパーツールを閉じるとリロードが再開されるので、どこかでブレークしているのかもしれない
    • ruby

3. livereloadを使う

Twiwt:Blog / jugyo : LiveReload & guard-livereloadを参考にしました。
が、まだきちんと動いていないので、こうすれば動くはずという手順を書きます。

livereload をインストール
gem install livereload -v 1.3

最新版の1.4 を使うと、RubyCocoa のライブラリをロードしようとしてエラーしてしまうので、Issues - RubyCocoa is not reliable, get rid of using it (osx/foundation issues etc)にあるとおり、1.3 を使います。


また、ruby < 1.8.7 を使っている場合、livereload.rb 内でEnumerable#reduce を使っている部分でエラーするので、reduce をinject に書き換えてあげます。

livereload のChrome 拡張をインストール

現在Web で配布されている拡張は1.4 向けのものなので、livereload クライアント1.3 と一緒には使えないので、mockko's livereload at v1.3 - GitHubの拡張をインストールします。

  1. livereload 1.3 をローカルにダウンロード
  2. Chrome拡張機能の画面を開く(OSX では、ウィンドウ ⇒ 拡張機能)
  3. デベロッパーモードをクリック
  4. パッケージ化されていない拡張を読み込むを選択
  5. livereload のLiveReload.chromeextension/ のディレクトリを選択し、開く
  6. インストール完了
使い方

指定したディレクトリ以下のファイルに変更があったらリロードするという仕様なので、ディレクトリを指定して起動。指定しなかった場合は、カレントディレクトリ以下のファイルを監視します。

cd path/to/yourapp
livereload


ファイルに変更があったときに、ブラウザのWebSocket をたたくサーバが起動します。次に、ブラウザ側でリロードしたいページを開き、livereload の拡張をON にします。
あとは、ファイルに変化があればブラウザーをリロードしてくれる。


本当はこうすると動くはずなのですが、現在僕の環境ですとファイルの変化が検知されずブラウザにリロードの命令が飛びません。うーん。

考察
  • メリット
    • エディタに依存しない
    • エディタの環境とブラウザの環境が別のホストにあっても平気
      • VM でサーバ起動して、ssh で作業。ブラウザはホストOS 側のを使っている場合とか
    • Safari でも使える
  • デメリット
    • ruby
    • 1.3 だと、監視対象ファイルが多すぎるとlivereload サーバを起動できない。HTML があるディレクトリだけを明示的に指定する必要がある
    • リロードしたいだけでブラウザと通信するサーバをたてるとか大袈裟な感じ


以上、vim でファイルを保存した時にChrome のページをリロードする3つの方法でした。僕の環境ですと、AppleScript 版以外の2つは、動作に問題がありますので、AppleScript 版を使っています(´ω`;)
ChromeRepl、livereload は使い勝手がよいので、いずれこれらに移行したらまたBlog を書きたいと思います。