Nachdem ich angefangen hatte, meine eigenen Umgebungen zu erstellen, fragte ich mich, ob es eine if-Bedingung gibt, die prüft, was der nächste Befehl ist, und dann die Option bietet, vor dem nächsten Befehl etwas auszuführen. Ein Pseudocode-Beispiel für das, was ich suche:
\newenvironment{test}{
ifnext{\begin{itemize}}{true: do something}{false: do other things}
}
{
}
Antwort1
LaTeX verfügt über das Makro \@ifnextchar
. Der Name ist vielleicht etwas irreführend, denn man kann es nicht nur verwenden, um das nächste einzelne Zeichen zu testen, sondern auch für ein Makro mit einer definierten Bedeutung, z. B. kann man testen, ob das nächste Element im Eingabestrom ist \begin
.
Dies kann zum Erstellen eines Makros verwendet werden \ifnextenv
. Es benötigt drei Argumente: den Namen der Umgebung, Code, der ausgeführt wird, wenn diese Umgebung darauf folgt, und Code, der andernfalls ausgeführt wird. Das Makro prüft, ob das nächste Element im Eingabestrom (nach seinen drei Argumenten) ist \begin
. Wenn dies der Fall ist, prüft es, ob das erste Argument mit \begin
dem ersten Argument \ifnextenv
übereinstimmt \pdf@strcmp
.
Anschließend werden die Zweige entsprechend den Testergebnissen eingefügt.
In diesem Anwendungsbeispiel \ifnextenv
wird automatisch ein „ itemize
if“ nach „ \begin{test}
no \begin{enumerate}
follow“ eingefügt.
\documentclass[]{article}
\usepackage{pdftexcmds}
\makeatletter
\newcommand\ifnextenv[3]
{%
\@ifnextchar\begin{\@ifnextenv{#1}{#2}{#3}}{#3}%
}
\newcommand\@ifnextenv[5]
{%
\ifnum\pdf@strcmp{#1}{#5}=0
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#2}
{#3}%
\begin{#5}%
}
\makeatother
\newenvironment{test}
{%
\ifnextenv{enumerate}
{\def\test@end{}}
{\def\test@end{\enditemize}\itemize}%
}
{%
\test@end
}
\begin{document}
\begin{test}
\item foo
\item bar
\end{test}
\begin{test}
\begin{enumerate}
\item foo
\item bar
\end{enumerate}
\end{test}
\end{document}
Antwort2
Hier ist eine Möglichkeit, dies mit einem Token-Zyklus zu tun.
Jedes Mal, wenn ich ein finde \begin{itemize}
, führe ich vorab aus \PREitemize
, was ich hier auf setze \par Hi Mom, I am about to itemize
. Wenn ein \begin
erkannt wird, es aber nicht ist itemize
, führe ich vorab aus \PREbegin
, was ich hier auf setze \par Sorry, this begin is not itemize
.
\documentclass{article}
\usepackage{tokcycle}
\def\ITM{itemize}
\def\TRUESET{T}
\def\PREitemize{\par Hi Mom, I am about to itemize}
\def\PREbegin{\par Sorry, this begin is not itemize}
\stripgroupingtrue
\tokcycleenvironment\finditemize
{\addcytoks{##1}}
{\tctestifx{\TRUESET\BEGgo}%
{\def\tmp{##1}\tctestifx{\ITM\tmp}%
{\addcytoks[1]{\PREitemize}}{\addcytoks[1]{\PREbegin}}
\addcytoks{\begin{##1}}}%
{\addcytoks{{##1}}}%
\def\BEGgo{F}%
}
{\tctestifx{\begin##1}{\def\BEGgo{T}}{\addcytoks{##1}}}
{\addcytoks{##1}}
\begin{document}
\finditemize
Here is a test
\begin{itemize}
\item A
\begin{itemize}
\item A.1
\item A.2
\end{itemize}
\item B
\item C
\end{itemize}
\begin{enumerate}
\item A
\item B
\item C
\end{enumerate}
\endfinditemize
\end{document}