Dividir cadena en caracteres y fusionar con formato

Dividir cadena en caracteres y fusionar con formato

¿Cómo puedo crear una macro?

\split{ABC}

que produce

ingrese la descripción de la imagen aquí

donde el formateo de los caracteres se realiza con otra macro, es decir

\formatchar{A}

dónde

\def\formatchar#1{{\color{red}#1}}

¿Para cualquier longitud de cuerda?

Intenté modificar el código en Dividir una cadena de caracteres n por n

\documentclass{article}
\usepackage{xstring}

\def\split#1#2{%
    \StrSplit{#2}{1}\tempa\tempb
    x%
    \tempa\let\tempa\empty
    \unless\ifx\tempb\empty\def\tempa{|\split{1}\tempb}\fi
    y%
    \tempa
}

\begin{document}
\split{1}{ABCD}
\end{document}

Y obtengo x e y antes y después (ya que no pude limitar con un comando y }) pero no puedo formatearlo correctamente. También me gustaría evitar el {1} ​​en la llamada y usar

\split{ABCD}

solo. Siempre son divisiones de 1 carácter.

¡Cualquier ayuda es muy apreciada!

Respuesta1

Si no se garantiza que su entrada sea "solo ASCII", \seq_set_split:Nnnes posible que un enfoque no funcione.

Cambié el nombre a \splitcharsporque \splitestá ocupado por amsmath.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xcolor}

\NewDocumentCommand{\formatchar}{m}{%
  \textcolor{red!90!yellow}{#1}% <--- or whatever you like
}

\ExplSyntaxOn

\NewDocumentCommand{\splitchars}{O{|}m}
 {% #1 = optional separator, default |
  % #2 = text to split
  \mflxvii_split:nn { #1 } { #2 }
 }

\seq_new:N \l__mflxvii_split_items_seq

\cs_new_protected:Nn \mflxvii_split:nn
 {
  \seq_clear:N \l__mflxvii_split_items_seq
  \text_map_inline:nn { #2 }
   {
    \seq_put_right:Nn \l__mflxvii_split_items_seq { \formatchar{##1} }
   }
  \seq_use:Nn \l__mflxvii_split_items_seq { #1 }
 }

\ExplSyntaxOff

\begin{document}

\splitchars{ABC}

\splitchars[--]{ABC}

\splitchars{ábç}

\splitchars{ÅÄÖ}

\end{document}

ingrese la descripción de la imagen aquí

Para obtener un resultado similar a una lista, aquí hay una extensión que permite un separador diferente entre los dos últimos elementos.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xcolor}

\NewDocumentCommand{\formatchar}{m}{%
  \textcolor{red!90!yellow}{#1}% <--- or whatever you like
}

\ExplSyntaxOn

\NewDocumentCommand{\splitchars}{O{|}O{#1}m}
 {% #1 = optional separator, default |
  % #2 = optional separator between last two
  % #3 = text to split
  \mflxvii_split:nnn { #1 } { #2 } { #3 }
 }

\seq_new:N \l__mflxvii_split_items_seq

\cs_new_protected:Nn \mflxvii_split:nnn
 {
  \seq_clear:N \l__mflxvii_split_items_seq
  \text_map_inline:nn { #3 }
   {
    \seq_put_right:Nn \l__mflxvii_split_items_seq { \formatchar{##1} }
   }
  \seq_use:Nnnn \l__mflxvii_split_items_seq { #2 } { #1 } { #2 }
 }

\ExplSyntaxOff

\begin{document}

\splitchars{ABC}

\splitchars[--]{ABC}

\splitchars{ábç}

\splitchars{ÅÄÖ}

\splitchars[, ][ and ]{ÅÄÖ}

\splitchars[, ][ and ]{ÅÄ}

\end{document}

ingrese la descripción de la imagen aquí

Respuesta2

Aquí hay una solución basada en LuaLaTeX, que utiliza las funciones integradas de gsubLua sub. En realidad, el código utiliza versiones de funciones gsuby subque pueden manejar caracteres codificados en utf8 directamente.

La macro principal a nivel de usuario se llama \splitstringen lugar de \split, porque lamatemáticasEl paquete define un entorno llamado splitjunto con macros llamadas \splity \endsplit.

Observe que (a) el argumento de \splitstringpuede contener espacios en blanco y (b) formatcharse implementa como una función Lua en lugar de como una macro LaTeX.

ingrese la descripción de la imagen aquí

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{xcolor}  % for '\textcolor' macro

% Lua-side code
\directlua{
  function formatchar ( c )
     return ( '\\textcolor{red}{\\textbf{' .. c .. '}}|' )
  end
  function split ( s )
     s = unicode.utf8.gsub ( s , '.' , formatchar )
     return ( unicode.utf8.sub ( s , 1 , -2 ) ) % delete final '|'
  end
}
% LaTeX-side code
\newcommand\splitstring[1]{\directlua{tex.sprint(split('#1'))}}

\begin{document}
\obeylines % just for this example
\splitstring{ABC}
\splitstring{123abc}
\splitstring{Hello World}
\end{document}

Respuesta3

Aquí está mi intento de solución usando ExplSyntax:

\documentclass{article}
\usepackage{xcolor}

\ExplSyntaxOn
\seq_new:N \l__my_split_seq
\NewDocumentCommand { \split } { m } {  \__my_split:n { #1 }  }
\cs_new_protected:Npn \__my_split:n #1
{
  \seq_set_split:Nnn \l__my_split_seq {} { #1 }
  \seq_set_map:NNn \l__my_split_seq \l__my_split_seq
  {  \__my_split_fn:n { ##1 }  }
  % \seq_log:N \l__my_split_seq
  \seq_use:Nn \l__my_split_seq { | }
}
\cs_new_protected:Npn \__my_split_fn:n #1 {   {  \color { red } #1  }   }
\ExplSyntaxOff

\begin{document}

\split{ABCD}

\split{1234}

\end{document}

ingrese la descripción de la imagen aquí

Respuesta4

Como no se ofrecen soluciones LaTeX2e, les doy una aquí. Utilizo un ciclo de token para tomar caracteres uno por uno del argumento. Esta solución supone que el argumento no tiene macros ni grupos. Los omití porque no se dio ninguna orientación sobre cómo deben manejarse, aunque se pueden manejar según sea necesario.

Si es necesario manejar caracteres Unicode, la compilación debe realizarse en xelatex o lualatex.

\documentclass{article}
\usepackage{tokcycle,xcolor}
\newcommand\formatchar[1]{\textcolor{red}{#1}}
\def\split#1{%
  \tokencycle{\formatchar{##1}\splitchar}
  {}{}{##1\splitchar}#1\endtokencycle}
\newcommand\splitchar{\tcpeek\z\ifx\empty\z\else$\mid$\fi}
\begin{document}
\split{ABCD}

\split{Å ÄÖ}
\end{document}

ingrese la descripción de la imagen aquí

información relacionada