マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

和文な制御記号を \DeclareRobustCommand するとアレ

和文の記号の名前を持つ制御記号(control symbol)、例えば \☃ に対して保護付のマクロを \DeclareRobustCommand で定義したとする。

% upLaTeX文書, UTF-8
\documentclass[uplatex,dvipdfmx,a4paper]{jsarticle}
\usepackage{scsnowman}
% ☃のマフラーは赤色
\DeclareRobustCommand*{\}{\scsnowman[%
  hat,arms,buttons,snow,muffler=red,scale=1.3]}
\begin{document}
% 目次
\tableofcontents

% 本文
\section{{\TeX}とは何か}
アレ。
\section{\☃とは何か}
非アレ。
\end{document}

よく見ると、目次の☃の部分の出力がおかしい。☃の後に余分な欧文空白が入ってしまっている。それもそのはず、補助(.aux)ファイルを見ると、明らかに \☃ の後に空白文字が入っている。

\relax 
\@writefile{toc}{\contentsline {section}{\numberline {1}{\TeX  }とは何か}{1}}
\@writefile{toc}{\contentsline {section}{\numberline {2}\☃  とは何か}{1}}

TeX on LaTeX な人には周知の通り、\DeclareRobustComamnd\foo を定義した場合は、内部で“foo␣”という名前の制御綴が使われる。\foo が動く引数で用いられた場合、補助ファイルにはこの内部制御綴が \foo␣␣ という形で書き出されるので、再び字句解析されたときには \foo に戻る、という仕組である。この仕組に従って、保護付の \☃ の定義では、補助ファイルに \☃␣␣ が書き出されるわけだが、 は英字扱いではないので、これは空白トークンが 1 つあると見なされてしまうのである。

というと、欧文の制御記号でも全く同じことになりそうな気がするが、そうではない。例えば、先の例で \☃ の変わりに \8 を使った場合は、補助ファイルは次のようになる。余計な空白文字は書き出されず、従って、組版結果にも余分な空きは現れない。

\relax 
\@writefile{toc}{\contentsline {section}{\numberline {1}{\TeX  }とは何か}{1}}
\@writefile{toc}{\contentsline {section}{\numberline {2}\8とは何か}{1}}

何故欧文の方は正常なのかというと、この場合は LaTeX が特別に対処しているからである。元の制御綴の意味を調べてみる。

\DeclareRobustCommand*{\}{NICE!}
\typeout{(\string\☃=\meaning\☃)}
\DeclareRobustCommand*{\8}{NICE!}
\typeout{(\string\8=\meaning\8)}
\stop

すると次のような結果になる。明らかに、欧文の方は普段(制御語の場合)と違う少し複雑な定義になっている。

(\☃=macro:->\protect \☃  )
(\8=macro:->\x@protect \8\protect \8  )

これに対して、和文の制御記号の場合はこの特別扱いから漏れている(制御語と同じ扱い)ことがわかる。LaTeX カーネル和文の制御記号を制御記号と扱い損ねているのであろう。