Hatena::ブログ(Diary)

アセトアミノフェンの気ままな日常

2016-06-29

新しい pLaTeX がアレすぎて嘆息してみる(続き)

前回の続き)

ようやく方針を議論する流れへ?

さすがにバグレポートが多すぎるので、forum:1954 から脱線しつつ

一方で,どこまでコミュニティ版 pLaTeX での改変を許容するのかも議論しどころです.アクセントの変更時のように,改変は即エンバグにつながりますので.LuaTeX-ja は,LuaTeX 本体もベータなんだからこれもベータなんだ,と言っておけばよいですが,pLaTeX は利用者が多いので,バグの影響も大きいです.stable / unstable の区分があればよいのですが…….分けても unstable を試す人が少なくてあんまり意味ないのかな.

という話題になった。これがどこに収束するか、というのはまだわからない。

以下、いま自分が思っていること:

理想は「バグを入れないこと」

本来、バグを入れないように努力するのが理想である。これは間違いなく正論である。しかし、ここに一つ大きな課題が生じる:

ありうるすべての場合を、テストケースとして列挙することは可能か?

バグを入れないためには、該当部分が絡むあらゆる原稿 tex ファイルを想定してコードを書く能力が必要である。そして、それが正しいかどうかテストしなければならない。しかし、少なくとも僕には必要十分なテストケースを作るのは難しすぎる。とりあえず動いていそうなコードくらいなら書けても、すぐにボロが出てしまう。「バグがないことの証明」は悪魔の証明とも匹敵する難易度だろうと思う。

絶対にコケないナントカ」も、落ちるときは落ちるのだ。

でも無理なので現実的な打開策を

そうなると、大勢で片っ端からテストしてみてボロが出ないか見つける作戦が「現実的」だろう。この作戦では、参加者数がカギとなる。そのために

  • いかにテストの手間を取らせないか
  • いかにテストを誰でも簡単に試せるものにするか

これらの課題をいかに解決するか考えることこそが、“もっとバグを出さないようにする努力” だと僕は思う。どうせ悪魔の証明は自分にはできないのだから。そして、考えることと並んで、告知することも大事だと思う。

そして、僕が出したのは「実験用コードをパッケージ (sty) に抜き出して TeX Live と一緒に配布する案」である*1。もちろん、sty なので本来の pLaTeX のような「dtx → ltx にストリップしてフォーマットを作る」の “まんま同じもの” ではないし、後に sty の実験コードを本体に採用することになったときにインポートする作業でバグが生じないとも限らない(これも悪魔の証明*2)。それでも、「限られた人にしかテストしてもらえない*3がゆえにバグが見つからない」よりは、よほど生産的なバグ発見に結びつくと思う。これがベストかどうか自信はないが、ともかくもいまは既に報告された深刻なバグを一刻も早く解消することが先決だと信じて、残り数日間は行動しようと考えている*4

おまけ

残念というべきか、時代の流れというべきか

TeX 言語に詳しい人ほど pLaTeX から離れている

ように僕にはみえる。いま、どんどんエキスパートユーザほど LuaTeX のような “新しいもの” に興味の対象が移っていて、pLaTeX を使う機会が減っているようである*5。これを加味すると、ますます「テストしてもいいよ!」という人のサポートに回るほうが有利だと思うのだが…いかがだろう。

最後に:「バグ入れないこと」より「バグ入れてしまった場合に早く対処すること」のほうが大事だし、努力による実現可能性も高い、と僕は思う。そして「早く対処する」ために、「なんでもいいから明確な案を出すこと」(ベストでなくても構わない)が必要な場面は多い、と思う。そういいながら、こういう場面に自分は慣れていないのだけど。

例によって誤解のないように:ブログで自己主張しているだけ、と思われるかもしれないが、確かにその一面は認める。でも、ここは僕にとって、あくまで個人の試行錯誤を書くための場所・あとから過去の自分を確認するための場所である(読んでもらうための場所=メインブログは別にある!)ことを、読者の方々にはどうかご承知おきいただきたい。

*1:その実装に先日解説したとおりの変な技法を使った。

