Problem mit einem Befehl, der Wörter nur bei Bedarf voranstellt, wenn die Argumente über Makros bereitgestellt werden

Problem mit einem Befehl, der Wörter nur bei Bedarf voranstellt, wenn die Argumente über Makros bereitgestellt werden

Betrachten Sie den folgenden Code vonDasAntwort, bei der einem Wort nur dann ein Präfix hinzugefügt wird, wenn das Präfix fehlt.

\documentclass[border=6pt,varwidth]{standalone}
\ExplSyntaxOn
\NewExpandableDocumentCommand { \forcebeginwith } { m m }
  {
    \str_if_eq:eeTF {#2} { \str_range:nnn {#1} { 1 } { \str_count:n {#2} } }
      {#1}
      { #2#1 }
  }
\ExplSyntaxOff

\newcommand{\mystringa}{fancycolor}
\newcommand{\mystringb}{\mystringa}
\newcommand{\mystringc}{\mystringb}

\newcommand{\prefixa}{fancy}
\newcommand{\prefixb}{\prefixa}
\newcommand{\prefixc}{\prefixb}

\begin{document}
\forcebeginwith{fancycolor}{fancy}    \\% OK: fancycolor
\forcebeginwith{color}{fancy}         \\% OK: fancycolor
\forcebeginwith{\mystringc}{\prefixc} \\% NOT WORKING: fancyfancycolor
\end{document}

FRAGE:Wie kann ich es zum Laufen bringen, wenn der Befehl erweiterbar sein muss?

Antwort1

Bei einer expl3-Basisfunktion können Sie eine Variante generieren, die ein oder mehrere Argumente verarbeitet, bevor die Ergebnisse an diese Funktion übergeben werden. Wenn eine Funktion beispielsweise einen Argumentspezifizierer (das Bit nach dem Doppelpunkt) hat n, können Sie eine Variante definieren, die o(expandÖnce) oder e(erweiterntxmutfully) anstelle von n. Dann verwenden Sie einfach die Variante, wo immer es erforderlich ist.

In diesem Fall wollen wir Varianten von zwei Funktionen

\cs_generate_variant:Nn \str_range:nnn { enn }

Dies stellt sicher, \str_range:enndass es existiert. Diese Variante erweitert das erste Argument, bevor es \str_range:nnnzur Verarbeitung an die Funktion übergeben wird.

\cs_generate_variant:Nn \str_count:n { e }

Dadurch wird sichergestellt \str_count:e, dass exists, das sein einziges Argument erweitert, bevor es an übergeben wird \str_count:n.

Dann können wir diese Varianten genauso verwenden wie die Basisfunktionen

\NewExpandableDocumentCommand { \forcebeginwith } { m m }
  {
    \str_if_eq:eeTF {#2} { \str_range:enn {#1} { 1 } { \str_count:e {#2} } }
      {#1}
      { #2#1 }
  }

Varianten erweitern Argumente vor der Verarbeitung, so dass alle drei Zeilen zum gleichen Ergebnis führen

Vollständiger Code:

\documentclass[border=6pt,varwidth]{standalone}
\ExplSyntaxOn
\cs_generate_variant:Nn \str_range:nnn { enn }
\cs_generate_variant:Nn \str_count:n { e }
\NewExpandableDocumentCommand { \forcebeginwith } { m m }
  {
    \str_if_eq:eeTF {#2} { \str_range:enn {#1} { 1 } { \str_count:e {#2} } }
      {#1}
      { #2#1 }
  }
\ExplSyntaxOff

\newcommand{\mystringa}{fancycolor}
\newcommand{\mystringb}{\mystringa}
\newcommand{\mystringc}{\mystringb}

\newcommand{\prefixa}{fancy}
\newcommand{\prefixb}{\prefixa}
\newcommand{\prefixc}{\prefixb}

\begin{document}
\forcebeginwith{fancycolor}{fancy}    \par% OK: fancycolor
\forcebeginwith{color}{fancy}         \par% OK: fancycolor
\forcebeginwith{\mystringc}{\prefixc} \par% NOT WORKING: fancyfancycolor
\end{document}

Antwort2

Hier ist ein Beispiel:

\documentclass[border=6pt,varwidth]{standalone}
\ExplSyntaxOn
\cs_generate_variant:Nn \str_range:nnn  { enn }
\NewExpandableDocumentCommand { \forcebeginwith } { m m }
  {
    \str_if_eq:eeTF {#2} { \str_range:enn {#1} { 1 } { \str_count:e {#2} } }
      {#1}
      { #2#1 }
  }
\ExplSyntaxOff

\newcommand{\mystringa}{fancycolor}
\newcommand{\mystringb}{\mystringa}
\newcommand{\mystringc}{\mystringb}

\newcommand{\prefixa}{fancy}
\newcommand{\prefixb}{\prefixa}
\newcommand{\prefixc}{\prefixb}

\begin{document}
\forcebeginwith{fancycolor}{fancy}    \\% OK: fancycolor
\forcebeginwith{color}{fancy}         \\% OK: fancycolor
\forcebeginwith{\mystringc}{\prefixc} \\% NOT WORKING: fancyfancycolor
\end{document}

Antwort3

Ein besserer Programmierstil besteht darin, den Befehl auf Benutzerebene als interne Funktion zu definieren.

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand { \forcebeginwith } { m m }
 {
  \vincent_forcebeginwith:ee { #1 } { #2 }
 }
\cs_new:Nn \vincent_forcebeginwith:nn
 {
  \str_if_eq:eeF {#2} { \str_range:nnn {#1} { 1 } { \str_count:n {#2} } } { #2 }
  #1
 }
\cs_generate_variant:Nn \vincent_forcebeginwith:nn { ee }

\ExplSyntaxOff

\newcommand{\mystringa}{fancycolor}
\newcommand{\mystringb}{\mystringa}
\newcommand{\mystringc}{\mystringb}

\newcommand{\prefixa}{fancy}
\newcommand{\prefixb}{\prefixa}
\newcommand{\prefixc}{\prefixb}

\begin{document}

\forcebeginwith{fancycolor}{fancy}    % OK: fancycolor

\forcebeginwith{color}{fancy}         % OK: fancycolor

\forcebeginwith{\mystringc}{\prefixc} % OK: fancycolor

\end{document}

Wie Sie sehen \vincent_forcebeginwith:nn, ist definiert, aber im Befehl auf Benutzerebene verwenden wir eine Variante davon, die ihre Argumente vollständig erweitert, bevor sie an übergeben wird \vincent_forcebeginwith:nn.

Bildbeschreibung hier eingeben

verwandte Informationen