
Algunos editores de programación e IDE resaltan nombres de variables legales e ilegales de diferentes maneras. Desearía listings
que se permitiera fácilmente dicha verificación y resaltado de sintaxis, pero no es así, al menos por el momento. Mi objetivo a largo plazo es implementar una solución compatible con listings
pero, por ahora, estoy viendo una versión muy simplificada del problema.
Quiero analizar la primera palabra en una secuencia de tokens compuesta únicamente de tokens de caracteres y espacios. esto tiene que hacerseficha por ficha, sin embargo, porque tengo que realizar algunas comprobaciones en cada token. Para eso, utilizo una macro recursiva que analiza la secuencia y la guarda en una \Word
macro hasta que .
se encuentra un token. En esa etapa, proceso \Word
de cierta manera, como imprimirlo en rojo. Yo defino unpalabracomo una secuencia de fichas de personaje ininterrumpida por ninguna ficha de espacio.
Problema: Aquí solo uso un .
token porque no puedo entender qué debo cambiar en mi código para detener la recursividad cuando .
se encuentra el siguiente token de espacio, no un token, en la secuencia. Sustituir un espacio de control ( \
) .
no parece funcionar. ¿Qué debo cambiar en mi código?
Prefiero una solución que utilice comandos TeX de bajo nivel para el análisis, pero las alternativas LaTeX2e y LaTeX3 también me interesan.
Editar: Pido disculpas si parece que estoy moviendo la portería, pero tuve que aclarar bastante mi pregunta agregando el requisito "token por token", lo que puede invalidar algunas de las respuestas ya publicadas.
\documentclass{article}
\usepackage{xcolor}
\def\ParseWordandPrint#1{%
\if #1.%
\textcolor{red}{\Word}\ %
\else
\edef\Word{\Word#1}
\expandafter\ParseWordandPrint
\fi%
}
\def\InitParseWordandPrint#1{%
\def\Word{}
\ParseWordandPrint#1%
}
\begin{document}
\InitParseWordandPrint Hello.World
\end{document}
Respuesta1
Recuperando esto a la luz de su pregunta editada.
Es más fácil captar la palabra de una vez con un argumento delimitado por espacios yentoncesiterar sobre esa letra por letra. (Como ejemplo compruebo aquí que son letras, el último ejemplo produce
illegal character 0
illegal character 1
Para iterar carácter por carácter deteniéndote en un espacio que debes usar \futurelet
(o equivalentemente \@ifnextchar
), pero eso no es tan bueno en una palabra, vas a componer, ya que es difícil no romper los núcleos y ligaduras entre letras. Así es más fácil captar la palabra primero.
\documentclass{article}
\usepackage{xcolor}
\def\InitParseWordandPrint#1 {\check#1\relax\textcolor{red}{#1} }
\def\check#1{%
\ifx\relax#1%
\else
\ifcat a#1%
\else
\typeout{illegal character #1}%
\fi
\expandafter\check
\fi}
\begin{document}
\InitParseWordandPrint Hello World
\InitParseWordandPrint World
Hello World
\InitParseWordandPrint W0r1d
\end{document}
Respuesta2
TeX \def
proporciona texto de parámetro delimitado. Entonces, en este caso, puedes usar el espacio como delimitador:
\documentclass{article}
\usepackage{xcolor}
\def\ParseWordandPrint#1{%
\if #1.%
\textcolor{red}{\Word}\ %
\else%
\edef\Word{\Word#1}%
\expandafter\ParseWordandPrint%
\fi%
}
\def\InitParseWordandPrint#1{%
\def\Word{}%
\ParseWordandPrint#1%
}
\def\highlightfirst#1 {\textcolor{red}{#1} }
\begin{document}
\InitParseWordandPrint Hello.World
\highlightfirst Hello World.
\end{document}
Respuesta3
Es realmente fácil con LaTeX3:
\documentclass{article}
\usepackage{xparse,xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\printfirstwordincolor}{ O{red} m }
{
\jubobs_pfwr:nn { #1 } { #2 }
}
\seq_new:N \l_jubobs_words_seq
\tl_new:N \l_jubobs_first_word_tl
\cs_new_protected:Npn \jubobs_pfwr:nn #1 #2
{
% split the input at spaces
\seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
% pop off the leftmost item
\seq_pop_left:NN \l_jubobs_words_seq \l_jubobs_first_word_tl
% print the first item in the chosen color
\textcolor{#1}{ \l_jubobs_first_word_tl } ~ %
% print the other items adding spaces between them
\seq_use:Nn \l_jubobs_words_seq { ~ }
}
\ExplSyntaxOff
\begin{document}
\printfirstwordincolor{Hello World}
\printfirstwordincolor[green]{Addio mondo crudele}
\end{document}
Si también desea procesar la entrada token por token, puede realizar un mapeo de los elementos guardados. Digamos que quieres poner en mayúscula cada 'd':
\documentclass{article}
\usepackage{xparse,xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\printfirstwordincolor}{ O{red} m }
{
\jubobs_pfwc:nn { #1 } { #2 }
}
\seq_new:N \l_jubobs_words_seq
\tl_new:N \l_jubobs_first_word_tl
\bool_new:N \l_jubobs_first_item_bool
\cs_new_protected:Npn \jubobs_pfwc:nn #1 #2
{
\seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
\seq_pop_left:NN \l_jubobs_words_seq \l_jubobs_first_word_tl
\textcolor{#1}{ \l_jubobs_first_word_tl } ~ %
\seq_use:Nn \l_jubobs_words_seq { ~ }
}
\NewDocumentCommand{\printfirstwordincolorandcapitalizeD} { O{red} m }
{
\jubobs_pfwcacd:nn { #1 } { #2 }
}
\cs_new_protected:Npn \jubobs_pfwcacd:nn #1 #2
{
\seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
\leavevmode
\bool_set_true:N \l_jubobs_first_item_bool
\seq_map_inline:Nn \l_jubobs_words_seq
{
\bool_if:NT \l_jubobs_first_item_bool
{ \c_group_begin_token \color{#1} }
\tl_map_inline:nn { ##1 }
{
\peek_charcode_remove:NT d { D } ####1
}
\bool_if:NT \l_jubobs_first_item_bool
{ \c_group_end_token \bool_set_false:N \l_jubobs_first_item_bool }
\c_space_tl
}
\unskip
}
\ExplSyntaxOff
\begin{document}
\printfirstwordincolor{Hello World}
\printfirstwordincolorandcapitalizeD[blue]{Addio mondo crudele}
\end{document}