
Considere el siguiente código proveniente deesterespuesta, donde agrega un prefijo a una palabra, solo si falta el prefijo.
\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}
PREGUNTA:¿Cómo hacer que funcione dado que necesito que el comando sea ampliable?
Respuesta1
Dada una función base expl3, puede generar una variante que procese uno o más argumentos antes de pasar los resultados a esa función. Por ejemplo, si una función tiene un especificador de argumento (el bit después de los dos puntos) n
, puede definir una variante que tenga o
(expandirohnce) o e
(expandirmiexhaustivamente) en lugar de n
. Luego simplemente utiliza la variante donde sea necesario.
En este caso, queremos variantes de dos funciones.
\cs_generate_variant:Nn \str_range:nnn { enn }
Esto asegura \str_range:enn
que existe. Esta variante expandirá el primer argumento antes de entregárselo a la función \str_range:nnn
para su procesamiento.
\cs_generate_variant:Nn \str_count:n { e }
Esto asegura \str_count:e
que existe, lo que expande su único argumento antes de pasarlo a \str_count:n
.
Entonces podemos usar estas variantes tal como lo haríamos con las funciones base.
\NewExpandableDocumentCommand { \forcebeginwith } { m m }
{
\str_if_eq:eeTF {#2} { \str_range:enn {#1} { 1 } { \str_count:e {#2} } }
{#1}
{ #2#1 }
}
Código completo:
\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}
Respuesta2
Aquí hay un ejemplo:
\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}
Respuesta3
Un mejor estilo de programación es definir el comando a nivel de usuario en términos de una función interna.
\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}
Como ves \vincent_forcebeginwith:nn
está definido, pero en el comando a nivel de usuario usamos una variante del mismo que expande completamente sus argumentos antes de entregárselos a \vincent_forcebeginwith:nn
.