*2:とはいえ、ここでバグが生じる場合は「フォーマットより後にコードパッチを読めば OK なのに、フォーマットの途中にコードがあると NG」なのだから、最悪「なるべく後ろの方にコードを入れ直す(≒ plpatch.ltx を復活させる)」で OK にできて、大した問題は起きないに違いない。

*3:“まんま同じもの” = TeX Live に入れて共存させることは不可能、すなわち GitHub に取りにきてもらわなければならない。しかもフォーマット生成も要求してしまうため、あまり親切とは言えないと僕は思う。

*4:次のリリースが出れば、しばらくは stable だろうと思う。実験用コードが安全そうだかどうかは、数ヶ月から半年は様子見となると個人的には見込んでいる。それまでに、もっとコミュニティ内で合意形成できていればいいね…

*5:僕の場合はまたそれとは別で、pLaTeX にコミットしているとはいえド素人である。そして、最近は LaTeX が本業に一切必要にならない生活を送っている。月に 1,2 回何かしら LaTeX で書く程度のことはあるが、それも別に LaTeX 必須というわけでもない。というわけで、LaTeX が本当に必要なのはブログのネタくらいである。

2016-06-28

新しい pLaTeX がアレすぎて嘆息してみる

コミュニティ版 pLaTeX にトラブルが続いている。

いまのところ「アクセント文字」パッチに対するものだけなのだが、Forum に既に 3 回もレポートされている。

上記のトラブル続きの「アクセント文字パッチ」が入った理由は、過去記事に出した「縦組で Å の合成がおかしくなる」という現象に対処するためであった。こんなバグレポートしなければ新しく余計なバグも入らなかったろうに…というのは置いておいて*1、では今後どうやって pLaTeX を維持開発したらよいのだろうか、ということを少しずつ真面目に考えてみる。

以下はいまの私の反省を踏まえて、敢えてオープンにした。オープンにすべきではないという批判もあるかもしれないし、言い訳をしているようで汚いという批判を受けるかもしれないが、反面教師にでもしていただければと思う。

遡って… コミュニティ版 pLaTeX の初期

諸事情あって*2、コミュニティ版 pLaTeX の誕生に関する雑多な決定は、クローズドな場で議論してきた。そういうこともあって、GitHub の pLaTeX リポジトリは実際には公開状態にあったにもかかわらず、数ヶ月にわたりほぼ texjporg の中の人(それもごく一部の参加者のみ)で commit されてきた。したがって、肝心の「どういう場合に変更するか」という方針決定もままならないまま、「ここが変かもしれない」というだけでとりあえず改変を入れてしまった。

全く決まっていなかった、というのが答え。

時は流れて… pretest の始まり

たいしてテストできないまま TeX Live 2016 pretest が迫り、そこにとりあえず形になった「コミュニティ版 pLaTeX」を入れることになった。もちろん、pretest に「コミュニティ版」を入れることは目標だったと思う。pretest 期間は 2 ヶ月近くもあるので、余裕をもってバグ出しできると踏んでいたからだ。ところが、実際には pretest の最終更新の直前にまでインストールがずれ込んでしまい、十分なテスト時間を取れなくなってしまった。これは引き継ぎの難しさや、日本語用マクロの特殊性*3を考慮すれば十分想定できたことだといまは思う。

不完全燃焼な pretest の終わり

先述のとおり pretest が実質 2 週間たらずで終わってしまった(この pretest 期間に修正は一切なし)ので、コミュニティ版 pLaTeX はそのまま TeX Live 2016 正式リリースに自動的に入った。これが最終目的だったはずなのだが、個人的にはむしろ「入ってしまった」感のほうが強かった。どこがバグるかも知れないコワイ状態である。

誰もなにも言わないということは、誰も疑問を感じていないのだろう、ということで安心するしかない。コワイ。

そして、TeX Live 2016 リリース

さすがにコワイので、フォーラムに告知することにした。

とりあえず「新しくなっていますよ」「こういう意図でここを変えましたよ」だけは書いたつもりだ。バグが入っていないことを祈っているので、「新しいバグがあるかも」とは当然言わない。

怒涛のバグレポート

冒頭に書いたとおり、途端にバグレポートが相次いでしまった。幸い、コミュニティ版には地道に実装しておいた「platexrelease パッケージ」が入っているので、とりあえず quick fix として昔の pLaTeX をエミュレートしていただくことができた。もしこれが無かったら、と考えると、相当ゾッとする話である。

