JavaScript
LaTeX
Pandoc
textlint

LaTeXで書いた学位論文もtextlintでチェックしよう(&工学系論文向けのtextlint presetを作っている話)

この記事はU-Tokyo mech (東京大学機械系) Advent Calendar 2018の24日目の記事です。


はじめに

学位論文執筆中の方はお疲れ様です。そうでない方もお疲れ様です。

皆さん、当然卒論は$\rm{\LaTeX}$で書いてますよね?

え? Word? 暴れ回るティラノサウルスを論文に含める必要がある方は大変ですね。

自分は幸運にも暴れ回るティラノサウルスを論文に掲載する必要がないため、早速$\rm{\LaTeX}$で書こうと準備をしています。

その一環として、記事の文章校正でいつもお世話になっているtextlintを使おうと調べていたところ、textlintの創造神であるazuさんのこんなツイートが。

ぼく「2016年のツイートか」

ぼく「$\rm{\LaTeX}$は使う人多いし流石にここ2年の間に何かできてるやろ(ググリー」

この後悪戦苦闘することになったので、書き残しておきます。

先に書いておくと、2018年現在$\rm{\LaTeX}$をtextlintでチェックする完全な手法はありません。今後状況が改善するといいですね。


(2019/1/23 追記)

@xtaniguchimasaya さんが$\rm{\LaTeX}$に完全対応したプラグインtextlint-plugin-latex2eを制作してくださいました。

こちらでほとんどの$\rm{\LaTeX}$ファイルに対応可能ですので、ぜひお試しください。


環境


Markdownで書かないの?

本題へ入る前に、そもそも$\rm{\LaTeX}$で卒論を書くモチベーションについて触れておきます。

あとで紹介するPandocを使えば、Markdownで書いた原稿を$\rm{\LaTeX}$に自動変換でき、textlintでのチェックももちろん可能です。

このQiitaを「markdown 論文」などで検索するとそういった記事は沢山出ています。

この手法を取らない理由は以下の通りです。



  • 結局$\rm{\LaTeX}$に触れる必要がある


    • 講義のレポートなどと違って学位論文は体裁が重要です

    • 図の位置の調整など細かい部分で、結局$\rm{\LaTeX}$側を加工せざるを得ないでしょう




  • Visual Studio Codeの$\rm{\LaTeX}$拡張機能が快適



    • LaTeX Workshopを導入すれば、保存時に毎回ビルドが走り・横にPDFがプレビューされ・コマンドは自動補完されるという至れり尽くせりな感じになります

    • $\rm{\LaTeX}$の面倒さはかなり軽減されます




  • $\rm{\LaTeX}$も経験しておきたい


    • 使えた方がかっこよくないですか?




textlintでLaTeXファイルを扱う方法

textlintが標準で読んでくれるのはplain textとMarkdown形式だけですが、pluginにより様々な記法に対応しています。



以下古い情報です。前述の通りtextlint-plugin-latex2eが登場したため、折り畳み内のような手法は不要になりました :tada:

とても恐ろしい集団心理である——

誰も…textlint-plugin-latexを作っていないのである!


textlint-plugin-latex

嘘です。ありました。


使ってみる

READMEを読んでみると、このプラグインは.texファイルを以下のように変換します。


  • コメント(%hode)やコマンド(\hoge)を削る

  • コマンドの引数({fuga})を「fuga」に置換する

  • plain textとして抽象構文木(AST)に変換する

では使ってみましょう。LaTeX動作確認テスト・サンプルファイルを対象とします。

ルールは日本語用有名プリセット4種類を中心に導入しました。



textlintの設定(.textlintrc


.textlintrc

{

"plugins": ["latex"],
"rules": {
"ja-hiragana-fukushi": true,
"ja-hiragana-hojodoushi": true,
"no-mixed-zenkaku-and-hankaku-alphabet": true,
"preset-ja-spacing": true,
"preset-ja-technical-writing": true,
"preset-japanese": {
"no-doubled-joshi": {
"min_interval" : 1
},
"sentence-length" : {
max: 100
}
},
"preset-jtf-style": true
}
}



出力(先頭のみ)

$ npx textlint textlint.tex

/.../textlint.tex
2:29 error 文末が"。"で終わっていません。 preset-ja-technical-writing/ja-no-mixed-period
3:8 error {の対となる}が見つかりません。{} preset-jtf-style/4.3.6.中かっこ{ }
3:9 error 文末が"。"で終わっていません。 preset-ja-technical-writing/ja-no-mixed-period
4:4 error 文末が"。"で終わっていません。 preset-ja-technical-writing/ja-no-mixed-period
9:9 error {の対となる}が見つかりません。{} preset-jtf-style/4.3.6.中かっこ{ }



課題

大量のエラーが指摘されましたが、何かが変です。

1番目のエラーが出ている2行目は見出しの行で、「 動作確認テスト・サンプルファイル」と変換されているはずです。

エラーを出したtextlint-rule-ja-no-mixed-periodの説明には、「」で囲まれた文はセリフ扱いでエラーにしないと書いてあります。なぜ$\rm{\LaTeX}$だとうまく動かないのでしょう。

この他にも複数のルールがtextlint-plugin-latexを通すと正常に動きません

あちこちソースコードを見回って判明した原因は、これらのルールがcontext.getSource()というAPIで変換前の原文を参照していることでした。

context.getSource()で生の.texが渡された結果、誤検出が多発してしまったわけですね。

また、各ルールはtextlint-plugin-latexによる変換後のデータを元にcontext.getSource()での取得範囲を指定してしまいます。

従ってずれた範囲が原文として得られてしまい、検出漏れや誤検出、エラー箇所のずれが起きてしまいます。

こういった問題を解決するには、$\rm{\LaTeX}$を直接ASTに変換するしかありません。それを行うプラグインは、望まれながらも未だ世に出ていないというわけです……。


PandocでMarkdownに変換する

ないものは仕方がないので、別の策を考えます。Pandocは、Markdown・HTML・LaTeXをはじめ多数の文書形式を自動変換してくれるツールです。これでMarkdownに変換してからtextlintにかけている方は多いようです。


使ってみる

そのままpandoc textlint.tex -o textlint.mdしてもよいのですが、Pandoc標準のMarkdownは\refによる参照などを扱えるよう拡張されています。

これはtextlintで日本語を校正する分には邪魔なため、-t markdown_strictを指定して拡張なしのMarkdownに変換しましょう。

$ pandoc textlint.tex -t markdown_strict -o md/textlint.md

$ npx textlint md/textlint.md

/.../textlint.md
1:14 error Disallow to use "!" preset-ja-technical-writing/no-exclamation-question-mark
4:9 error Disallow to use "!" preset-ja-technical-writing/no-exclamation-question-mark
7:14 error Disallow to use "!" preset-ja-technical-writing/no-exclamation-question-mark
15:1 error Line 15 sentence length(223) exceeds the maximum sentence length of 100.
Over 123 characters preset-ja-technical-writing/sentence-length
18:22 error Disallow to use "?" preset-ja-technical-writing/no-exclamation-question-mark
19:20 ✓ error "することができます"は冗長な表現です。"することが"を省き簡潔な表現にすると文章が明瞭になります。参考: http://qiita.com/takahi-i/items/a93dc2ff42af6b93f6e0 preset-ja-technical-writing/ja-no-redundant-expression

✖ 6 problems (6 errors, 0 warnings)
✓ 1 fixable problem.
Try to run: $ textlint --fix [file]

良さそうです。「Line 15が長すぎる」というのは、元の.texファイルにあった数式を1つの文章と認識しているためで、これだけは誤検出です。


package.jsonにスクリプトを定義する

毎回手で操作をするのは大変なので、npm-scriptsとして定義しておきましょう。

npm-scriptsは、textlintが動いているNode.jsのパッケージ管理システムであるnpm経由でコマンドを実行できる仕組みです。


package.json(一部)

  "scripts": {

"test": "npm run pandoc && npm run textlint-md",
"pandoc": "rm -r md/* && find . -type f -name 'main.tex' -prune -o -type f -name '*.tex' -print | xargs -I% pandoc % -t markdown_strict -o md/%.md",
"textlint-md": " textlint -f pretty-error md/",
"textlint": "find . -type f -name '*.tex' -print | xargs textlint -f pretty-error"
},

全体のサンプルはGistに公開しています

npm testを実行すると、Pandocによる自動変換とtextlintによるチェックを連続実行します。

Pandocにかける際main.texを除いたのは、これが論文の他のファイル全てをincludeしているためです。Pandocはinclude先まで辿って変換し、main.tex.mdに論文の全内容が入ってしまいます。

各章の.texファイルがチェックされれば十分なので、main.tex以外を変換してmd/以下に出力します(gitを使っている場合はmd/を除外しておきましょう)。

あとはmd/全体をtextlintして完了です。


課題

この方法を使うには、まずはPandocを導入している必要があります。まあPandocは何かと便利なので、導入しておいて損ではありません。

Pandocの比較的簡単なインストール方法などを参考にインストールしてください。

第2に、Pandocが間に入る分時間がかかります。書き進めて分量が増えるにつれ待ち時間が増える可能性があります。

また、別の形式に変換しているので、元の.texファイルと行番号が合いませんtextlint --fixによる自動修正も上手くいきません。

エラーと見比べながら修正箇所を探しましょう。



工学系論文用のプリセットを作成する

上のいずれかの方法でtextlintによる校正はできるようになりました。

ただ、これで論文を書くにはそれに適したルールが必要です。

textlintのルールの多くは句読点として「」「」を使うことを求めています。しかし、日本機械学会指定テンプレートをはじめ工学系の多くの論文では」(カンマ)と「」(ピリオド)が指定されます。

textlintの句読点を扱うルールはtextlint-rule-preset-JTF-styleに複数あるものの、これらは「」「」しか認めてくれません。

また、textlint-rule-ja-no-mixed-periodではオプションで句点を変えられますが、読点はチェックしません。


textlint-rule-preset-ja-engineering-paper

以上の事情から、工学系論文専用のルールプリセットを作成し、npmに公開しました。

今後他のルールも盛り込みたいため、ルールでなくプリセットにしました(今は句読点に関するルール1つだけですが……)。


unify-kuten-and-touten

句読点を「」(全角ピリオド)と「」(全角カンマ)に統一します。また、オプションで指定する句読点を変えられるようになっています。

仕組みは単純で、句読点としてありうる記号のうち指定以外のものを検出してエラーを出すだけです。「句読点としてありうる記号」もオプションで追加できます。


今後追加したいルール

理系の論文では「数値+単位」の表記も指定されます。


  • 数値と単位の間には半角スペースを開ける(例:1.2 mm

  • SI単位で表記する(正:2 m/s・誤:2 m/sec

などです。単位の表記をチェックするルールもtextlintにはないため、今後追加するつもりです。


おわりに

軽い気持ちで学位論文にもtextlintを使おうとしたら、かなり大変でした。

package.json.textlintrcのサンプルはGistにあるので、textlintに慣れている方は試してみてください。