我正在尝试定义一个list
具有多个可选参数的环境,并为这些参数设置默认值。例如,创建一个名为newenv
,它接受两个参数,如果不存在则使用默认值:
\documentclass{article}
\usepackage{array}
\usepackage{multicol}
\usepackage{enumerate}
\begin{document}
\newenvironment{newenv}[2][2]
{\begin{multicols}[#1]\begin{enumerate}[#2]}
{\end{enumerate}\end{multicols}}
\begin{newenv}{2}{2}
\item a
\item b
\item c
\item d
\end{newenv}
\end{document}
我错过了什么?
答案1
我会用enumitem
包 - 它简化了语法并为我们完成了繁重的工作
第一部分是设置一个新的列表环境
\newlist{newenv}{enumerate}{5}
\setlist[newenv]{label=\arabic*.}
其默认标签为1.
, 2.
, 等
然后我们设置一个新密钥,columns
\SetEnumitemKey{columns}{before=\begin{multicols}{#1},
after=\end{multicols}}
这使我们能够使用各种组合,如下面的 MWE 所示
\documentclass{article}
\usepackage{enumitem}
\usepackage{multicol}
\newlist{newenv}{enumerate}{5}
\setlist[newenv]{label=\arabic*.}
\SetEnumitemKey{columns}{before=\begin{multicols}{#1},
after=\end{multicols}}
\begin{document}
\begin{newenv}[label=\roman*),columns=4]
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[columns=3]
\item a
\item b
\item c
\end{newenv}
\hrule
\begin{newenv}[label=\roman*)]
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[label*=(A\arabic*),columns=3]
\item a
\item b
\item c
\item d
\item e
\item f
\end{newenv}
\end{document}
答案2
我同意 Werner 的观点,认为多个可选参数应该用键值语法代替。下面是一种方法:
\documentclass{article}
\usepackage{enumerate,multicol,xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{newenv}{ O{} }
{
\keys_set:nn { aksr/newenv }
{
#1 % use the options
}
\int_compare:nT { \l__aksr_columns_tl > 1 } % more than one column
{ \begin{multicols}{ \l__aksr_columns_tl } }
% We must pass the optional argument expanded
\use:x { \exp_not:N \begin{enumerate}[ \l__aksr_label_tl ] }
}
{
\end{enumerate}
\int_compare:nT { \l__aksr_columns_tl > 1 }
{ \end{multicols} }
}
\tl_new:N \l__aksr_columns_tl
\tl_new:N \l__aksr_label_tl
\keys_define:nn { aksr/newenv }
{
columns .tl_set:N = \l__aksr_columns_tl,
columns .initial:n = 2,
label .tl_set:N = \l__aksr_label_tl,
label .initial = 1.,
}
\ExplSyntaxOff
\begin{document}
\begin{newenv}
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[columns=1]
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[label=i)]
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[label=(A),columns=3]
\item a
\item b
\item c
\item d
\item e
\item f
\end{newenv}
\end{document}
一旦我们掌握了它,它就相当简单了。唯一的微妙之处在于我们必须将参数传递给\begin{enumerate}
expanded,而不是标记列表变量,所以这\use:x
能起到作用。
这两个键只是将值存储在一个标记列表变量中以供以后使用。默认值只需在评估可选参数之前给出值即可建立newenv
。
您可以考虑领养enumitem
而不是enumerate
。
下面是一个不同的版本,它可以使用enumitem
并展示“未知”键的使用方法:
\documentclass{article}
\usepackage{enumitem,multicol,xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{newenv}{ O{} }
{
% clear the options passed to enumitem
\tl_clear:N \l__aksr_enumitem_tl
\keys_set:nn { aksr/newenv }
{
#1 % use the options
}
\int_compare:nT { \l__aksr_columns_tl > 1 } % more than one column
{ \begin{multicols}{ \l__aksr_columns_tl } }
% We must pass the optional argument expanded; we append
% the label key and value to the other possibly set options
\tl_put_right:Nn \l__aksr_enumitem_tl { label = }
\tl_put_right:NV \l__aksr_enumitem_tl \l__aksr_label_tl
\aksr_beginenum:V \l__aksr_enumitem_tl
}
{
\end{enumerate}
\int_compare:nT { \l__aksr_columns_tl > 1 }
{ \end{multicols} }
}
\cs_new_protected:Npn \aksr_beginenum:n #1
{
\begin{enumerate}[#1]
}
\cs_generate_variant:Nn \aksr_beginenum:n {V}
\tl_new:N \l__aksr_columns_tl
\tl_new:N \l__aksr_label_tl
\tl_new:N \l__aksr_enumitem_tl
\keys_define:nn { aksr/newenv }
{
columns .tl_set:N = \l__aksr_columns_tl,
columns .initial:n = 2,
label .tl_set:N = \l__aksr_label_tl,
label .initial:n = \arabic*.,
%% unknown keys will be passed to enumitem
unknown .code:n = \tl_put_right:Nx \l__aksr_enumitem_tl
{
\l_keys_key_tl % the key name
\tl_if_empty:nF { #1 } % the value, if not empty
{ = \exp_not:n { #1 } } , },
}
\ExplSyntaxOff
\begin{document}
\begin{newenv}
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[columns=1,noitemsep]
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[label=\roman*)]
\item a
\item b
\item c
\item d
\end{newenv}
\hrule
\begin{newenv}[label=(\alph*),columns=3]
\item a
\item b
\item c
\item d
\item e
\item f
\end{newenv}
\end{document}
答案3
尽管这个建议可能会受到谴责,但你可以对不同的可选项使用不同的分隔符。
\NewDocumentEnvironment{newenv}{ O{2} D<>{(a)} }
指定有两个可选参数,第一个是O
标准方括号可选类型,其默认值为以下括号组(此处2
)中的内容。第二个可选参数是D
(“D”限定)类型,其左分隔符<
、右分隔符>
为 ,默认值为以下括号组(此处 )中的内容(a)
。
\documentclass{article}
\usepackage{array}
\usepackage{multicol}
\usepackage{enumerate}
\usepackage{xparse}
\NewDocumentEnvironment{newenv}{ O{2} D<>{(a)} }
{\begin{multicols}{#1}\begin{enumerate}[#2]}
{\end{enumerate}\end{multicols}}
\begin{document}
\begin{newenv}[2]<i.>
\item a
\item b
\item c
\item d
\end{newenv}
\end{document}