コマンドの拡張性をチェックするマクロ

コマンドの拡張性をチェックするマクロ

作りたい式が完全に展開可能かどうかをチェックし、展開できない場合はクラッシュするコマンド(理想的にはエラーメッセージを表示する)。それをやりたい特定のTeXエンジンを念頭に置かずにこの質問に関連していると思いますマクロが完全に展開可能かどうかを確認するただし、提供された回答には LuaTeX が必要です。


テストコード

テストコードは次のようになります。

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xparse}
\usepackage{xstring}

\NewDocumentCommand{\checkexpandability}{m}{
    % CODE HERE
}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}

\begin{document}
\checkexpandability{\expandable{test}} % Should be OK
\checkexpandability{\notexpandable{test}} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}} % Should CRASH
\end{document}

複雑すぎる場合は

それが実行できない場合は、コマンド シグネチャを変更して、コマンドが展開されるパラメータを含めても問題ありません。

\begin{document}
\checkexpandability{\expandable{test}}{test} % Should be OK
\checkexpandability{\notexpandable{test}}{test} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}}{true} % Should CRASH
\end{document}

拡張性に関するコメント

完全に拡張可能の定義は、考えられるほど明確ではないため (以下のコメントを参照)、この質問のコンテキストは、コードのデバッグに役立つものを作成しようとしているだけです。質問をこの特定の動作に限定しても問題ありません。つまり、マクロがコマンドのようなコンテキスト マクロで機能するかどうかです\color

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\color{\expandable{blue}} % OK
\color{\notexpandable{red}} % CRASHES
X
\end{document}

基本的に、このコマンドは私が求めている種類の作業を実行しますが、私はそれを と呼び、もう少し汎用性を高め、わかりやすいエラー メッセージを出力したい\colorと思います。\checkexpandability

答え1

基本的な誤解は

基本的に、この\colorコマンドは私が求めている種類の仕事をします。

この\colorコマンドは要求されたタイプのチェックは行わず、展開後に引数が定義済みの色名であることを期待するだけです。展開が失敗すると低レベルのエラーが発生し、未定義の色に展開されると特定のエラー メッセージが表示されますが、処理のどの部分も汎用的ではなく、色を期待するコマンド以外のコマンドには適用されません。

実装できる唯一のバージョンは、2つの引数が展開後に等しいかどうかを単純に尋ねる、期待される展開を伴うバージョンです。L3プログラミング層にはそのバリエーションがいくつかありますが、パッケージを使用しifthen

\ifthenelse{\equal{\expandable{test}}{test}}{yes}{no}

引数が同じものに展開される場合は yes を返し、そうでない場合は no を返します。引数が展開コンテキストで安全でない場合は低レベルのエラーを返します (これは通常、「展開可能ではない」という意味です)。

答え2

コードをデバッグするには、 を使用します\typeout

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\typeout{\expandable{blue}} % OK, print "blue"
\typeout{\notexpandable{red}} % CRASHES
X
\end{document}

ポイントは、\typeout引数を完全に展開し、完全に展開された結果をターミナルに印刷することです。つまり、ターミナルを確認するだけでよいのです。

最初のケースでは と印刷されるblueので、すべて正常です。2 番目のケースではクラッシュします。


もちろん、上記のアプローチには 2 つの問題があります。

  • たとえ\expandable{blue} 完全に拡張可能(それが何を意味するかはともかく)、\color結果を色として解釈する前に、その議論を完全に展開することが保証されているわけではないかもしれない。(たぶんハイラムの法則ただし、実際には「既存のパッケージ」を壊さないようにするためです。

    したがって、さらに確実にしたい場合は、例えば次のようにして事前に拡張しておくとよいでしょう。\ExpandArgs

  • カテゴリ コードに関する情報、およびコード内に潜む特殊文字 (スペースとタブなど) は失われます。

    実際にはこれはあまり問題になりませんが、時には問題になることがあります。(たとえば、環境本体を逐語的にキャプチャしようとするパッケージをデバッグしようとするときなど)

    もしそうなら、試してみることを検討してください私の荷物(コードは今のところめちゃくちゃですが、まあ動作しますし、もっとひどいソースコードのパッケージも存在します)

関連情報