就我的目的而言,每行给出一个元素的列表(用 ASCII 分隔)很方便\n
。我想迭代这样的列表。像这样:
\begin{itemize}
\foreachperline{
foo
bar, baz
abcdef \emph{test}
}{\item TEST#1END}
\end{itemize}
这将产生:
测试foo结束
测试栏,bazEND
测试表def测试结尾
我希望\foreachperline
完全按照上面的方法工作,忽略第一个和最后一个换行符,但如果这样会变得混乱,下面的方法也可以
\foreachperline{foo
bar, baz
abcdef \emph{test}}{\item TEST#1END}
明确标记行尾也是可以接受的(优于选项 2,但不优于选项 1),如下所示
\foreachperline{
foo\\
bar, baz\\
abcdef \emph{test}\\
}{\item TEST#1END}
请注意,中没有空格,TEST#1END
但是根据行的内容,输出中有空格(参见bar
行)。
用作占位符不是必需的#1
。像这样的东西也可以。
\foreachperline{
foo
bar, baz
abcdef \emph{test}
}{\item TEST\placeholder{}END}
语法不一定非要是单个宏。类似这样的也可以。
\forthingy \i \in {...}{\item TEST\i{}END}
我该如何书写\foreachperline
,或者其他功能等效的书写?
答案1
使用换行符作为分隔符只会适得其反:大多数编辑对于如何组织用户输入都有自己的想法。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\foreachperline}{m}
{
\cs_set_protected:Nn \__spraff_per_line_do:n { #1 }
\group_begin:
\char_set_catcode_other:n { 13 }
\char_set_catcode_active:n { 32 }
\char_set_active_eq:nN { 32 } \c_space_token
\__spraff_per_line_go:n
}
\cs_new_protected:Nn \__spraff_per_line_go:n
{
\seq_set_split:Nfn \l__spraff_per_line_input_seq { \char_generate:nn { 13 } { 12 } } { #1 }
\seq_pop_left:NN \l__spraff_per_line_input_seq \l_tmpa_tl
\seq_pop_right:NN \l__spraff_per_line_input_seq \l_tmpa_tl
\seq_map_function:NN \l__spraff_per_line_input_seq \__spraff_per_line_do:n
\group_end:
}
\seq_new:N \l__spraff_per_line_input_seq
\cs_generate_variant:Nn \seq_set_split:Nnn { Nf }
\ExplSyntaxOff
\begin{document}
\begin{itemize}
\foreachperline{\item TEST#1END}{
foo
bar, baz
abcdef \emph{test}
}
\end{itemize}
\end{document}
不将三个空格压缩为一个吗?好吧,您知道 TeX 会忽略行首的空格,因此您无法获得它们,或者无法像往常一样处理它们。
哦,甚至不要尝试将其作为参数传递给另一个命令;特别是,不要嵌套。