くろねこ日記

ソフトウェアに関する技術メモが多いです.

Guardをつかってみた

はじめに

Guardというファイル変更を検出して動作するRuby製のツールがあります. Guardは編集して保存するだけで勝手に何かバックでコマンドを走らせることができるツールです.

guard/guard · GitHub

これをtexコンパイルなどに使うと非常に便利でしたのでメモしておきます.

Guardのインストール

gem install guard
gem install gurad-shell

guard-shellをつかうことでシェル上からGuardを常駐させたり,Guardの設定ファイルを簡単に生成できるようになります.

Guardの簡単な使い方

ここではtest.texというファイルを書くことを想定した例で説明していきます.

普通の文章でも構いませんが,ここでは例なので次のような文を書いておきます

test.tex

\documentclass[a4j]{jarticle}
\begin{document}
    テスト
\end{document}

これでGuardを導入するまでの下準備ができました.

では本題に移りましょう.

Guardの初期化をまずはしましょう

guard init

こうすることで Guardfileと呼ばれるものが生成されるはずです. 中身はrubyで記述することができます. コメントアウトがたくさん書かれてますが,必要部分はここだけです. Guardfile

guard :shell do
  watch(/(.*).txt/) {|m| `tail #{m[0]}` }
end

Rubyを知らない方にとっては意味不明かもしれませんが,ざっくり説明すると, 現在のディレクトリ以下に存在するどれかのtxtファイルが変更されたらtailコマンドをつかって変更されたファイルの末尾を出力するというものです.

なお,m[0]にはファイル名が出力されます.

ごちゃごちゃ書いても仕方ないので例をおみせしましょう. まずはGuardfileのtxtの部分をtexに変更してください

guard :shell do
  watch(/(.*).tex/) {|m| `tail #{m[0]}` }
end

これでtexファイルが変更されたら,そのtexファイルをtailで実行するというものになりました.

ではさっそくつぎのようにしてGuardを走らせましょう.

Guardの起動は簡単です.shell上で次のようにタイプしましょう.

guard

こうするとバックで動くので別なウィンドウで先程つくったtest.texを上書きしてみてください.何も編集しないで,保存だけすると次のような形でtexファイルをtailした結果がでるはずです.

\documentclass[a4j]{jarticle}
\begin{document}
    テスト
\end{document}
[1] guard(main)>

基本的な使い方はこれだけです. これでtexを保存するたびにコンパイルする方法は察しはついたかと思います. ようするに「tail m[0]」の箇所をコンパイルするときのコマンドに書き換えてあげればいいのです.

Guardをつかってコンパイルしてみる

ここではplatexをつかってtexコンパイルしてdviファイルを生成,dvipdfmxをつかってpdfを出力させてみます.

guard :shell do
  watch(/(.*).tex/) {|m| `platex test.tex && dvipdfmx test.dvi` }
end

これだけです.

あとは先程のようにGuardを実行しておけば保存するたびにコンパイルされるはずです.

ただ,僕自身癖なのか,つい上書き保存を何度もしてしまうらしくて,何もファイルが変更されてないときに保存してしまって,そのたびにコンパイルがバックで動くという面倒なことをよくやってしまいます.人によってはある条件のときだけコンパイルさせたいとかそういったこともあるとは思います.

次はそのようなときにどうするかについてメモしておきます.

特定の条件のときだけアクションを起こしたい

ここでは,ファイルに何ら変更がないときにはコンパイルをしないというような設定にしてみます.

やりかたは様々あるとは思いますが,簡単に思いついた方法があったのでそれに沿って設定してみました.

  • まずは,test.texをコピーしてbuf.texというファイルをつくります.

  • コピーしたファイルとtest.texの差分をとって,もし何らかの文字列がでてきたら,変更と見做してコンパイルを実行,何も文字列がでてこなければ変更されてないとしてコンパイルせずに無視します.

では実際にやってみましょう

まずはtest.texをコピーしてbuf.texというファイルをつくります

cp test.tex buf.tex

つぎに差分をとって変化を検出するような設定をしましょう.先程つくったGuardfileを次のように編集すればokです.

Guardfile

guard :shell do
  watch(/(.*).tex/) {|m| 
     s = `diff readme.tex buf.tex`
     if s.length > 0 then
       `cp readme.tex buf.tex`
       `platex readme.tex && dvipdfmx readme.dvi` 
     end
   }
end

簡単に紹介しますと,

     s = `diff readme.tex buf.tex`

でreadme.texとbuf.texの差分を出力してます.その結果がsという変数に代入されます.

次のif文ではs変数に代入された文字列1文字以上あればbuf.texを更新したあとtexコンパイルをするというものです.

このようにGuardfileはRubyが走るので様々な条件などで試せますね.

まとめ

Guardをtexをつかうときに便利な例をメモした.

ただファイルの変更を検出して動作させるためのものではなく,Rubyを使った自由な表現が可能なので使い方の幅が広がります.