Токенизировать и применить команду

Токенизировать и применить команду

У меня есть строка, разделенная запятыми. В ней я хочу получить каждый элемент и применить команду. У меня есть следующее, которое работает.

\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}

Основная идея во многом совпадает с ответом Хайко: вместо того, чтобы выполнять сопоставление вручную, используйте готовую команду, которая занимается поиском конца списка.

Связанный контент