逗号分隔列表环境和 etoolbox

逗号分隔列表环境和 etoolbox

我想将逗号分隔列表中的自动标点符号与这个答案使用 中的列表处理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包)和\unexpandede-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}

在此处输入图片描述

相关内容