Acetaminophen’s diary

化学に関すること,TeXに関すること,ゆきだるまに関すること。

LaTeX パッケージのオプションには空白を含めないほうがよい話

この記事は、サブブログの 2016-09-17 投稿記事を移転してきたものです。

LaTeX team からいただいた情報によると、「パッケージ読込時に “,” 区切り周囲にスペースを入れると Option clash する例」が最近発覚したらしい。以下の例示ソースで再現可能*1

\documentclass{article}
\usepackage[a, b, c]{foo}
\usepackage[a ]{foo}
\stop
! LaTeX Error: Option clash for package foo.

同じパッケージが 2 回以上使われそうになった場合、本来ならば「2回目のオプションたちが1回目のオプションたちの部分集合であればスルー、もし増えていたら Option clash エラー」となるべきである。ところが、上記ソースでは空白がおかしな作用をして、部分集合になっているのに clash している。これも次回リリース(2017-01-01)で直すつもりらしい。

\def\@if@pti@ns#1#2{%
  \let\reserved@a\@firstoftwo
  \edef\reserved@b{\zap@space#2 \@empty}%       <- new
 \@for\reserved@b:=\reserved@b\do{%             <- changed
   \ifx\reserved@b\@empty
   \else
     \expandafter\in@\expandafter{\expandafter,\reserved@b,}{,#1,}%
     \ifin@
     \else
       \let\reserved@a\@secondoftwo
     \fi
   \fi
 }%
 \reserved@a}

ついついやってしまいがちな「空白」。特にオプションを多数指定する場合、コード上は改行して書くことも多いだろう:

\usepackage[dvipdfmx,%
 bookmarks=true,%
 bookmarksnumbered=true,%
 colorlinks=true,%
 setpagesize=false,%
 pdftitle={LaTeX研修課程},%
 pdfauthor={ななしのごんべぇ},%
 pdfsubject={hyperref入門・演習},%
 pdfkeywords={TeX; dvipdfmx; hyperref; color;}]{hyperref}

最後の % を書く習慣は付けておくと無難、ということであろう。

 

LaTeX パッケージ作者もオプションには空白を含めないほうがよい話

こんなタレコミも。

\begin{filecontents}{test3.sty}
\DeclareOption{foo}{\typeout{*** FOO OPTION ***}}
\DeclareOption{bar}{\typeout{*** BAR OPTION ***}}
\DeclareOption{baz}{\typeout{*** BAZ OPTION ***}}
\DeclareOption{qux}{\typeout{*** QUX OPTION ***}}
\ExecuteOptions{foo, bar}
\ProcessOptions\relax
\end{filecontents}

\documentclass{article}
\usepackage[baz, qux]{test3}
\begin{document}
a
\end{document}

パッケージが既定で foo と bar を実行し(パッケージ内で作者が \ExecuteOptions で指定)、さらにユーザが baz と qux を指定する(\usepackage のオプション)ので、全部で四つのメッセージが出そうである。ところが

*** FOO OPTION ***
*** BAZ OPTION ***
*** QUX OPTION ***

確かに、本来は出るはずの BAR が表示されなかった!「\usepackage はコンマの周りに空白があってもよいのに、\ExecuteOptions はダメ」というトラップがあったようだ。この件を報告したところ、LaTeX team の方も「20年経って今頃なんでこんなに…?」と戸惑っていた…。

 

追記:対処されたようです (2016-10-04)

LaTeX2e public svn をみると、2016/10/02 付けで「\ExecuteOptions に空白があるとオプションを無視する話」と「\@if@pti@ns で空白があると Option clash する話」について対処された (r1227) 。いちばん難しい「\ProcessOptions の干渉」はまだで、バグ懸念で慎重になっているようだ(2018-12-01 現在も未対応の模様)。

*1:これは一般化した記述であるが、たとえば foo → graphicx、a → dvipdfmx、b → dvips、c → dvipsone 等と置き換えてみるとよいだろう。