Ein Makro zum Überprüfen der Befehlserweiterbarkeit

Ein Makro zum Überprüfen der Befehlserweiterbarkeit

Ich möchte erstellenein Befehl, der prüft, ob ein Ausdruck vollständig erweiterbar ist, und abstürzt, wenn dies nicht der Fall ist(idealerweise eine Fehlermeldung drucken). Das würde ich gerne machenohne eine bestimmte TeX-Engine im Sinn zu haben. Ich denke, es hängt mit dieser Frage zusammenÜberprüfen Sie, ob das Makro vollständig erweiterbar ist, aber die bereitgestellte Antwort erfordert LuaTeX.


Testcode

Ein Testcode würde folgendermaßen aussehen:

\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}

Falls es zu kompliziert ist

Wenn dies nicht machbar ist, bin ich damit einverstanden, die Befehlssignatur so zu ändern, dass sie einen Parameter einschließt, zu dem der Befehl erweitert werden soll:

\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}

Kommentar zur Erweiterbarkeit

Da die Definition von „vollständig erweiterbar“ nicht so klar ist, wie man meinen könnte (siehe Kommentar unten), besteht der Kontext dieser Frage darin, dass ich nur versuche, etwas zu erstellen, das mir beim Debuggen von Code hilft. Ich bin damit einverstanden, die Frage auf dieses spezifische Verhalten zu beschränken: ob das Makro im Kontext von Makros wie dem \colorBefehl funktionieren würde:

\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}

Im Grunde erledigt der \colorBefehl die von mir gesuchte Aufgabe. Ich möchte ihn nur \checkexpandabilityetwas allgemeiner aufrufen und eine nette Fehlermeldung ausgeben lassen.

Antwort1

Ich denke, das grundlegende Missverständnis ist

Im Grunde erledigt der \colorBefehl die Art von Arbeit, die ich suche.

Der \colorBefehl führt keine Überprüfungen des angeforderten Typs durch, sondern erwartet lediglich, dass das Argument nach der Erweiterung ein definierter Farbname ist. Wenn die Erweiterung fehlschlägt, erhalten Sie einen Fehler auf niedriger Ebene, oder wenn die Erweiterung zu einer undefinierten Farbe erfolgt, erhalten Sie eine spezifische Fehlermeldung, aber kein Teil der Verarbeitung ist generisch oder gilt für einen anderen Befehl als Befehle, die Farben erwarten.

Die einzige Version, die implementiert werden könnte, ist die Version mit einer erwarteten Erweiterung, da diese einfach fragt, ob die beiden Argumente nach der Erweiterung gleich sind. Die L3-Programmierschicht hat mehrere Varianten davon, oder Sie könnten das ifthenPaket verwenden und

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

Dies gibt „yes“ zurück, wenn die Argumente auf dasselbe Ergebnis erweitert werden, „no“, wenn dies nicht der Fall ist, oder gibt einen Fehler auf niedriger Ebene aus, wenn das Argument in einem Erweiterungskontext nicht sicher ist (was normalerweise mit „ist nicht erweiterbar“ gemeint ist).

Antwort2

Zum Debuggen Ihres Codes würde ich einfach verwenden \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}

Der Punkt ist, dass \typeoutdas Argument vollständig erweitert wird und dann das vollständig erweiterte Ergebnis auf dem Terminal ausgedruckt wird – Sie können also einfach einen Blick auf das Terminal werfen.

Im ersten Fall wird gedruckt blue, also ist alles in Ordnung. Im zweiten Fall stürzt es ab.


Natürlich gibt es mit dem obigen Ansatz zwei Probleme.

  • Selbst wenn\expandable{blue} Istvollständig erweiterbar (was auch immer das bedeutet),Es kann sein, dass nicht \colorgarantiert ist, dass das Argument vollständig ausgearbeitet wird, bevor das Ergebnis als Farbwert interpretiert wird.. (Ich schätze durchHyrums GesetzIn der Praxis geht es jedoch darum, die Beschädigung „vorhandener Pakete“ zu vermeiden.)

    Wenn Sie also ganz sicher sein wollen, ist es besser, es im Voraus zu erweitern, beispielsweise mit\ExpandArgs.

  • Dabei gehen die Informationen zum Kategoriecode sowie eventuell im Code enthaltene Sonderzeichen (z. B. Leerzeichen statt Tabulator) verloren.

    In der Praxis wäre dies nicht so wichtig, manchmal ist es aber doch so (z. B. wenn Sie versuchen, ein Paket zu debuggen, das den Umgebungstext wörtlich zu erfassen versucht).

    Wenn das der Fall ist, sollten Sie versuchenmein Paket. (der Code ist im Moment ein Durcheinander, aber er funktioniert, und es gibt Pakete mit schlechterem Quellcode)

verwandte Informationen