Un comando expandible que agrega una cadena a un argumento si falta la cadena

Un comando expandible que agrega una cadena a un argumento si falta la cadena

Me gustaría escribir un comando expandible que agregue una cadena S1 al comienzo de otra cadena S2 si S2 no comienza con S1 para garantizar que mi cadena siempre comience con S1.

Actualmente tengo este código que se basa en el paquete xstring

\NewDocumentCommand\forcebeginwith{m m}{%
    \edef\expandedstring{#1}%
    \edef\expandedbeginning{#2}%
    \IfBeginWith{
        \expandedstring % String
    }{
        \expandedbeginning % Beginning
    }{
        \expandedstring % String
    }{
        \expandedbeginning\expandedstring % Beginning + String
    }
}

Por ejemplo :

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

Pregunta:Me gustaría convertir este comando en un comando expandible NewExpandableDocumentCommand, pero no tengo idea de cómo hacerlo (me gustaría que el código resultante funcione en versiones de látex que datan de, digamos, hace 5 años, así que me gustaría evitar los súper recientes comandos/paquetes).

Respuesta1

El comando \forcebeginwithse define con \NewExpandableDocumentCommand. La prueba se realiza con \str_if_eq:eeTF. El comando \forcebeginwithse puede utilizar en el interior \edefcomo en el siguiente ejemplo.

ingrese la descripción de la imagen aquí

\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
\begin{document}
\forcebeginwith{fancycolor}{fancy}\\% fancycolor
\forcebeginwith{color}{fancy}\\% fancycolor
\edef\testA{\forcebeginwith{LaTeX}{La}}\testA\\
\edef\testB{\forcebeginwith{TeX}{La}}\testB
\end{document}

Respuesta2

Si usas pdflatex, entonces puedes hacerlo con

\documentclass{article}

\newcommand{\forcebeginwith}[2]{%
  \ifnum\pdfmatch{^#2}{#1}=0 #2\fi#1%
}

\begin{document}

\forcebeginwith{fancycolor}{fancy}% fancycolor

\forcebeginwith{color}{fancy}% fancycolor

\edef\testA{\forcebeginwith{LaTeX}{La}}\testA

\edef\testB{\forcebeginwith{TeX}{La}}\testB

\end{document}

ingrese la descripción de la imagen aquí

Lo probé hasta TeX Live 2012.

Respuesta3

Usando sólo primitivas TeX, el código debería ser así:

\def\forcebeginwith#1#2{\fbwA .#1\end .#2\end{#1}{#2}}
\def\fbwA #1#2\end #3#4\end #5#6{%
   \ifx #1#3%
      \ifx \end#4\end #5% S2 is included at the start of S1, print S1 only
      \else 
          \ifx \end#2\end {#5} shorter than {#6}, something wrong%
          \else \fbwB {#2\end #4\end {#5}{#6}}%
          \fi
      \fi
   \else #6#5% S2 isn't inluded at the start of S1, print S2S1.
   \fi
}
\def\fbwB #1\fi\fi#2\fi{\fi\fi\fi \fbwA #1}

% test:

\message{\forcebeginwith{fancycolor}{fancy}}

\message{\forcebeginwith{color}{fancy}}

\bye

Tenga en cuenta que TeX no funciona con "cadenas", solo hay listas de tokens.

Respuesta4

La siguiente solución basada en LuaLaTeX define una macro de usuario llamada \forcebeginwith. Debería funcionar con versiones del kernel LaTeX que tienen más de una década de antigüedad, ya que las propiedades de la \directluaprimitiva no han cambiado realmente desde su primera aparición. Porque \directluaes ampliable, también lo es \forcebeginwith. Tenga en cuenta que los argumentos de \forcebeginwithno necesitan estar codificados en ASCII; en cambio, se les permite estar codificados en UTF8.

ingrese la descripción de la imagen aquí

% !TEX program = lualatex
\documentclass{article} % or some other suitable document class
\directlua{% Define the Lua function 'forcebeginwith':
   function forcebeginwith ( s1 , s2 )
      if unicode.utf8.sub ( s1 , 1 , unicode.utf8.len ( s2 ) ) == s2 then
         return ( s1 )
      else
         return ( s2..s1 )
      end
   end
}
\newcommand\forcebeginwith[2]{%
   \directlua{ tex.sprint ( forcebeginwith ( "#1" , "#2" ) ) }}

\newcommand\Za{color}
\newcommand\Zb{fancy}

\begin{document}
\obeylines % just for this document
\forcebeginwith{fancycolor}{fancy}
\forcebeginwith{color}{fancy}

\smallskip
% Demonstrate that '\forcebeginwith' is expandable
\forcebeginwith{\Zb\Za}{\Zb}
\forcebeginwith{\Za}{\Zb}
\end{document}

información relacionada