我正在处理一个文档模板,其中有一些嵌套的逐项列表,我需要在每个列表元素之前和之后添加一些命令。
为了实现这一点,我用命令创建了一个新的环境\newenvironment
,我将其称为环境tlist
的包装器itemize
,并且还创建了一个名为的新命令,\titem
它是命令的包装器\item
。
然后我使用 来\newif
检测某个项目是否已打开和关闭,以允许列表嵌套,而无需 之后的任何内容\titem
。 MWE 如下所示。
\documentclass{article}
\usepackage{ifpdf}
\usepackage{etoolbox}
% Keep track of whether we are in a titem
\newif\ifistitemopen
% TList environment
\newenvironment{tlist}{
% Begin list
\begin{itemize}
% Check if an item is open already
\ifistitemopen
% Must be in a nested list. Close just the body
\item close by tlist begin
\fi
% No item is open
\istitemopenfalse
}{
% No item is open
\ifistitemopen
% Close previous list item if open
\item close by tlist end
\istitemopenfalse
\fi
% End list
\end{itemize}
}
% New user command \titem replaces \item
\newcommand{\titem}{
\ifistitemopen
% Close previous list item if open
\item close by new item
\fi
\istitemopentrue
% Open new list item
\item open by new item
\item
}
\begin{document}
\textbf{Bad Example 1:}
\begin{tlist}
\titem Foo
\begin{tlist}
\titem Bar
\end{tlist}
\end{tlist}
\textbf{Bad Example 2:}
\begin{tlist}
\titem Foo
\begin{tlist}
\titem Bar
\end{tlist}
\titem Fizz
\end{tlist}
\end{document}
\if...
目前,这基本上是可行的,除了我无法理解的原因,在将 is 设置为 false 后第一次对其进行检查似乎将其检测为 true。为了尝试可视化这一点,我\item
在代码中添加了一些额外的命令,以便在发生事情时打印出来。我展示了两个例子,其中 isif
被检查,即使它应该是 false,但\item
is 的输出好像它是 true 一样 - 如下图所示。
我不是 LaTeX 专家,因此,对于为什么会发生这种情况以及如何解决它,任何建议都将不胜感激。
答案1
它适用于计数器而不是条件语句,因为计数器是作用于全球(超越了他们所处的群体,环境形成了群体)。
相反,\newif
使得\...false
和\...true
命令只行动本地,因此它们的效果会以它们出现的组为终点。如果您希望命令全局起作用,您可以手动修复它们。
\documentclass{article}
\usepackage{ifpdf}
\usepackage{etoolbox}
% Keep track of whether we are in a titem
\newif\ifistitemopen
% redefine the associated commands to act globally
\def\istitemopentrue{\global\let\ifistitemopen\iftrue}
\def\istitemopenfalse{\global\let\ifistitemopen\iffalse}
% TList environment
\newenvironment{tlist}{%
% Begin list
\begin{itemize}
% Check if an item is open already
\ifistitemopen
% Must be in a nested list. Close just the body
\item close by tlist begin
\fi
% No item is open
\istitemopenfalse
}{%
% No item is open
\ifistitemopen
% Close previous list item if open
\item close by tlist end
\istitemopenfalse
\fi
% End list
\end{itemize}
}
% New user command \titem replaces \item
\newcommand{\titem}{%
\ifistitemopen
% Close previous list item if open
\item close by new item
\fi
\istitemopentrue
% Open new list item
\item open by new item
\item
}
\begin{document}
\textbf{Bad Example 1:}
\begin{tlist}
\titem Foo
\begin{tlist}
\titem Bar
\end{tlist}
\end{tlist}
\textbf{Bad Example 2:}
\begin{tlist}
\titem Foo
\begin{tlist}
\titem Bar
\end{tlist}
\titem Fizz
\end{tlist}
\end{document}
或者,在代码中执行\global\istitemopentrue
和。\global\istitemopenfalse
答案2
我不知道为什么它\newif
没有按预期工作,但我找到了一种使用计数器的解决方法:
\documentclass{article}
\usepackage{ifpdf}
\usepackage{etoolbox}
% Keep track of whether we are in a titem
\newcounter{titemopencount}
\setcounter{titemopencount}{0}
% TList environment
\newenvironment{tlist}{
% Begin list
\begin{itemize}
% Check if an item is open already
\ifnum\the\value{titemopencount}>0
% Must be in a nested list. Close just the body
\item close by tlist begin
\addtocounter{titemopencount}{-1}
\fi
% No item is open
}{
% No item is open
\ifnum\the\value{titemopencount}>0
% Close previous list item if open
\item close by tlist end
\addtocounter{titemopencount}{-1}
\fi
% End list
\end{itemize}
}
% New user command \titem replaces \item
\newcommand{\titem}{
\ifnum\the\value{titemopencount}>0
% Close previous list item if open
\item close by new item
\addtocounter{titemopencount}{-1}
\fi
\addtocounter{titemopencount}{1}
% Open new list item
\item open by new item
\item
}
\begin{document}
\textbf{Good Example 1:}
\begin{tlist}
\titem Foo
\begin{tlist}
\titem Bar
\end{tlist}
\end{tlist}
\textbf{Good Example 2:}
\begin{tlist}
\titem Foo
\begin{tlist}
\titem Bar
\end{tlist}
\titem Fizz
\end{tlist}
\end{document}
目前生产的产品有: