У меня есть строка, разделенная запятыми. В ней я хочу получить каждый элемент и применить команду. У меня есть следующее, которое работает.
\documentclass[12pt]{article}
\usepackage[trim]{tokenizer}
\newcommand{\cadd}[1]{
\def\Source{#1}
\whiledo{\not\equal{\Source}{}}
{
\GetTokens{TokenOne}{TokenTwo}{\Source}
\textbf{\TokenOne}
\let\Source\TokenTwo
}
}
\begin{document}
\cadd{a,b,c}
\end{document}
Но я хотел бы иметь следующее
\documentclass[12pt]{article}
\usepackage[trim]{tokenizer}
\newcommand{\cadd}[1]{
\whiledo{\not\equal{#1}{}}
{
\GetTokens{TokenOne}{TokenTwo}{#1}
\textbf{\TokenOne}
\let\#1\TokenTwo
}
}
\begin{document}
\cadd{a,b,c}
\end{document}
Но \let\#1\TokenTwo
выдает ошибку. Как я могу использовать #1
с\let
решение1
#1
заменяется при первом вызове макроса. Если макрос\cadd
\newcommand{\cadd}[1]{
\whiledo{\not\equal{#1}{}}
{
\GetTokens{TokenOne}{TokenTwo}{#1}
\textbf{\TokenOne}
\let\#1\TokenTwo
}
}
называется \cadd{a,b,c}
, тогда он становится:
<space>
\whiledo{\not\equal{a,b,c}{}}<space>
{<space>
\GetTokens{TokenOne}{TokenTwo}{a,b,c}<space>
\textbf{\TokenOne}<space>
\let\#1\TokenTwo
}<space>
- Строка
\let\#1\TokenTwo
состоит из\let
присваивания\let\#=1
и\TokenTwo
.#1
заменяется только в макрорасширении первым аргументом. Имеется много пробелов (из-за конца строки):
- Первый игнорируется в вертикальном режиме, поскольку абзац еще не начался.
- Второй игнорируется, если
\whiledo
считывает тело цикла как неразделенный аргумент. - Третий и четвертый будут присутствовать в выводе.
- Последнее удалено из-за конца абзаца.
Пробелы в конце строки можно исключить, используя символ комментария, как показано в следующем примере.
Существует множество парсеров для списков, разделенных запятыми. Один из них предоставляется пакетом kvsetkeys
:
\documentclass[12pt]{article}
\usepackage{kvsetkeys}
\makeatletter
\newcommand{\cadd}[1]{%
\comma@parse{#1}{\caddentry}%
}
\newcommand*{\caddentry}[1]{%
\textbf{[#1]}%
}
\makeatother
\begin{document}
\cadd{a,b,c}
\cadd{ a , b , c }
\cadd{abc, def, ghi}
\cadd{{ with spaces }, {a b c}}
\end{document}
решение2
Heiko хорошо описал детали. Для полноты, решение с использованием функции отображения запятых LaTeX3\clist_map_inline:nn
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\NewDocumentCommand { \cadd } { m }
{ \clist_map_inline:nn {#1} { [ \textbf {##1} ] } }
\ExplSyntaxOff
\begin{document}
\cadd{a,b,c}
\cadd{ a , b , c }
\cadd{abc, def, ghi}
\cadd{{ with spaces }, {a b c}}
\end{document}
Основная идея во многом совпадает с ответом Хайко: вместо того, чтобы выполнять сопоставление вручную, используйте готовую команду, которая занимается поиском конца списка.