Comando tokenizar e aplicar

Comando tokenizar e aplicar

Eu tenho uma string separada por vírgulas. Com isso quero pegar cada elemento e aplicar um comando. Eu tenho o seguinte, que funciona.

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

Mas eu gostaria de ter o seguinte

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

Mas \let\#1\TokenTwoestá dando um erro. Como posso usar #1com\let

Responder1

#1é substituído na primeira chamada da macro. Se macro\cadd

\newcommand{\cadd}[1]{
    \whiledo{\not\equal{#1}{}}
    {
        \GetTokens{TokenOne}{TokenTwo}{#1}
        \textbf{\TokenOne}
        \let\#1\TokenTwo
    }
}

é chamado como \cadd{a,b,c}, então se torna:

<space>
\whiledo{\not\equal{a,b,c}{}}<space>
{<space>
  \GetTokens{TokenOne}{TokenTwo}{a,b,c}<space>
  \textbf{\TokenOne}<space>
  \let\#1\TokenTwo
}<space>
  • A linha \let\#1\TokenTwoconsiste na \letatribuição \let\#=1e \TokenTwo. #1só é substituído na expansão macro pelo primeiro argumento.
  • Existem muitos tokens de espaço (causados ​​pelo final da linha):

    • O primeiro é ignorado no modo vertical, pois o parágrafo ainda não começou.
    • O segundo é ignorado se \whiledoler o corpo do loop como argumento indelimitado.
    • O terceiro e o quarto estarão presentes na saída.
    • O último é removido por causa do final do parágrafo.

    Os tokens de espaço no final da linha podem ser evitados usando o caractere de comentário, como visto no exemplo a seguir.

Existem muitos analisadores para listas separadas por vírgulas. Um deles é fornecido por pacote 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}

Resultado

Responder2

Heiko cobriu bem os detalhes aqui. Para completar, uma solução usando a função de mapeamento de lista de vírgulas 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}

A ideia subjacente é praticamente a mesma da resposta de Heiko: em vez de ter que fazer o mapeamento manualmente, use um comando pré-construído que trata de encontrar o final da lista.

informação relacionada