コマンドの前に引数を指定したTeXコマンド

コマンドの前に引数を指定したTeXコマンド

\mycmdTeXマジックを使って、 1つの引数を取るコマンドを作成することは可能ですか?前にコマンドと1その後. ということで、<arg1>\mycmd<arg2>. 試してみました

\documentclass{memoir}
\def#1\mycmd#2{Hello World of #1 and #2}
\begon{document}

{foo}\mycmd{bar}

\end{document}

しかし、明らかに失敗しました。とにかく、うまくいくとは思っていませんでした。

答え1

この問題は、異なる観点から検討されてきた。コマンドの前後に引数があるコマンドは可能ですか?しかし、状況は異なります。メイン コマンドの前または後に配置されるオブジェクト自体がマクロです。

「後ろ向き」のマクロは作成できません。マクロ展開後、TeX は厳密に「先入先出」です。さらに、マクロまたはプリミティブに引数を提供する必要がある場合にのみ入力をトークン化します。

マクロ展開後は展開できないトークンのみが残り、見つかった順に実行されて削除されます。そのため、次のような状況では

{abc}\macro{def}

が検査されるとき、その{abc}部分はすでになくなっています\macro。その痕跡は内部リストの一部に残ることがあるため、たとえば、TeX は、\unskip実行時に、それがグルーである場合に、現在のリストから最後のノードを削除するコマンドである を実行できます (細かい点では複雑ですが、基本的には事実です)。

コマンドは思われるやりたいことを実行するには です\over。ただし、これはマクロではなくプリミティブです。

その作業は内部リストのレベルで行われます。TeXが を見つけると\over、それは展開できないのでそれを実行します。実行は、現在の数式リストにあるものを特別な場所に保存して続行することで行われます。現在の数式リストの終わりが見つかると、TeXはそれと保存された部分を使用して、フラック分子としてヘッド サブリスト、分母としてテール サブリストを持つアトム。ただし、マクロ展開レベルでは何も起こりません。

あなたできるマクロが来る\firstかどうかを引数の後に先読みして確認し、次に何をすべきかについて適切な決定を下すマクロを用意します。\second

LuaTeX でも、マクロ プロセッサを変更しない限り、これを行うことはできません。これは、現在のリスト内のすべての種類のノードを調べて管理できるのに対し、TeX の機能はより制限されているからです (ペナルティ、グルー、カーニング、ボックスのみで、あらゆる状況に対応できるわけではありません)。

答え2

ご要望可能だたとえば encTeX の場合、次のコードをcsplainformat でコンパイルして試してください。

\mubyte \phantomcmd #1 {\endmubyte

\mubytein=0
\def\phantomcmd#1\mycmd#2{1=#1, 2=#2}
\def\mycmd{my}
\def\normalcmd#1{normal=#1}

\mubytein=1

\normalcmd{hello}    % gives: normal=hello 
...{foo}\mycmd{bar}  % gives: ...1=foo, 2=bar

\bye

\mubytein=1特殊入力がアクティブになると、文字\phantomcmdが出現するたびに が挿入されます{。これはトークン プロセッサと展開プロセッサの前で行われます。ただし例外があります。{トークン プロセッサによってトークン化された制御シーケンスの直後に が続く場合は、 は\phantomcmd挿入されません。したがって、 と の両方の例が機能します。2 番目の例は\normalcmd{hello}内部{foo}\cmd{bar}的に次のように機能します。

\phantomcmd{foo}\mycmd{bar}

そして、これは望みどおりに展開されます。しかし、この手法は非常に脆弱です。なぜなら、{制御シーケンスの直後ではない の各出現には、自動的に\phantomcmd(when \mybytein=1) が先行するからです。たとえば、これはクラッシュします:

\normalcmd {hello}   % this is transformed to \normalcmd\phantomcmd{hello}
bb {foo}\mycmd{bar}  % 

この例と前の例の違いに注意してください。 の直後のスペースです\normalcmd

この脆弱性を恐れなければ、\pfantomcmdさまざまなプロセスを定義できます\mycmds

\mubyte \phantomcmd #1 {\endmubyte
\mubytein=0
\def\phantomcmd#1{\def\tmp{#1}}
\def\mycmdA#1{I am A. before: \tmp, after: #1}
\def\mycmdB#1{I am B. before: \tmp, after: #1}
\mubytein=1
... {a}\mycmdA{b} ... {x}\mycmdB{y}
\bye

答え3

OP のコメントでは、このアプリケーションはカリグラフィ文字の前に引用符を事前に決定するというものであると述べられています。コメントへの返信で述べたように、問題をより制限できれば、おそらくいくらかの希望があるでしょう。たとえば、 が常に (そして唯一) catcode 12 の可能性の限られたセットからの 1 つのグリフである場合、それらのグリフを にして、 がそれに続くかどうかを先読みすることで、<arg1>目的の結果を得ることができます。\active\mycmd

このアプローチは、他のマクロ内で可能性が必要でない限り使用できます<arg1>。たとえば、ピリオドは、小数点を使用して次元を指定するために頻繁に使用されるため、.ではうまく機能しません。<arg1>

MWE では、<arg1>\mycmd<arg2>巨大な が出力されます\fbox{<arg1><arg2>}。 については、二重引用符または疑問符を傍受するようにのみ設定していますが<arg1>、その他の catcode 12<arg1>グリフを追加することもできます。

の「不正な」値を持つ呼び出しを無視するように編集されました<arg1>

\documentclass{article}
\let\precommand\relax
\let\mycmd\relax
\def\testnext#1#2{\ifx#1\mycmd\myactualcmd\precommand{#2}\else\precommand#1#2\fi}
\def\myactualcmd#1#2{\if#1\precommand\fbox{\Huge#1#2}\else#1#2\fi}
\let\svquote"
\catcode`"=\active
\def"{\let\precommand\svquote\testnext}
\let\svqmark?
\catcode`?=\active
\def?{\let\precommand\svqmark\testnext}

\begin{document}
Is this is a "test"\textbf{?}  This is a "\mycmd{BIG} test?\mycmd{!}

Here mycmd is used with illegal precommand =\mycmd{which} is ignored.
\end{document}

ここに画像の説明を入力してください

関連情報