我想修改itemized
环境(这里称为myitemized
),以便它只显示第一个否列表中的元素。基本上我希望能够做类似的事情
\documentclass{article}
\newcommand{\maxlist}{3}
\begin{document}
\begin{myitemize}
\item First item
\item Second item
\item Third item
\item Fourth item
\end{myitemize}
\end{document}
并得到
- 第一项
- 第二项
- 第三项
其中,所有之后的项目\maxlist
(本例中为 3)均被省略。
编辑
Niel de Beaudrap 的回答回答了上述问题。对于我的应用程序,我希望能够将截断环境包装在另一个环境中。类似于\newenvironment{wrapper}{\begin{truncitemize}}{\end{truncitemize}}
。
答案1
可以通过改编 中的部分代码来生成解决方案amsmath.sty
。如果细节看起来很复杂,请不要担心,但这里有一些您可以使用的代码,并附有一些注释。
启用忽略列表中剩余项目的代码
我们需要某种方法来收集某个点之后项目列表中剩余的所有内容,其中项目要点也可能包含环境。这强烈促使我们使用与环境非常相似的代码来收集、和其他多行数学环境amsmath
的主体。align
gather
编辑:正如评论中所述egreg
,大多数功能由environ
包提供,我们可能会将其包括在内以简化代码。但是,我们仍然需要修改环境\collect@body
中使用的主宏的版本amsmath
,以控制对已收集的列表项的实际操作。我们给它一个不同的名称,以便它不会与现有宏冲突,并对其进行了轻微的修改。具体来说,新宏不接受(或对)参数执行任何操作,并且不是实际使用它收集的源的内容,而是执行一个宏来代替列表中所有剩余的项目。(可以单独修改此宏以执行任何您喜欢的操作,包括什么都不做。)
\usepackage{environ}% <--- for \collect@@body, etc.
\makeatletter
\def\truncatedlist@omit{%
\edef\process@envbody{%
\noexpand\let\noexpand\item\noexpand\orig@item
\noexpand\omitlistitems \noexpand\end{\@currenvir}}%
\@envbody\@emptytoks \def\begin@stack{b}%
\begingroup
\expandafter\let\csname\@currenvir\endcsname\collect@@body
\edef\process@envbody{\expandafter\noexpand\csname\@currenvir\endcsname}%
\process@envbody
}
请特别注意第一行,它将 重新定义\item
为某个宏 的值\orig@item
。这是因为,对于您的截断列表环境,我们将修改 的定义\item
,但在描述要做什么时,可能希望使用 的原始含义,\item
而不是省略的项目。
定义新的截断列表环境
现在我们进入练习的重点。定义两个计数器:
\newcounter{trunclistnum}
\newcounter{trunclistlimit}
\setcounter{trunclistlimit}{3}% <--- or whatever limit you prefer
我们还定义了如何处理省略的项目。
\def\omitlistitems{\item $\cdots$}
% or if you prefer, \def\omitlistitems{}
最后,我们定义列表本身。以下代码基本上是itemize
对 中的环境的修改latex.ltx
。它将项目数设置为零,并重新定义\item
以检查项目数是否超出限制。如果是,它会调用用于省略其余项目的宏;否则它会调用包含 的原始行为的宏\item
。
\let\endtruncitemize\enditemize
\def\truncitemize{%
\ifnum \@itemdepth >\thr@@\@toodeep\else
\c@trunclistnum=0\relax
\let\orig@item\item
\def\item{%
\ifnum\c@trunclistnum<\c@trunclistlimit
\let\@tempa\orig@item%
\else
\let\@tempa\truncatedlist@omit%
\fi
\advance\c@trunclistnum by 1%
\@tempa}%
\advance\@itemdepth\@ne
\edef\@itemitem{labelitem\romannumeral\the\@itemdepth}%
\expandafter
\list
\csname\@itemitem\endcsname
{\def\makelabel##1{\hss\llap{##1}}}%
\fi}
\makeatother
示范
将所有这些内容放入文档的前言中,然后尝试以下内容:
\begin{document}
\subsection*{Result}
A truncated itemized list:
\begin{truncitemize}
\item First item
\item Second item
\item Third item
\item Fourth item
\item Yet further items
\end{truncitemize}
A normal itemized list:
\begin{itemize}
\item First item
\item Second item
\item Third item
\item Fourth item
\item Yet further items
\end{itemize}
\end{document}
答案2
我们可以让environ
完成将环境内容加载到 中的大工作\BODY
。然后我们重新定义\item
一个计数器,在启动环境时将其设置为零itemize
;然后 new\item
检查计数器的值是否高于阈值(\maxlist
)。在这种情况下,它会吞噬剩余的所有内容(可能会打印“省略”的项目);否则它会发出我们保留在 中的\ignore@to@end
常规内容。\item
\old@item
这甚至可以嵌套,并且可以使用可选参数在本地更改阈值。
\documentclass{article}
\usepackage{environ}
\makeatletter
\NewEnviron{myitemize}[1][\maxlist]{%
\begin{itemize}
\@tempcnta=\z@
\def\item{\advance\@tempcnta\@ne\ifnum\@tempcnta>#1\relax
\show@omitted@items
\expandafter\ignore@to@end
\else
\expandafter\old@item
\fi}%
\BODY\final@sentinel
\end{itemize}}
\long\def\ignore@to@end#1\final@sentinel{}%
\let\final@sentinel\@empty
\let\old@item\item
\newif\if@show@omitted
\newcommand{\showomitted}{\@show@omittedtrue}
\newcommand{\dontshowomitted}{\@show@omittedfalse}
\newcommand{\show@omitted@items}{\if@show@omitted\old@item\relax\dots\fi}
\makeatother
\newcommand{\maxlist}{3}
\begin{document}
\begin{myitemize}\showomitted
\item Yes
\item Yes
\begin{myitemize}\dontshowomitted
\item Yes
\item Yes
\item Yes
\item No
\item No
\item No
\end{myitemize}
\item Yes
\item No
\item No
\item No
\end{myitemize}
separator
\begin{myitemize}[5]
\item Yes
\item Yes
\item Yes
\item No
\item No
\item No
\end{myitemize}
\end{document}