CotEditor から LaTeX をタイプセットするスクリプト

## はじめに

***2017/11/10 修正***
*編集中の TeX ファイルのフルパスが空白を含んでいる場合、スクリプトが正常に実行されません。スクリプトを修正しました。*

普段、論文などを執筆するときは、LaTeX を使っています。今までは、LaTeXTools というプラグインを使って Sublime Text で書いていました。ほとんど不満はありません。しかし、Sublime Text は日本語入力には弱いです。検索や単語・文節区切りのカーソル移動はできないのです。それの回避策はありますが、それでも不便です。

それに対して、ご存知、Mac で使える日本語入力に強いテキストエディタ、[CotEditor](https://coteditor.com) があります。プログラミング用に文法ハイライト機能も搭載されています。機能を拡張するためのスクリプティングも提供されています。しかし残念ながら、Sublime Text のようなスクリプト・リポジトリはありません。LaTeX 用は、いくつか公開されていますが、そのまま満足できるものは現時点ではありません。

そんなわけでスクリプトを作りました。このスクリプトは、[CotEditor から AppleScript で latexmk を叩く](https://aximov.wordpress.com/2016/01/20/coteditor-latexmk/)を参考に作りました。私も普段 `latexmk` を使っているのでちょうどいいです。

作ったスクリプトは、出力の PDF ファイルを自動的にプレビューし、エディタで今カーソルのあるところまで飛んでくれます。PDF のプレビューは、[Skim](http://skim-app.sourceforge.net) を使います。

## `.latexmkrc`

まず、`latexmk` を実行するためのパラメータを `.latexmkrc` にまとめてホームディレクトリに保存しておきます。以下は、私の場合です。

```bash:.latexmkrc
#!/usr/bin/env perl
$latex            = 'platex -synctex=1';
$latex_silent     = 'platex -synctex=1 -interaction=batchmode';
$pdflatex         = 'pdflatex -synctex=1 %O %S';
$bibtex           = 'pbibtex';
$dvipdf           = 'dvipdfmx %O -o %D %S';
$makeindex        = 'mendex %O -o %D %S';
$max_repeat       = 5;
$pdf_mode         = 3; # generates pdf via dvipdfmx

# Prevent latexmk from removing PDF after typeset.
# This enables Skim to chase the update in PDF automatically.
$pvc_view_file_via_temporary = 0;

# Use Skim as a previewer
$pdf_previewer    = "open -a /Applications/Skim.app";
```

英文の LaTeX をタオプセットするときは `pdflatex` を、和文の LaTeX をタオプセットするときは `platex` + `dvipdfmx` を使うように設定してあります。`latexmk` コマンドを `-pdf` か `-pdfdvi` かを付けて実行します。パラメータは、適宜変更してください。

## スクリプト

スクリプトは 3 つあります：pLaTeX でタイプセットする場合、pdfLaTeX でタイプセットする場合、それから LaTeX 出力をクリーンアップする場合です。

まず、pdfLaTeX でタイプセットするスクリプトは次になります。

```AppleScript:pdfLaTeX.applescript
tell application "CotEditor"
    if exists front document then
        set thelinerange to line range of selection of front document
        set theline to item 1 of thelinerange
        set thisfile to path of front document as Unicode text
        set thisdir to (do shell script "/usr/bin/dirname \"" & thisfile & "\"")
        set thisbase to thisdir & "/" & (do shell script "/usr/bin/basename \"" & thisfile & "\" .tex")
        set thispdf to thisbase & ".pdf"
        set thislog to thisbase & ".log"
        set acommand to "/Applications/Skim.app/Contents/SharedSupport/displayline -r"
    
        if (thisfile is not "") then 
            tell application "Terminal"
                activate
                do script with command "latexmk -pdf -cd \"" & thisfile & "\"; " & "if ! grep -Fq \\^\\! \"" & thislog & "\"; then " & acommand & " " & theline & " \"" & thispdf & "\" \"" & thisfile & "\"; " & "fi; " & "exit"
            end tell
        end if
        activate
    end if
end tell
```

このスクリプトの仕組みは次になります：

- `latexmk` で LaTeX ファイルをタイプセットします。ターミナルを起動してその中で実行します。
- エラーが発生しない場合は、そのまま出力の PDF ファイルを Skim でプレビューして、ターミナルを自動的に閉じます。
- エラーが発生した場合は、ターミナルを表示したままスクリプトを停止します。エラーを確認したら、ターミナルを自動的に閉じます。

では、次は、`pLaTeX` + `dvipdfmx` でタイプセットする場合スクリプトです。仕組みは同じです。

```AppleScript:pLaTeX.applescript
tell application "CotEditor"
    if exists front document then
        set thelinerange to line range of selection of front document
        set theline to item 1 of thelinerange
        set thisfile to path of front document as Unicode text
        set thisdir to (do shell script "/usr/bin/dirname \"" & thisfile & "\"")
        set thisbase to thisdir & "/" & (do shell script "/usr/bin/basename \"" & thisfile & "\" .tex")
        set thispdf to thisbase & ".pdf"
        set thislog to thisbase & ".log"
        set acommand to "/Applications/Skim.app/Contents/SharedSupport/displayline -r"
    
        if (thisfile is not "") then 
            tell application "Terminal"
                activate
                do script with command "latexmk -pdfdvi -cd \"" & thisfile & "\"; " & "if ! grep -Fq \\^\\! \"" & thislog & "\"; then " & acommand & " " & theline & " \"" & thispdf & "\" \"" & thisfile & "\"; " & "fi; " & "exit"
            end tell
        end if
        activate
    end if
end tell
```

最後に、LaTeX の出力をクリーンアップするスクリプトです。

```AppleScript:CleanupLaTeX.applescript
tell application "CotEditor"
    if exists front document then
        set thisfile to path of front document as Unicode text
    
        if (thisfile is not "") then 
            tell application "Terminal"
                activate
                do script with command "latexmk -cd -c \"" & thisfile & "\"; exit"
            end tell
        end if
        activate
    end if
end tell
```

このスクリプトは、PDF、DVI と PS ファイルを残します。それらのファイルも削除したい場合は、`-c` の代わりに `-C` を付けて `latexmk` を実行してください。

以上です！

## おまけ

上記スクリプトは、Skim で PDF をプレビューするときに、エディタで今カーソルのあるところまで飛んでくれます。Skim には、その逆もできます。Skim で <kbd>Shift</kbd> <kbd>Command</kbd> クリックすると、CotEditor がアクティブなって、クリックしたところまでスクロールします。

設定は、Sublime Text やその他のメージャーなエディタ用のあらかじめ用意されているものはありますが、残念ながら CotEditor 用はありません。次のように設定します。

<img width="495" alt="Skim_Sync.png" src="https://qiita-image-store.s3.amazonaws.com/0/100827/09fdd2c9-eec2-8164-f1b9-5eb342d0eeba.png">

- **Check for file changes** のチェックは外します（デフォルトはチェックされていません）。
- **Preset** には、*Custom* を選択してください。
- **Command** には、`/Applications/CotEditor.app/Contents/SharedSupport/bin/cot` を入力してください。
- 最後に、**Argument** には `-l %line "%file"` を入力してください。

どうぞ試してください。