我想将逗号分隔列表中的自动标点符号与这个答案使用 中的列表处理etoolbox
。但是,我没有得到任何输出。这里出了什么问题?
\documentclass{article}
\usepackage{xparse,environ,xspace,etoolbox}
\ExplSyntaxOn
\NewEnviron{commalist}[1][\space]{\spence_comma_list:V \BODY #1}
\seq_new:N \l_spence_items_seq
\cs_new_protected:Npn \spence_comma_list:n #1
{
\seq_set_split:Nnn \l_spence_items_seq { \item } { #1 }
\seq_pop_left:NN \l_spence_items_seq \l_tmpa_tl % we have an empty element at the beginning
\seq_use:Nnnn \l_spence_items_seq { ~ and ~ } { , ~ } { , ~ and ~ }
}
\cs_generate_variant:Nn \spence_comma_list:n { V }
\ExplSyntaxOff
\begin{document}
The new list works:
\begin{commalist}
\item a
\item b
\item c
\end{commalist}
List processing from etoolbox works:
\forcsvlist{;}{a,b,c}
The combination does not work:
\begin{commalist}
\forcsvlist{\item}{a,b,c}
\end{commalist}
\end{document}
答案1
我不确定这种语法是否支持 OP 想要实现的目标,但问题是,通常情况下,扩展。
\documentclass{article}
\usepackage{xparse,environ,xspace,etoolbox}
\ExplSyntaxOn
\NewEnviron{commalist}[1][\space]{\spence_comma_list:V \BODY #1}
\seq_new:N \l_spence_items_seq
\cs_new_protected:Npn \spence_comma_list:n #1
{
\seq_set_split:Nnn \l_spence_items_seq { \item } { #1 }
\seq_pop_left:NN \l_spence_items_seq \l_tmpa_tl % we have an empty element at the beginning
\seq_use:Nnnn \l_spence_items_seq { ~ and ~ } { , ~ } { , ~ and ~ }
}
\cs_generate_variant:Nn \spence_comma_list:n { V }
\ExplSyntaxOff
\begin{document}
\def\tmp{\begin{commalist}}
\edef\z{\forcsvlist{\noexpand\item}{a,b,c}}
\expandafter\tmp\z
\end{commalist}
\end{document}
然而,如果一个人没有强制要使用该commalist
环境,其他方法更简单:
\documentclass{article}
\usepackage{listofitems}
\newcommand\oxcomma[1]{%
\readlist*\mylist{#1}%
\foreachitem\z\in\mylist[]{%
\ifnum\zcnt=1\else
\ifnum\listlen\mylist[]<3\else,\fi\ \fi
\ifnum\zcnt=\listlen\mylist[]\relax and \fi
\z
}
}
\newcommand\nooxcomma[1]{%
\readlist*\mylist{#1}%
\foreachitem\z\in\mylist[]{%
\ifnum\zcnt=1\else
\ifnum\zcnt=\listlen\mylist[]\relax\ and \else, \fi
\fi
\z
}
}
\begin{document}
\noindent OPTION A:\\ % OXFORD COMMA
\oxcomma{A, B}\\
\oxcomma{A, B, C}
\medskip\noindent OPTION B:\\
\nooxcomma{A, B}\\
\nooxcomma{A, B, C}
\end{document}
答案2
这是一种使用b
参数类型\NewDocumentEnvironment
(因此不需要environ
包)和\unexpanded
e-TeX 原语的方法,以免过早扩展内容(a,b,c
示例中为无害)。
\documentclass{article}
% xspace not needed
% xparse not needed if the LaTeX kernel is from 2020-10-01 or later
\usepackage{xparse,etoolbox}
\ExplSyntaxOn
\NewDocumentEnvironment { commalist } { +b }
{ \spence_comma_list:n {#1} }
{ }
\seq_new:N \l__spence_items_seq
% From egreg: <https://tex.stackexchange.com/a/62620/73317>
\cs_new_protected:Npn \spence_comma_list:n #1
{
\seq_set_split:Nnn \l__spence_items_seq { \item } { #1 }
% We have an empty element at the beginning:
\seq_pop_left:NN \l__spence_items_seq \l_tmpa_tl
\seq_use:Nnnn \l__spence_items_seq { ~ and ~ } { , ~ } { , ~ and ~ }
}
\ExplSyntaxOff
\begin{document}
The combination works:
\begingroup
\renewcommand{\do}[1]{\noexpand\item \unexpanded{#1}}%
\edef\zzz{%
\endgroup
\noexpand\begin{commalist}
\docsvlist{a,b,c}%
}\zzz
\end{commalist}.
\end{document}