我想要生成以逗号分隔的列表,例如“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}