逗号分隔列表

逗号分隔列表

我想要生成以逗号分隔的列表,例如“a、b、c、d”或“a、b、c 和 d”。

要求:

  • 在 Latex 源代码中,源代码的每一行都应该包含一个列表元素,以及尽可能少的附加标记。

  • 通过改变源代码行的顺序,应该可以轻松地重新排序条目。

例如,我可以简单地像这样编写列表元素:

a,
b,
c, and
d.

这(几乎)可以满足第一个要求,但第二个要求却无法满足。每当我重新排序条目(或只是添加新条目)时,我都必须记住修正标点符号。这听起来微不足道,但令人惊讶的是,很容易忘记用逗号替换句号,而且很难发现错误。而且我有一个较长的 Latex 文档,其中混合了其他内容和此类列表,因此使用外部脚本生成适当的 Latex 代码并不方便——我真的在寻找一种尽可能易于长期维护的东西。

我真的不知道什么样的界面才合适;因此这也可以看作是一个界面设计挑战。也许是这样的:

xxx\begin{commasep}[and]
    \item a
    \item b
    \item c
    \item d
\end{commasep}yyy

将产生:

xxxa, b, c, and dyyy

(注意:“d”后没有空格,以便我可以在列表后添加适当的标点符号。)

我想知道是否paralist可以进行调整来产生我想要的东西?

答案1

这里有一些宏,它们将行作为宏参数读取。它的灵感来自这个问题。可以将“界面”改为 LaTeX 环境,但 TeX 语法(不带\begin\end)更简单。

\documentclass{article}

