Divida a string em caracteres e mescle com a formatação

Divida a string em caracteres e mescle com a formatação

Como posso criar uma macro

\split{ABC}

que produz

insira a descrição da imagem aqui

onde a formatação dos caracteres é feita com outra macro, ou seja

\formatchar{A}

onde

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

para qualquer comprimento de string?

Eu tentei modificar o código em Dividir uma sequência 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}

E recebo x e y antes e depois (já que falhei na limitação com um comando e}), mas não consigo formatar corretamente. Também gostaria de evitar a chamada {1} e usar

\split{ABCD}

apenas. São sempre divisões de 1 caractere.

Qualquer ajuda é muito apreciada!

Responder1

Se não for garantido que sua entrada seja “somente ASCII”, uma abordagem \seq_set_split:Nnnpode não funcionar.

Mudei o nome para \splitcharsporque \splité 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}

insira a descrição da imagem aqui

Para obter uma saída semelhante a uma lista, aqui está uma extensão que permite um separador diferente entre os dois últimos itens.

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

insira a descrição da imagem aqui

Responder2

Aqui está uma solução baseada em LuaLaTeX, que faz uso de Lua gsube subde funções integradas. Na verdade, o código usa versões das funções gsube subque podem lidar diretamente com caracteres codificados em utf8.

A macro principal no nível do usuário é chamada \splitstringem vez de \split, porque oamsmathpackage define um ambiente chamado splitjunto com macros chamadas \splite \endsplit.

Observe que (a) o argumento de \splitstringpode conter espaços em branco e (b) formatcharé implementado como uma função Lua em vez de uma macro LaTeX.

insira a descrição da imagem aqui

% !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}

Responder3

Aqui está minha tentativa de solução 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}

insira a descrição da imagem aqui

Responder4

Como não há soluções LaTeX2e oferecidas, apresento uma aqui. Eu uso um ciclo de token para capturar os caracteres um por um do argumento. Esta solução assume que o argumento não possui macros nem grupos. Eu os omiti porque nenhuma orientação foi dada sobre como deveriam ser manuseados, embora possam ser manuseados conforme necessário.

Se for necessário manipular caracteres Unicode, a compilação deverá ser realizada em xelatex ou 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}

insira a descrição da imagem aqui

informação relacionada