続く

*1:責任は当然感じているわけですが、過ぎたことを悔やむより先のことを考えさせてください。

*2アスキーからの引き継ぎ・CTAN へのアップロード・TeX Live への自動インストールなど、直接「pLaTeX の挙動変更」に関わること以外のデリケートな議論を含んだため、そもそも実現可能かどうかすら不透明だったと思う。

*3:通常 TeX Live のすべてのパッケージは UTF-8 で収録されるが、日本語関係のパッケージに限り、pTeX の歴史的経緯により最も扱いやすい ISO-2022-JP (JIS) エンコードで収録されるように特別扱いしてある。

2016-06-25

単独でタイプセットできるパッケージファイル

パッケージとそのドキュメントを一緒に開発したいとき、最もよく使われるのが docstrip の仕組みである。最近主流の docstrip の使いかたは

dtx ファイル(コードとドキュメント本体)+ ins ファイル(dtx から sty をストリップするためのバッチファイル)のセット

だろう。あまり書き方を説明したオンライン日本語文献は見当たらないが、ut さんちの「dtx ファイル一般の話とサンプル」の節に

例として、いんちきな dtx ファイルを用意してみました (foobar.dtx.txt):

として簡単な dtx サンプルまで付いている。実は TeX Live には sty2dtx という Perl で書かれたスクリプトがあって、これは入力した sty ファイルから適切なガードを付けた dtx を作ってくれる便利なものである*1

でも:パッケージファイルひとつにしてみたい

これはこれで普及している方法なのだけど、いちいち dtx から sty をストリップするのは面倒だという意見もあるだろう。一方、コードの間近に直接文書を書き込める dtx は、後からコードを読んで開発を引き継ぐ人(そして原開発者自身*2)にとって便利なものである。もちろん普通の sty でも % を使ってコメントを付ければよいわけだが、そのまま latex 等でタイプセットして PDF ドキュメントになってくれたほうが、別途マニュアルを作成しなくて済むというメリットがあるだろう*3

この溝を埋めるには

  • sty ファイルを直に配布
    • 当然これは \usepackage できる
    • 時に \documentclass より前で \RequirePackage される
  • sty ファイル単独でもコンパイルが通る
    • dtx 同様のコード解説を含められる

がよいのではないだろうか。…と思ったのだが、この試みは案外なされていない。というわけで、ここに一案を出したのがこれ (Issue 9) 。

これは pLaTeX 向けコードや解説が入っているので、もう少し短くしたもの:

実用に供するパッケージではなく、あくまで実装の例示である。

ちょっとだけ解説

コード中に解説は書いたが、トリッキーなのでもう少し詳しく。

いちばんトリッキーなのは

\ifx\undefined\@undefined\relax
  % (パッケージの宣言)
\else
  % (ドキュメント用「ドライバ」コード)
\fi

の部分である(以下「トリックコード」と呼ぶ)。これは〈@〉のカテゴリーコードが「パッケージとして読まれた場合」と「TeX ファイルとして読まれた場合」で異なることを利用している。

case 1: パッケージとして読まれた場合
\usepackage{tcstyalone}

あるいは

\RequirePackage{tcstyalone}

の場合、上記「トリックコード」実行時には \makeatletter が有効になっている。すなわち \ifx が比較するトークンは \undefined\@undefined である。どちらのコントロール・シーケンスも「未定義」なので、判定は真となり(パッケージの宣言)が実行される。

case 2: TeX ファイルとして読まれた場合
$ pdflatex tcstyalone.sty

あるいは

\input{tcstyalone.sty}

のように読まれた場合、上記「トリックコード」は \makeatletter 無効である。この場合、\ifx が比較するトークンは \undefined\@ である。\@ はコントロール・シンボルで、LaTeX では

\spacefactor\@m{}

と定義されている*4ため「未定義」とは異なる。すなわち判定は偽となり(ドキュメント用「ドライバ」コード)が実行される。判定部の後にくっついている undefined\relax なる部分は、真の場合のコードの一部とみなされて、必ずすっ飛ばされることに注意。

さらなる帳尻合わせ

