Warum funktioniert der folgende Code nicht?
\Requirepackage{amsthm}
\renewcommand\newtheorem[2]{%
\NewEnviron{\csname #1\endcsname}[1]{%
##1 : \BODY
}
}
Ich habe Beispiele für die Verwendung eines Makros ohne Argumente gesehen \csname SOMENAME\endcsname
, weiß aber nicht, wie ich es mit einem \NewEnviron
oder einem \newcommand
mit mehreren Argumenten machen soll. Ich erhalte die Fehlermeldung ! Missing \endcsname inserted
.
Antwort1
Sie möchten keinen Befehlsnamen für den Namen einer Umgebung. Nur der Name ist ausreichend.
Sie können also Folgendes tun:
\documentclass{article}
\usepackage{amsthm,environ}
\renewcommand\newtheorem[2]{%
\NewEnviron{#1}[1]{%
##1 : \BODY
}%
}
\begin{document}
\newtheorem{acorns}{oaks}
\begin{acorns}{trees}
leaves and things
\end{acorns}
\end{document}
Beachten Sie, dass dieser Code nicht erfordertamstham, Sie können es einfach verwenden, \newcommand\newtheorem...
es sei denn, Sie benötigen das Paket aus anderen Gründen.
Außerdem tun Sie mit dem zweiten Argument nie etwas, obwohl Sie den Befehl so erstellen, dass er erforderlich ist. Im obigen Beispiel wird mit nie etwas getan oaks
.
Ich bin nicht überzeugt, dass das wirklich das ist, was Sie tun möchten. Die Ausgabe des obigen Codes lautet:
AlsChristian Hupfer weist darauf hin, dies wird natürlich alles zerstören, was \newtheorem
im Standardsinn verwendet wird. Alsegreg sagt, es ist überhaupt nicht klar, welchem Zweck \newtheorem
eine solche Neudefinition dient. Es scheint fast garantiert, dass es früher oder später zu Problemen führen wird ... wahrscheinlich früher.
Antwort2
Warum funktioniert der folgende Code nicht?
Schauen wir uns genauer an, was das \NewEnviron
bedeutet:
Danach wird eine kurze Makrokette \NewEnviron
verwendet , um die Benutzereingaben richtig zu analysieren \env@newenvironment
, was am Anfang der Fall \let
war .\newenvironment
Nun \newenvironment
macht intern unter anderem (etwas vereinfacht) so etwas wie
\expandafter\def\csname <env-name>\endcsname{<begin-code>}
(Im Grunde haben Sie das Richtige getan, ohne zu wissen, dass die internen Prozesse sich bereits darum kümmern.)
Wenn Sie " " setzen <env-name>=\csname SOMENAME\endcsname
– was sich aus der Verwendung Ihres benutzerdefinierten Makros wie folgt ergeben würde \newtheorem{SOMENAME}{}
– erhalten Sie ein überflüssiges \csname...\endcsname
Paar:
\expandafter\def\csname\csname SOMENAME\endcsname\endcsname...
\expandafter
(wie Sie wahrscheinlich wissen) greift \def
und speichert es in diesem Fall, um nach dem nächsten Token zu suchen und dieses zuerst zu erweitern. Hier findet es \csname
which, sucht nach dem nächsten \endcsname
und erweitert alles dazwischen und bildet daraus eine Kontrollsequenz. Dies wäre eine weitere \csname
, die wieder korrekt durch das abschließende beendet wird \endcsname
. Sie wenden den Mechanismus also tatsächlich zweimal auf 'SOMENAME' an und das bedeutet, dass Sie nicht (wie geplant) \csname
mit enden , sondern mit\def\SOMENAME{<begin-code>}
\def\<expansion of \SOMENAME>{<begin-code>}
Wenn \SOMENAME
definiert war, hatten wir kein Problem:
\documentclass{article}
\usepackage{environ}
\def\SOMENAME{somename}
\NewEnviron{\csname SOMENAME\endcsname}{somename-content: \BODY}
\begin{document}
\begin{somename}
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer feugiat tempus urna, cursus placerat sapien mollis ac.
Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}
Aber du solltestnichtdefinieren; diese Benutzeroberfläche wäre irgendwie irreführend. Verwenden Sie einfach \NewEnviron
genau das gleiche wie \newenvironment
bei der Eingabe des Umgebungsnamens:
\documentclass{article}
\usepackage{environ}
\newcommand{\FlorianEnvdefWrapper}[1]{%
\NewEnviron{#1}[1]{##1: \BODY}
}
\FlorianEnvdefWrapper{somename}
\begin{document}
\begin{somename}{foo-bar}
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer feugiat tempus urna, cursus placerat sapien mollis ac.
Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}
Anmerkung
Ich habe den Namen Ihres Beispielmakros geändert, um Konflikte mit dem amsthm
Paket zu vermeiden. Ich denke, es ist im Allgemeinen besser, diese Dinge so zu belassen, wie sie sind. Sicherlich gibt es Ausnahmen, aber der vollständige Verlust der Funktionalität ist möglicherweise nicht die beste Option, wenn Sie dies vermeiden können, indem Sie einfach einen anderen Namen für Ihren Befehl wählen.