После того, как я начал создавать свои собственные среды, мне стало интересно, есть ли условие if, которое проверяет, какая следующая команда, а затем дает возможность запустить что-то перед следующей командой. Пример псевдокода для того, что я ищу:
\newenvironment{test}{
ifnext{\begin{itemize}}{true: do something}{false: do other things}
}
{
}
решение1
В LaTeX есть макрос \@ifnextchar
. Название может немного вводить в заблуждение, вы можете использовать его не только для проверки следующего одиночного символа, но и для макроса с определенным значением, например, вы можете проверить, является ли следующее во входном потоке \begin
.
Это можно использовать для создания макроса \ifnextenv
. Он будет принимать три аргумента, имя среды, код, который будет выполнен, если эта среда следует за ним, и код, который выполняется в противном случае. Макрос проверит, является ли следующее во входном потоке (после трех его аргументов) \begin
. Если это так, он проверит, \begin
соответствует ли первый аргумент первому аргументу с \ifnextenv
помощью\pdf@strcmp
.
Затем он вставит ветви в соответствии с результатами теста.
В этом примере использования используется \ifnextenv
автоматическая вставка itemize
if после \begin{test}
no \begin{enumerate}
following.
\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}
решение2
Вот как это сделать с помощью цикла токенов.
Каждый раз, когда я нахожу \begin{itemize}
, я предварительно выполняю \PREitemize
, который здесь установлен на \par Hi Mom, I am about to itemize
. Если есть \begin
обнаруженный , но это не itemize
, я предварительно выполняю \PREbegin
, здесь установлен на \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}