我有一个使用 创建一些列表的包enumitem
。全局更改列表参数的标准方法是使用\setlist
,但如果列表是自定义列表,这有时会产生错误。这是一个最小文档。
在下面的代码中,假设自定义列表test
是在包中定义的,即包的最终用户看不到\newlist
和\setlist
命令。因此,他们会假设他们可以使用\setlist[test]{nosep}
来全局设置列表间距test
。但此命令失败并出现错误。
\documentclass{article}
\usepackage{enumitem}
% assume this code is in a package
\newlist{test}{enumerate}{1}
\setlist[test]{resume,leftmargin=*,label=(\arabic*)}
% end package code
% Now a user wants to adjust the list properties
\setlist[test]{nosep} % This doesn't work \setlist* is needed
%\setlist*[test]{nosep] % works and makes sense because it adds to list
%\setlist[test,1]{nosep} % But why does this work?
\begin{document}
\begin{test}
\item This is an item
\end{test}
\end{document}
有两种方法可以解决这个问题:1) 使用\setlist*
或 2) 使用\setlist[test,1]
,即添加显式级别。这两种选择都不是普通用户所期望的。
问题
- 为什么
\setlist[test]
会失败又会\setlist[test,1]
起作用? - 有没有办法解决这个问题,这样我就不需要指导用户如何明确设置列表属性?
答案1
为什么\setlist[test]
会失败又会\setlist[test,1]
起作用?
其核心功能是使用 来\setlist[<arg>]
保存传递给它的设置。\enit@@<slightly modified version of 'arg'>
\def
因此,\setlist[test]
会覆盖先前的\setlist[test]
,因为它们都保存到同一个宏中\enit@@test
。但\setlist[test,1]
不会覆盖所做\setlist[test]
的,因为它保存到\enit@@testi
。
您的示例会失败,因为\setlist[test]{nosep}
删除了先前的定义,特别是label
导致新test
环境没有标签的定义。
我之前没有意识到这一点,甚至不知道\setlist*
,但现在我觉得这\setlist*
更自然,应该是更改列表设置的首选命令。但我怀疑很多人有同样的感觉,甚至不知道\setlist*
,所以这可能不是一个选择。
等等,为什么无辜的人\setlist[enumerate]{nosep}
不会犯这些错误?
enumerate
很特殊,因为它是在 LaTeX 内核中定义的。它的标签定义通常在文档类中设置,因此您不会遇到\setlist[enumerate]
覆盖enumitem
设置的麻烦。test
另一方面,您的 LaTeX 是一张白纸,因此它需要标签定义。
啊哈!我们为什么不定义一个默认计数器呢?
的确
\newcounter{testi}
\renewcommand\thetesti{\arabic{testi}}
\def\labeltesti{(\thetesti)}
\newlist{test}{enumerate}{1}
\setlist[test]{resume,leftmargin=*,label=(\arabic*)}
如果稍后使用,错误就会消失\setlist[test]{nosep}
。但仔细检查后我们发现,这只会节省\setlist[test]{label=(\arabic*)}
。我们还必须resume,leftmargin=*
自己设置。但这两个不能像设置那样容易label=(\arabic*)
。你最终会enumitem
在包中泄露干净的界面。
有没有解决的办法?
我从这些调查中得出的结论是,我会尝试教育用户使用\setlist*
而不是\setlist
。抱歉。
可以做出像\setlist[test]{label=(\arabic*)}
\setlist
证明这样的定义,但像更复杂的东西\setlist[test]{resume,leftmargin=*,label=(\arabic*)}
需要大量额外的工作,最终可能不值得(如果可能的话,我没有检查是否可以让类似的东西resume
起飞)。