Для моих целей удобно иметь список, заданный одним элементом на каждой строке (разделенным ASCII \n
). Я хочу перебрать такой список. Что-то вроде этого:
\begin{itemize}
\foreachperline{
foo
bar, baz
abcdef \emph{test}
}{\item TEST#1END}
\end{itemize}
Это даст:
TESTfooEND
ТЕСТ-бар, базаEND
TESTabcdefтестКОНЕЦ
Я бы предпочел, чтобы for \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 игнорирует пробелы в начале строк, так что либо вы их не получите, либо их нельзя будет обработать как обычно.
Ой, даже не пытайтесь использовать это в качестве аргумента для другой команды; в частности, никакой вложенности.