我有一个逗号分隔的信息列表,由作者提供,作为文档的序言。然后我想使用这个列表,并且我想每行放一个列表中的项目。我的想法只是用换行符代替逗号。但是当我对元素进行格式化时,它不起作用。
我希望作者能够随意添加他喜欢的格式(或在词汇表中引用),而不会出现任何问题。
分数维:
\documentclass{article}
\usepackage{xstring}
\begin{document}
% In my case, the first argument is a command in the reality
\StrSubstitute{Test, Test2, Test3}{,}{\newline} % OK
\StrSubstitute{Test, \textit{Test2}, Test3}{,}{\newline} % NOK
\end{document}
答案1
要格式化用逗号分隔的项目列表或根据需要使用任何其他格式,您可以使用listofitems
:
\documentclass{article}
\usepackage{listofitems}
\setsepchar{,}
\readlist\foo{Test1,\textit{Test2},{\bfseries Test3},\LaTeX,Test4}
\renewcommand\showitemsmacro[1]{\qquad\textbullet\quad #1\par}
\begin{document}
\foo[1] made with \foo[4]:
\showitems\foo
End of the example.
\end{document}
或得到相同的结果:
\documentclass{article}
\usepackage{listofitems}
\setsepchar{,}
\readlist\foo{Test1,\textit{Test2},{\bfseries Test3},\LaTeX,Test4}
\begin{document}
\foo[1] made with \foo[4]:
\foreachitem\test\in\foo{\qquad\textbullet\quad \test\par}
End of the example.
\end{document}
答案2
这是旧版 LaTeX 的版本:
\documentclass{article}
\makeatletter
\newcommand\commatonewline[1]{%
\@for\user@tmp:=#1\do{\user@tmp\newline}%
}
\makeatother
\begin{document}
indentation is normal at start of paragraph
% In my case, the first argument is a command in the reality
\commatonewline{Test, Test2, Test3} % OK
\commatonewline{Test, \textit{Test2}, Test3} % OK, too
\end{document}
其他答案会告诉您使用现代 LaTeX(或使用自制循环,与旧的 LaTeX2e 相比可能具有优势)。
答案3
主要问题是xstring
尝试完全扩展其命令的参数。
下面介绍如何使用 进行操作expl3
。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\typesetlist}{m +O{} +m +O{}}
{
#2 % before
\exp_args:NV \clist_use:nn { #1 } { #3 }
#4
}
\ExplSyntaxOff
\newcommand{\listprovidedbytheauthor}{Test1,\textit{Test2},{\bfseries Test3},\LaTeX,Test4}
\begin{document}
\typesetlist{\listprovidedbytheauthor}[\begin{flushleft}]{\\}[\end{flushleft}]
\typesetlist{\listprovidedbytheauthor}[\noindent Keywords: ]{, }
\end{document}
如您所见,项目周围的括号被删除,如果输入错误\bfseries Test3
(带括号或不带括号),则可能会产生不良后果。为了避免此类输入错误,您可以使用两步方法:我们用逗号分隔列表,然后用括号将每个项目括起来。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\typesetlist}{m +O{} +m +O{}}
{
#2 % before
\clem_list_typeset:Vn #1 { #3 }
#4
}
\seq_new:N \l__clem_typeset_list_in_seq
\seq_new:N \l__clem_typeset_list_out_seq
\cs_new_protected:Nn \clem_list_typeset:nn
{
\seq_set_from_clist:Nn \l__clem_typeset_list_in_seq { #1 }
\seq_set_map:NNn \l__clem_typeset_list_out_seq \l__clem_typeset_list_in_seq { {##1} }
\seq_use:Nn \l__clem_typeset_list_out_seq { #2 }
}
\cs_generate_variant:Nn \clem_list_typeset:nn { V }
\ExplSyntaxOff
\newcommand{\listprovidedbytheauthor}{Test1,\textit{Test2},{\bfseries Test3},\LaTeX,Test4}
\begin{document}
\typesetlist{\listprovidedbytheauthor}[\begin{flushleft}]{\\}[\end{flushleft}]
\typesetlist{\listprovidedbytheauthor}[\noindent Keywords: ]{, }
\end{document}
答案4
如果你只是想处理列表以进行打印,则无需使用xstring
;etoolbox
提供列表处理功能:
\documentclass{article}
\usepackage{etoolbox}
\newcommand{\processlist}[2][,]{%
\def\itemdelim{\def\itemdelim{#1}}% Item delimiter delayed by one cycle (https://tex.stackexchange.com/a/89187/5764)
\renewcommand*{\do}[1]{\itemdelim##1}% How each item is processed
\docsvlist{#2}}% Process CSV list
\begin{document}
\setlength{\parindent}{0pt}% Just for this example
First list:
\processlist[\newline]{Test, Test2, Test3}
\hrulefill
Second list:
\processlist[\newline]{Test, \textit{Test2}, Test3}
\end{document}
LaTeX3 中也有列表解析器/处理器。以下内容部分取自xparse
文档并产生与上面相同的结果:
\documentclass{article}
\NewDocumentCommand{\nextitem}{ m }{ #1 \par}
\NewDocumentCommand{\processlist}{ > { \SplitList { , } } m }{%
\ProcessList{#1}{ \nextitem } }
\begin{document}
\setlength{\parindent}{0pt}% Just for this example
First list:
\processlist{Test, Test2, Test3}
\hrulefill
Second list:
\processlist{Test, \textit{Test2}, Test3}
\end{document}