ここで sty を単独でタイプセットしたい場合、「ドライバ」コード部には

\documentclass{...}
\begin{document}
...
\end{document}

を含める必要があるのだが、先の「トリックコード」では \fi\end{document} より後に来てしまう。つまり、case 1 では既に \if...\fi が釣り合っている一方で、このままでは「case 2 の場合だけ一回分 \fi が足りない」という問題が発生する:

(\end occurred when \ifx on line 15 was incomplete)

これを解消するため、ここでは docstrip の「\DocInput では行頭の % が無視される」という仕様を利用してみた。case 2 だけ余分の \fi% 付きで発行するのである。そうして書いたのが、例の gist のコードである。

先行研究の例

以上の実装コードを書いたあとで、別解らしきものを見つけた。

*1:「アスキー版 pLaTeX」に付属していた tascmac.sty は直書きされていたのだが、texjporg の「コミュニティ版 pLaTeX」の tascmac.sty は文書付きの ascmac.dtx からストリップされるようにしてある。この dtx は、実は僕が tascmac.sty を sty2dtx にかけたあと、文書を書き下ろしたものである。

*2:一回書いたコードの意図なんか 3 日もすればすぐに忘れてしまうので、未来の自分は今の自分から見ればまったくの他人である

*3:PDF ドキュメントなしでは texdoc で読みづらい!

*4:2014 年までは {} が無かったが、ここではどうでもいい。

2016-06-24

color パッケージが縦組でアレになってしまった話

先日の「color パッケージの dvips オプションがエラーになる話」の調査継続中。

「(2) pLaTeX で対処できるかもしれない案」の続き

先日の方法だと、\AtBeginDvi{} を発行するとまたエラーが起きてしまうことがわかった。そこで、unbox せずに box する方法を追求するなら

\makeatletter
\def \@begindvi{%
  \box \@begindvibox
  \global\let \@begindvi \@empty
}
\def \AtBeginDvi #1{%
  \global \setbox \@begindvibox
  \vbox{\box \@begindvibox #1}%
}
\makeatother
\documentclass[dvips]{tarticle}
\usepackage{color}
\AtBeginDvi{}
\begin{document}

あいうえお

\end{document}

とする必要があるようだ。出力も正常だがやっぱり副作用が心配。

「(3) pLaTeX でエラーだけ消し去る案」の続き

先日の方法だとレイアウトは駄目なままだったが、以下のようにする:

\makeatletter
\def \@begindvi{%
  \iftbox\@begindvibox\tate\else\yoko\fi
  \unvbox \@begindvibox
  \global\let \@begindvi \@empty
}
\def \AtBeginDvi #1{%
  \global \setbox \@begindvibox
  \vbox{\iftbox\@begindvibox\tate\else\yoko\fi
  \unvbox \@begindvibox #1}%
}
\makeatother
\documentclass[dvips]{tarticle}
\usepackage{color}
\AtBeginDvi{}
\begin{document}

あいうえお

\end{document}

これはなんと出力が正常!(ちょっと驚き)

上記 2 例とも A4 縦以外のレイアウトを試していないが、実際にクラスオプションに [a5paper] などを指定してみると「dvips.def が意図した setpagesize が正しくはたらいている」ことも確認できた。 → ZR さんから forum でコメントをいただいたとおり

