
¿Es posible comprobar si un token es un delimitador, es decir (
, )
, |
, , \vert
, \langle
, \rangle
etc. sin comprobar directamente cada uno de ellos en una condición?
La estructura del delimitador se describe bien aquí:https://tex.stackexchange.com/a/296650/213149. Parece usar \delimiter
comando
Entonces mi pregunta es cómo puedo detectar dicho delimitador de una manera algo versátil usando TeX puro o LaTeX3.
Por ejemplo, quiero una macro personalizada \isDelimiter{...}
para imprimir true
o false
en el documento si su argumento es un delimitador o no, respectivamente.
Respuesta1
No estoy seguro de que esto pueda ser útil para tu \veca
problema. De todos modos…
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\isDelimiterTF}{mmm}
{
\antshar_isdel:Nnn #1 { #2 } { #3 }
}
% first check whether #1 is a control sequence
\cs_new:Nn \antshar_isdel:Nnn
{
\token_if_cs:NTF #1
{
\__antshar_isdel_cs:Nnn #1 { #2 } { #3 }
}
{
\__antshar_isdel_char:Nnn #1 { #2 } { #3 }
}
}
% it is a control sequence; first check the two exceptional cases \{ and \}
% which return true; otherwise go on: if the token is not expandable return false
\cs_new:Nn \__antshar_isdel_cs:Nnn
{
\str_case:nnF { #1 }
{
{\{}{#2}
{\}}{#2}
}
{
\token_if_expandable:NTF #1
{
\__antshar_isdel_csexp:Nnn #1 { #2 } { #3 }
}
{
#3
}
}
}
% the token is expandable, access its expansion
\cs_new:Nn \__antshar_isdel_csexp:Nnn
{
\__antshar_isdel_exp:onn { #1 } { #2 } { #3 }
}
% if the expansion begins with \delimiter return true, otherwise false
\cs_new:Nn \__antshar_isdel_exp:nnn
{
\__antshar_isdel_exp_aux:w #1 \q_nil \q_stop { #2 } { #3 }
}
\cs_generate_variant:Nn \__antshar_isdel_exp:nnn { o }
\cs_new:Npn \__antshar_isdel_exp_aux:w #1 #2 \q_stop #3 #4
{
\token_if_eq_meaning:NNTF #1 \delimiter { #3 } { #4 }
}
% when the token is a character, look at its \delcode;
% if positive return true, otherwise false
\cs_new:Nn \__antshar_isdel_char:Nnn
{
\int_compare:nTF { \delcode`#1 > 0 } { #2 } { #3 }
}
\ExplSyntaxOff
\begin{document}
\verb|a|: \isDelimiterTF{a}{T}{F}
\verb|(|: \isDelimiterTF{(}{T}{F}
\verb|]|: \isDelimiterTF{]}{T}{F}
\verb|\langle|: \isDelimiterTF{\langle}{T}{F}
\verb-\|-: \isDelimiterTF{\|}{T}{F}
\verb|\{|: \isDelimiterTF{\{}{T}{F}
\verb|\lbrace|: \isDelimiterTF{\lbrace}{T}{F}
\verb|\mbox|: \isDelimiterTF{\mbox}{T}{F}
\end{document}
¿Cómo reconocemos cuando una secuencia de control es un delimitador? Su expansión de primer nivel debe comenzar con \delimiter
o, si es un personaje, debe \delcode
ser positivo.
Por tanto, la comprobación de un personaje es obvia. Para una secuencia de control primero necesitamos ver si es expandible o no. Pero también hay que cuidarlos \{
y \}
que son algo especiales, por eso estos casos se solucionan solos.
Si la secuencia de control que estamos examinando no es expandible, no es un delimitador (tal vez se deban agregar otras excepciones como \{
y con algunos paquetes de fuentes). \}
Si es expandible, miramos su expansión de primer nivel llamando
\__antshar_isdel_exp:onn { #1 } { #2 } { #3 }
entonces el o
tipo de argumento hará la expansión de un nivel requerida. esto se convertirá
\__antshar_isdel_exp_aux:w #1 \q_nil \q_stop { #2 } { #3 }
La definición de \__antshar_isdel_exp_aux:w
es
\cs_new:Npn \__antshar_isdel_exp_aux:w #1 #2 \q_stop #3 #4
{
\token_if_eq_meaning:NNTF #1 \delimiter { #3 } { #4 }
}
entonces el primer token en la expansión de la secuencia de control que estamos examinando se convierte en #1
y el resto \q_nil
se convierte en #2
. El resto, es decir, #3
y #4
son el texto verdadero y falso de \isDelimiterTF
. El primer argumento no está delimitado, por lo que tomará el primer token del flujo de entrada como argumento; el segundo argumento termina cuando TeX encuentra \q_stop
.
Lo extraño \q_nil
está ahí porque si lo intentas \isDelimiter{\empty}{T}{F}
no habría nada en la expansión; en este caso \q_nil
se toma como #1
y #2
está vacío. Pero como \q_nil
no es así \delimiter
, todo pasa.