在 itemize 环境中递归使用 \@ifnextchar

在 itemize 环境中递归使用 \@ifnextchar

我在递归使用宏时遇到了一些麻烦\@ifnextchar。我的目标是能够在或环境\subitem{item1}{item2}...{itemN}中调用。这是我目前所拥有的,但它只拾取了第一个参数。enumerateitemize

\makeatletter
\newcommand{\checknextarg}{\@ifnextchar\bgroup{\gobblenextarg}{}}
\newcommand{\gobblenextarg}[1]{ \item #1\checknextarg}
\newcommand*\@enumerate{enumerate}
\newcommand*\@itemize{itemize}
\renewcommand{\subitem}[1]{%
  \ifx\@currenvir\@enumerate
    \begin{enumerate}
        \item #1\checknextarg
    \end{enumerate}
  \else
    \ifx\@currenvir\@itemize
        \begin{itemize}
            \item #1\checknextarg
        \end{itemize}
    \fi
  \fi    
}
\makeatother

例如

\begin{enumerate}
 \item foo
 \subitem{bar}{baz}
\end{enumerate}

生产

在此处输入图片描述

答案1

在这里我使用了一个标记循环(一种递归循环输入流的标记的工具),并带有以下指令:

  1. 如果下一个标记是字符或宏(即控制序列),则结束标记循环 + 结束子枚举 + 将下一个标记恢复到输入流

  2. 如果下一个 token 是 cat-1 组,则应用于\item该组内容

  3. 如果下一个标记是空格,则忽略它。

MWE 证明了当\subenumerate出现在项目中间、项目之间或枚举末尾时的有效性。

这里,我没有区分 itemize 和 enumerate,而只是求解了。可以构造enumerate一个等价的。\subitemize

\documentclass{article}
\usepackage{tokcycle}
\Characterdirective{\tcpush{\noexpand\endtokcycraw\end{enumerate}#1}}
\Groupdirective{\item{#1}}
\Macrodirective{\tcpush{\noexpand\endtokcycraw\end{enumerate}#1}}
\Spacedirective{}
\newcommand\subenumerate{\begin{enumerate}\tokencyclexpress}
\begin{document}

\begin{enumerate}
 \item foo1
 \subenumerate{bar}{baz}
  continue foo
 \item foo2
 \subenumerate{bar2}{baz2}
 \item foo3
 \subenumerate{bar3} {baz3}
\end{enumerate}
End of enumerate
\end{document}

在此处输入图片描述

或者,可以将标记循环指令合并到宏定义本身中:

\documentclass{article}
\usepackage{tokcycle}
\newcommand\subenumerate{\begin{enumerate}\tokencycle
  {\tcpush{\noexpand\endtokencycle\end{enumerate}##1}}%CHARS
  {\item{##1}}%GROUPS
  {\tcpush{\noexpand\endtokencycle\end{enumerate}##1}}%MACROS
  {}%SPACES
}
\begin{document}

\begin{enumerate}
 \item foo1
 \subenumerate{bar}{baz}
  continue foo
 \item foo2
 \subenumerate{bar2}{baz2}
 \item foo3
 \subenumerate{bar3} {baz3}
\end{enumerate}
End of enumerate
\end{document}

答案2

我警告你不要这么做。它破坏了 LaTeX 的所有已知语法(如果你想创建索引,就会遇到问题)。

\documentclass{article}

\makeatletter
\newcommand{\check@next@arg}{\@ifnextchar\bgroup{\another@item}{\finish@up}}
\newcommand{\another@item}[1]{\item #1\check@next@arg}
\renewcommand{\subitem}{%
  \edef\finish@up{\noexpand\end{\@currenvir}}%
  \expandafter\begin\expandafter{\@currenvir}%
  \check@next@arg
}
\makeatother

\begin{document}

\begin{enumerate}
 \item foo
 \subitem{bar}{baz}
\end{enumerate}

\begin{itemize}
 \item foo
 \subitem{bar}{baz}{whatever}
\end{itemize}

\end{document}

在此处输入图片描述

你的错误是什么?你吸收了第一个参数,当你的\checknextarg命令进入场景时,它会找到\end下一个标记。

我更喜欢显式标记。但是,这里有一个略有不同的版本,它允许选择不同的列表类型,并使用在 处拆分的单个参数\\

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\sublist}{om}
 {
  \IfNoValueTF { #1 }
   {
    \richbai_sublist:vn { @currenvir } { #2 }
   }
   {
    \richbai_sublist:nn { #1 } { #2 }
   }
 }

\seq_new:N \l__richbai_sublist_items_seq

\cs_new_protected:Nn \richbai_sublist:nn
 {
  \begin{#1}
  \seq_set_split:Nnn \l__richbai_sublist_items_seq { \\ } { #2 }
  \item \seq_use:Nn \l__richbai_sublist_items_seq { \item }
  \end{#1}
 }
\cs_generate_variant:Nn \richbai_sublist:nn { v }

\ExplSyntaxOff

\begin{document}

\begin{enumerate}
 \item foo
 \sublist{bar \\ baz}
\end{enumerate}

\begin{itemize}
 \item foo
 \sublist[enumerate]{bar \\ baz \\ whatever}
 \item bar
\end{itemize}

\begin{itemize}
 \item foo
 \sublist{bar \\ baz \\ whatever}
 \item bar
\end{itemize}

\end{document}

在此处输入图片描述

相关内容