同じくjlreq.clsに次のようなマクロがある.
\jlreq@ifempty{<トークン列>}{<実行1>}{<実行2>}
これは<トークン列>が空ならば<実行1>を,そうでなければ<実行2>になる.e-TeX拡張が使える場合(jlreq.clsはこれを仮定している)は,このマクロの定義は
\long\def\jlreq@ifempty#1{%
\expandafter\ifx\expandafter\relax\detokenize{#1}\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
とするのが最善手だ.
としてもおもしろくないので,ここでは通常のTeXで考えてみる.よく見るのが
\def\jlreq@ifempty{%
\ifx\jlreq@uniqtoken#1\jlreq@uniqtoken
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
だけど(かなり長いことこれにしていた)これはやっぱり\jlreq@ifempty{\iftrue\fi}
で破綻する.というかした.
ともかく「最初のトークンだけ取り出す」マクロが作れればよいので,昨日のを少し応用して
\def\A#1#{\B#1\Y\Z}
\def\B#1#2\Z#3\Z{#1}
というマクロを考えて,\A#1\X{}\Z
という形のマクロを考えてみる,これを二回展開すると次のようになる.#1
における{***}
の前までをS
,その後をT
とすると,
T
が空でないならば,\A ST\X{}\Z
→\B S\Y\Z T\X{}\Z
→S\Y
の先頭T
が空ならば,\A S\X{}\Z
→\B S\X\Y\Z{}\Z
→S\X\Y
の先頭
#1
の先頭トークンが得られていることになる.ただし先頭が{
の場合は\Y
が,また#1
が空の場合は\X
に展開される.
これを使って(マクロ名を変更して)次のようにしてみた.
\def\jlreq@getfirsttoken#1#{\jlreq@getfirsttoken@#1\bgroup\jlreq@endmark}
\def\jlreq@getfirsttoken@#1#2\jlreq@endmark#3\jlreq@endmark{#1}
\long\def\jlreq@ifempty#1{%
\expandafter\expandafter\expandafter\ifx\jlreq@getfirsttoken#1\jlreq@uniqtoken{}\jlreq@endmark
\jlreq@uniqtoken
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo\fi}
前のと対応させると,\X
が\jlreq@uniqtoken
,\Y
が\bgroup
,\Z
が\jlreq@endmark
である.これで大体うまく行くと思う.まぁ空白トークンは闇に消えますが.
etoolboxに \ifblank というマクロがありますが、それと同じ仕様ですかね。
返信削除%---- etoolbox.sty 470行目
% ここで'&'のcatcodeは3で, 実質的にユニーク
\newcommand{\ifblank}[1]{% from url.sty
\etb@ifblank@i#1&&\@secondoftwo\@firstoftwo:}
\long\def\etb@ifblank@i#1#2#4#5:{#4}
なんかそうっぽいですね.賢いなぁ.(そして\expandafterを消された.)そうすると\jlreq@ifendmarkもこんなんでいいのか.
返信削除\def\jlreq@ifendmark#1{\jlreq@ifendmark@#1\jlreq@endmark\@firstoftwo\@secondoftwo:}
\def\jlreq@ifendmark@#1\jlreq@endmark#2#3#4:{#3}
ちなみに手元のetoolbox(2017/01/02)の\ifblankは\detokenizeを使った実装になっているんですが,上のだと何かまずい点があったんでしょうか?