\def\AtBeginDvi#1{%
  \global\setbox\@begindvibox
    \vbox{\yoko\unvbox\@begindvibox #1}}

のほうが筋がよさそうです(\@begindvi は再定義なし)。ありがとうございます。

事の顛末:そもそも color パッケージは関係なかった話

ちなみに、LaTeX team の David さんから

\documentclass{tarticle}
\AtBeginDocument{\AtBeginDvi{}}
\begin{document}

a

\end{document}

がエラーを出す MWE であることも教えていただいた。2 種類の \AtBeginナントカ がそろって初めてエラーになるので、いままで pLaTeX で気づかなかったのだろう。

2016-06-18

pLaTeX と共存できていない LaTeX パッケージの備忘録(続・続編)

なんか多忙のためサブブログを書かない日が数週間続いてしまった。この期間にメインブログの記事は 3 回も更新したが…

気を取り直して、初回第2回に続き、3回目。

color パッケージ

縦組で使うと、ドライバ dvipdfmx 指定だと正常終了なのに dvips 指定だとエラー。

\documentclass[dvips]{tarticle}
\usepackage{color}
\begin{document}

{\color{red}あいうえお}

\end{document}
./test.tex:7: Incompatible direction list can't be unboxed.
\@begindvi ->\unvbox \@begindvibox 
                                   \global \let \@begindvi \@empty 
l.7 \end{document}
                  
? 

原因はまだ調べていない。別のところで報告されているのすら見つからない…

追記 (2016-06-23):TeX Live 2015 最終版では通る模様。2016 最新版はエラー。

  • 2015 は「dvips.def 2015/12/30 v3.0k」
  • 2016 は「dvips.def 2016/06/02 v3.0l」あるいは「dvips.def 2016/06/17 v3.0m」

なので、この間の変更すなわち setpagesize が関係していると推測*1
→ かなり厄介そうなので forum:1956 へ。とりあえず回避するには:

(1) ユーザ側でなんとかする案:nosetpagesize オプション
\documentclass[dvips]{tarticle}
\usepackage[nosetpagesize]{color}
\begin{document}

{\color{red}あいうえお}

\end{document}

デフォルトが setpagesize なので、それを override する。しかし、この方法はよほどユーザが注意しないと忘れがちだと思う*2

(2) pLaTeX で対処できるかもしれない案
\makeatletter
\def\@begindvi{%
  \box\@begindvibox
  \global\let\@begindvi\@empty
}
\makeatother
\documentclass[dvips]{tarticle}
\usepackage{color}
\begin{document}

{\color{red}あいうえお}

\end{document}

これはエラーなく終了して出力も正常。ただし unbox しないことで良からぬ副作用がないかどうかは未検討。もし副作用がないならこれは優れた方法かも。

(3) pLaTeX でエラーだけ消し去る案(レイアウトは駄目なまま)
\makeatletter
\def\@begindvi{%
  \iftbox\@begindvibox\tate\else\yoko\fi
  \unvbox\@begindvibox
  \global\let\@begindvi\@empty
}
\makeatother
\documentclass[dvips]{tarticle}
\usepackage{color}
\begin{document}

{\color{red}あいうえお}

\end{document}

先述の心配事である unbox は保持できるが、dvips.def に対して pLaTeX 縦組用に ad hoc な変更を加えてもらうことが前提として必要になってしまう。
もう少し調べてみた (2016-06-24) 。

ちょっと前の biblatex パッケージ(?)

これは forum:1508 より。最小ソースは置いてあるんだが…あれ、今やってみるとエラー出なかった… biblatex が変わったのかな。

CJK パッケージ ← 要注意!

欧文 LaTeX (pdflatex) などで日中韓文書を作りたい場合に便利な CJK パッケージだが、結論を言うと僕自身は CJK.sty は pLaTeX とは共存しないと思う。最も引っかかりそうなのが、ruby.sty という「ルビをふるパッケージ」である。これが CJK パッケージ群のものだとは名前からは気づきにくい。

\documentclass[a4j]{tarticle}
\usepackage{ruby} % including CJK.sty here!
\begin{document}
振り仮名のテスト。\ruby{}{}\ruby{}{}\ruby{}{}のテスト。
\end{document}

ルビが小書きにならないのは、pLaTeX が再定義している \selectfont が CJK.sty によって上書きされてしまうから。同じ原因で、OTF パッケージが文字化けするという問題も知られている (forum:1748) 。pLaTeX でルビをつけたければ、美しい pxrubrica パッケージを使うか、簡単なマクロなら okumacro を参考に \ruby を作ってしまうのが上策だろう。

先日の記事では everysel / tracefnt パッケージによる \selectfont の再定義をうまく回避する方法を考察したが、これは everysel など(や、それに依存したパッケージたち)に一定の有用性を見いだせたからである。しかし、CJK の場合はなにが有用なのか分からない… というわけで、forum:1954 へ出した。

*1:geometry パッケージが縦組で使えないのも同じエラーなので、たぶん現象としては近いことが起きているのかも。

*2:第三者のパッケージが color を呼ぶ事例は極めて多いが、ページを shipout するところで初めてエラーが出るため、原因に気づきづらいはずだ。