\makeatletter
\newcommand*\commasep[2][, ]{%
   \begingroup
   \def\commasepsep{#1\space}%  store separator e.g. ','
   \def\commasependsep{#2\space}%  store last separator e.g. 'and'
   \@commasep
}
\newcommand*\@commasep[1][.]{%
   \def\commasepend{#1}%  store end marker e.g. '.'
   \@ifnextchar\endcommasep{}{%  check for empty list
     \catcode\endlinechar\active%  make end-of-line active
     \commasepfirstelement%  read first element
   }%
}%
\begingroup
\catcode\endlinechar\active%
% The `~` character represents the end-of-line character in the
% code below:
\lccode`\~=\endlinechar%
\lowercase{%
% Read first element
\gdef\commasepfirstelement#1~}{%
    #1%
    \@ifnextchar\endcommasep{%
      \commasepend% remove this if you don't want one with only one element
    }{%
      \commasepelement% no comma here!
    }%
}%
\lowercase{%
\endgroup%
% Read all other elements
\gdef\commasepelement#1~}{%
    \@ifnextchar\endcommasep{% Stop at `\endcommasep`
      \commasependsep#1\commasepend%
    }{%
      \commasepsep#1\commasepelement%
    }%
}%
\def\endcommasep{%
  \@gobble{endcommasep}% be unique (for `\@ifnextchar`) 
  \endgroup
}%
\makeatother

\begin{document}

% Usage: \commasep[<separator>]{<last separator>}[<end marker>]
xxx\commasep[,]{and}[.]
a
b
c
d
\endcommasep yyy

xxx\commasep{and}
a
\endcommasep yyy

xxx\commasep{and}
\endcommasep yyy

xxx\commasep{or}
a
b
\endcommasep yyy

\end{document}

另请注意parselines可以使用的包。但是,它不支持对最后一个条目进行不同的处理。不过,对于对这种解析感兴趣的人来说,它的代码可能值得一读。

答案2

项目以 分隔,,,列表以 结尾..。实际上,每个项目,,后面都应该有一个空格或行尾(不带%)。对于非常长的列表(几个段落?),这可能会变慢,因为我们在每一步都将整个列表作为参数。

(请注意,我用“声明”每个命令,以\newcommand\command{}确保在使用定义它们之前它们不存在\def。)

整个构造依赖于通用宏,用于在列表元素之间插入所需的分隔符,并可以进行一些配置。例如,参见\commasepitem下文,它将列表写入itemize环境中。

\documentclass{article}    

\makeatletter
% #1 at the beginning
% #2 between each element
% #3 between the last two
% #4 after the last
% #5 is the first item
\newcommand*\commasep@generic{}
\def\commasep@generic#1#2#3#4 #5,, {#1#5\commasep@next{#2}{#3}{#4}}

\newcommand*\commasep@next{}
\def\commasep@next#1#2#3#4,, #5..{%
  % #1 is the list separator,
  % #2 is the last list separator,
  % #3 is the end text
  % #4 the item, 
  % #5 the rest.
  \expandafter\ifx\expandafter a\detokenize{#5}a% test if #3 is empty.
  \expandafter\@firstoftwo
  \else
  \expandafter\@secondoftwo
  \fi
  {#2#4#3}%
  {#1#4\commasep@next{#1}{#2}{#3}#5..}%
}%

\newcommand*\commasep[1]{\commasep@generic{}{, }{, #1 }{\ignorespaces}}
\newcommand*\commasepitem{%
  \commasep@generic{\begin{itemize}\item}{\item}{\item[(last)]}{\end{itemize}} }
\makeatother



\begin{document}

xx\commasep{and}
    a,,
    b,,
    c,,
    d,,
    ..
yyyy

xxx\commasepitem
    ``London bridge is falling down'' is much more frightening!,,
    c,,
    ``Mary had a little lamb, little lamb, little lamb'' is a nice
    little song that my mom used to sing,,
    d,,
    ..
yyyy

\end{document}

答案3

在...的帮助下枚举项有可能的。

\usepackage[inline]{enumitem}

\begin{itemize*}[label={}, itemjoin={,}, itemjoin*={, and}]
  \item one
  \item two
  \item three
\end{itemize*}

输出:

输出

答案4

具有灵活的界面来设置分隔符:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\commasep}{O{}m}
 {
  \group_begin:
  \jukka_commasep:nn { #1 } { #2 }
  \group_end:
  \ignorespaces
 }

\NewDocumentCommand{\commasepsetup}{m}
 {
  \keys_set:nn { jukka/commasep } { #1 }
 }

\cs_new_protected:Nn \jukka_commasep:nn
 {
  \keys_set:nn { jukka/commasep } { #1 }
  \seq_set_split:Nnn \l__jukka_commasep_seq { \\ } { #2 }
  \str_if_eq_x:nnT { } { \seq_item:Nn \l__jukka_commasep_seq { -1 } }
   {
    \seq_pop_right:NN \l__jukka_commasep_seq \l_tmpa_tl
   }
  \seq_use:NVVV \l__jukka_commasep_seq
   \l__jukka_commasep_two_tl
   \l__jukka_commasep_more_tl
   \l__jukka_commasep_last_tl
 }

\cs_generate_variant:Nn \seq_use:Nnnn { NVVV }

\keys_define:nn { jukka/commasep }
 {
  two  .tl_set:N = \l__jukka_commasep_two_tl,
  more .tl_set:N = \l__jukka_commasep_more_tl,
  last .tl_set:N = \l__jukka_commasep_last_tl,
  two  .initial:n = { ~and~ },
  more .initial:n = { ,~ },
  last .initial:n = { ,~and~ },
 }

\ExplSyntaxOff

\begin{document}

xxx\commasep{
 a \\
}yyy

xxx\commasep{
 a \\
 b \\
}yyy

xxx\commasep{
 a \\
 b \\
 c \\
 d \\
}yyy

\commasepsetup{
  two=+,
  more=-,
  last=-,
}

xxx\commasep{
 a \\
}yyy

xxx\commasep{
 a \\
 b \\
}yyy

xxx\commasep{
 a \\
 b \\
 c \\
 d \\
}yyy

\end{document}

在此处输入图片描述

相关内容