ptex2pdfがghq管理下のリポジトリでPDFを作成できないことがある

この記事は、[TeX ＆ LaTeX Advent Calendar 2018](https://adventar.org/calendars/3382) 12日目の記事です。
Lua(La)TeXとは無関係ですが、Lua要素はあります（強引）。

昨日の記事は、p_typoさんの「[添字のお話](https://note.mu/yuw/n/ne4f1e2f78b3d)」でした。

---
## TL;DR
- VS Code&LaTeX Workshopで、ghq管理リポジトリの`.tex`ファイルのビルドに失敗する可能性がある
    - `ptex2pdf`がドット入りのディレクトリパスを正しく扱えないため
- 
2018年12月現在、[`ptex2pdf`のGitHubリポジトリ](https://github.com/texjporg/ptex2pdf)では修正されている

    - 本記事公開当日の12日、[**version 20181212.0としてCTANにリリースされました**](https://ctan.org/pkg/ptex2pdf)

## はじめに
初めて参加させていただきます。@kn1chtです。

$\rm{\LaTeX}$歴0年の初心者です。環境だけは手元に揃えていたものの、[pandoc](https://pandoc.org/)でMarkdown文書をPDF化するのに使っていただけでした。
いよいよ学位論文を書くことになり、流石に$\rm{\LaTeX}$で書かねばと思い執筆環境を整えました。
その過程で`ptex2pdf`のバグを踏んで報告&Pull Requestしたら採用していただいたので、経緯を書きたいと思います。

## 環境
- [MacTeX 2018](http://www.tug.org/mactex/)
- Visual Studio Code `1.29.1`
- [LaTeX Workshop](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop) `5.17.3`
- [ghq](https://github.com/motemen/ghq) `0.8.0`

## 問題の発見
### ghqによるリポジトリの取得
VS Codeで書くのが快適だと聞き、[Visual Studio CodeでTeXのコンパイルをできるようにする方法](https://qiita.com/SUZUKI_Masaya/items/7fb5509006163e7e671f)を参考に設定しました。
日本語の文書が無事コンパイルできるか試すため、適当なテンプレートをGitHubからcloneします。

<font color="SlateGray">※実際に使ったリポジトリはprivateのため、ここでは[情報システム工学研究室(JSK)](http://www.jsk.t.u-tokyo.ac.jp/index-j.html) 様のテンプレートを使用させていただきます</font>

```bash
$ ghq get jsk-report-template/ci-thesis.git
```

ここで使ったツールは**[ghq](https://github.com/motemen/ghq)というGitリポジトリ管理ツール**です。散乱しがちなローカルリポジトリを`~/.ghq/[hostname]/[user|org]/[repo]`のディレクトリ構成で整理してくれます。
上記の例なら`~/.ghq/github.com/jsk-report-template/ci-thesis`となります。

### ビルドがdvipdfmxの段階で失敗する
それでは準備も整ったのでLaTeX Workshop経由でビルドしてみます。

<img width="700" alt="error.png" src="https://qiita-image-store.s3.amazonaws.com/0/150557/b7b98310-f31c-f2b2-1806-249ec2367aa9.png">

エラーで止まったのでログを見てみると、ある異変に気づきます。

```bash
Output written on main.dvi (19 pages, 30576 bytes).
SyncTeX written on main.synctex.gz.
Transcript written on main.log.
github.dvi -> github.pdf

dvipdfmx:fatal: Could not open specified DVI (or XDV) file: github.dvi
```

**いやgithub.pdfどっから出てきたんだよ**。

当然ディレクトリに`github.tex`なんてあるわけないですし、そもそも`main.dvi`の作成までは成功しています。

### エラー原因の検証
この段階では原因の見当もついていませんが、とりあえずターミナルを開いて**コマンドでのビルド**を試します。

```bash
$ ptex2pdf -l -ot -kanji=utf8 main.tex
# ...
Output written on main.dvi (21 pages, 33736 bytes).
Transcript written on main.log.
main.dvi -> main.pdf
[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21]
117951 bytes written
main.pdf generated by dvipdfmx.
```

すんなり通りました。つまり手元の環境やテンプレート自体の問題ではなさそうです。
**VS Code & LaTeX Workshopを使う時だけうまくいかない**という謎の状況となってしまいました。

その後色々試したのち、ghq管理でないディレクトリでのコンパイルをやってみたところ、

<img width="700" alt="changed-dir.png" src="https://qiita-image-store.s3.amazonaws.com/0/150557/5cadc3d1-ef85-395c-d270-970dc31d601b.png">

できました！　つまり**ghqのディレクトリでLaTeX Workshopを使う**ときだけこの問題が起こると言えます。

## 解決

### LaTeX Workshopがコマンドにフルパスを渡していた
あらためてLaTeX Workshopのログを見てみます。

```bash
This is ptex2pdf[.lua] version 20180514.0.
Processing /Users/[ユーザー名]/.ghq/github.com/jsk-report-template/ci-thesis/main
This is e-pTeX, Version 3.14159265-p3.8.1-180226-2.6 (utf8.euc) (TeX Live 2018) (preloaded format=platex)
 restricted \write18 enabled.
```

`ptex2pdf`に**フルパスが渡されていました**。
ghq管理のディレクトリパスには、はじめに触れたように`github.com`の文字列が入っています。これが謎の`github.dvi`の正体とみて間違いないでしょう。

### ptex2pdfのコードから問題箇所を特定する
`ptex2pdf`は、指定したTeXコマンドと`dvipdfmx`を連続実行するLuaスクリプトであり、テキストエディタで開けば中身を見ることができます。

私はLuaを読んだことすらないため、雰囲気で`dvipdfmx`が登場する部分を見てみると、

```lua:ptex2pdf.lua(ll.426-431)
print("Processing ".. filename)
if (os.execute(tex .. " " .. texopts .. prefilename .. " \"" .. filename .. "\"") == 0) and
   (dvipdf == "" or  (os.execute(dvipdf .. " " .. dvipdfopts .. " \"" .. bname .. ".dvi" .. "\"") == 0)) then
  if dvipdf ~= "" then
    print(bname .. ".pdf generated by " .. dvipdf .. ".")
  end
```

どうやら`bname`なる変数が渡されています。これが`"main"`でなく`"github"`になってしまう原因がもっと前にあるはずです。

```lua:ptex2pdf.lua(ll.403-405)
    -- if it has already an extension, we need to drop it to get the dvi name
    bname = string.gsub(filename, "^(.*)%.[^.]+$", "%1")
  end
```

なにやら正規表現で置換しています。コメントによると、「dviのファイル名を得るために拡張子を消す」そうです。

`filename`から**最後の`.`以下を削った**ため、`~/.ghq/github.com/jsk-report-template/ci-thesis/main`が`~/.ghq/github`にされたというのが、今回のバグの元凶でした。

### 正規表現の修正
拡張子を削るのが目的ならば、パスの途中で`.`を含むディレクトリがあっても無視しなくてはなりません。
後に`/`が出てくる`.`を除外すれば良さそうです。

正規表現の中に謎の`%`が出てきて一瞬戸惑いましたが、[Luaではエスケープに`\`でなく`%`を使う](http://aoikujira.com/wiki/lua/index.php?%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE)と知って納得しました。
`\`に置き換えれば、[regex101](https://regex101.com/)などの正規表現テスターが使えます。

<img width="400" alt="regex-ng.png" src="https://qiita-image-store.s3.amazonaws.com/0/150557/0e04c757-d513-d26a-e1b3-e8163ba3259a.png">

3つ目のパターンを除外するため、右の`[]`内にスラッシュを追加しましょう。

<img width="400" alt="regex-ok.png" src="https://qiita-image-store.s3.amazonaws.com/0/150557/63bf871e-9f34-e13a-487b-2de4ad921cc3.png">

良さそうなので`ptex2pdf.lua`を修正します。Luaでは`/`をエスケープする必要がないらしく、以下のように1文字の追加でOKです。

```diff:ptex2pdf.lua(diff)
@@ -399,7 +399,7 @@
     end
   else
     -- if it has already an extension, we need to drop it to get the dvi name
-    bname = string.gsub(filename, "^(.*)%.[^.]+$", "%1")
+    bname = string.gsub(filename, "^(.*)%.[^./]+$", "%1")
   end
   -- filename may contain "/", but the intermediate output is written
   -- in current directory, so we need to drop it
```

## バグ報告・Pull Request
手元では無事ビルドが通るようになりました。

検証中に何度も検索したものの、この問題は報告されていません。
困っている人が少ないとはいえ、想定外の挙動をしているのは確かなので[ptex2pdfのGitHubリポジトリ](https://github.com/texjporg/ptex2pdf)にissueを出しました。

- [File path which contains .(dot) causes error of dvipdfmx · Issue #12 · texjporg/ptex2pdf](https://github.com/texjporg/ptex2pdf/issues/12)

この時点で上記の解決手段にたどり着いていたので[プルリクも出した](https://github.com/texjporg/ptex2pdf/pull/13)ところ、開発者のNorbert Preiningさんが**その日のうちにマージ**してくださいました。

## おわりに
今回のような状況でビルドに困っているという方がもしいれば、`ptex2pdf`を`20181212.0`にアップデートしてみてください。

先程報告が上がっていないと書きましたが、実はすべてが終わったあと @__pandaman64__さんのこんなツイートを見つけました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あとでptex2pdfに報告</p>&mdash; 世界一ソフトクリームを食べるのが下手 (@__pandaman64__) <a href="https://twitter.com/__pandaman64__/status/993160759218552834?ref_src=twsrc%5Etfw">2018年5月6日</a></blockquote>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">しようと思って忘れてました</p>&mdash; 世界一ソフトクリームを食べるのが下手 (@__pandaman64__) <a href="https://twitter.com/__pandaman64__/status/1067995423325925381?ref_src=twsrc%5Etfw">2018年11月29日</a></blockquote>

困っていたのは私だけではなかったということで、少し安心ですね（？）

最後になりますが、TeXの日本コミュニティは**[github.com/texjporg](https://github.com/texjporg)で各種リポジトリを公開**しています。
私のような部外者であっても、Pull Requestすれば見ていただけると思うので、気づいた点があれば積極的に報告していくと良いと思いました。

---

明日はmattskalaさんの「[TeXLiveからMediaWikiのために最小のインストールは何ですか？](http://ansuz.sooke.bc.ca/entry/352)」です。