Befehl tokenisieren und anwenden

Befehl tokenisieren und anwenden

Ich habe eine durch Kommas getrennte Zeichenfolge. Darauf möchte ich jedes Element abrufen und einen Befehl anwenden. Ich habe Folgendes, was funktioniert.

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

Aber ich hätte gerne folgendes

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

Aber es \let\#1\TokenTwowird ein Fehler ausgegeben. Wie kann ich #1mit\let

Antwort1

#1wird beim ersten Aufruf des Makros ersetzt. Wenn Makro\cadd

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

heißt \cadd{a,b,c}, dann wird es zu:

<space>
\whiledo{\not\equal{a,b,c}{}}<space>
{<space>
  \GetTokens{TokenOne}{TokenTwo}{a,b,c}<space>
  \textbf{\TokenOne}<space>
  \let\#1\TokenTwo
}<space>
  • Die Zeile \let\#1\TokenTwobesteht aus der \letZuweisung \let\#=1und \TokenTwo. #1wird nur bei der Makroerweiterung durch das erste Argument ersetzt.
  • Es gibt viele Leerzeichen (verursacht durch das Zeilenende):

    • Der erste wird im vertikalen Modus ignoriert, da der Absatz noch nicht begonnen hat.
    • Das zweite wird ignoriert, wenn \whiledoder Schleifenkörper als nicht begrenztes Argument gelesen wird.
    • Die dritte und vierte Zahl werden in der Ausgabe vorhanden sein.
    • Der Letzte wird wegen des Absatzendes entfernt.

    Leerzeichen am Zeilenende können durch die Verwendung von Kommentarzeichen vermieden werden, wie im folgenden Beispiel zu sehen ist.

Es gibt viele Parser für durch Kommas getrennte Listen. Einer davon wird vom Paket bereitgestellt 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}

Ergebnis

Antwort2

Heiko hat die Details hier gut beschrieben. Der Vollständigkeit halber eine Lösung mit der LaTeX3-Kommalisten-Mapping-Funktion\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}

Die zugrunde liegende Idee ist weitgehend dieselbe wie in Heikos Antwort: Anstatt die Zuordnung manuell vornehmen zu müssen, verwenden Sie einen vorgefertigten Befehl, der das Ende der Liste findet.

verwandte Informationen