En el proyecto en el que estoy trabajando actualmente, el usuario puede definir, dentro de un entorno definido por el proyecto, una lista de etiquetas, almacenadas internamente en una macro (por ejemplo, \tags
). Cada elemento de esta lista consta de una o más palabras y espacios y números superfluos (por ejemplo, \tags
podría ser {foo, bar, baz qux , quux2, Corge Grault}
).
Me gustaría saber cómo definir un \mytest
comando que probaría si una o más palabras proporcionadas por el usuario pertenecen a la \tags
lista y ejecutaría un código de acuerdo con el resultado de la prueba. El usuario debería poder utilizar operadores booleanos (y, o no), se deberían eliminar los espacios superfluos y podría haber una opción para determinar si la búsqueda debe tener en cuenta las mayúsculas y minúsculas.
Por ejemplo, if \tags={foo, bar, baz qux , quux2, Corge Grault}
y if \userinput=(foo && BAR ) || garply
then \mytest{\userinput}{\tags}{true}{false}
devolvería true
while \mytest[1]{\userinput}{\tags}{true}{false}
devolvería false
, suponiendo que el parámetro opcional [1]
proporcionado significa que la búsqueda distingue entre mayúsculas y minúsculas.
Tengo la sensación de que LaTeX3 podría resultar particularmente útil para resolver este problema, pero lamentablemente no soy lo suficientemente competente para lograr el resultado deseado.
Cualquier ayuda sería bienvenida.
Respuesta1
El comando \mytest
tiene una opción *
para distinguir entre mayúsculas y minúsculas.
Se utiliza \str_map_inline:nn
para recorrer el segundo argumento.
En cada elemento de este bucle \tl_set_rescan:Nnn
se realiza. Luego se verifica si este elemento es |
, &
, (
o )
.
La función \__searching_if_in:
comienza con \tl_trim_spaces:N
. Se construye \l__searching_boolean_expression_tl
. Al final, esto es interpretado por \bool_if:nTF
.
\documentclass[border=6pt]{standalone}
\ExplSyntaxOn
\clist_new:N \l__searching_tags_clist
\tl_new:N \l__searching_accumulate_text_tl
\tl_new:N \l__searching_boolean_expression_tl
\tl_new:N \l__searching_text_item_tl
\cs_new:Npn \__searching_if_in:
{
\tl_trim_spaces:N \l__searching_accumulate_text_tl
\tl_if_empty:NF \l__searching_accumulate_text_tl
{
\clist_if_in:NVTF \l__searching_tags_clist \l__searching_accumulate_text_tl
{ \tl_put_right:Nn \l__searching_boolean_expression_tl { \c_true_bool } }
{ \tl_put_right:Nn \l__searching_boolean_expression_tl { \c_false_bool } }
}
\tl_clear:N \l__searching_accumulate_text_tl
}
\NewDocumentCommand { \mytest } { s m m m m }
{
\clist_set:NV \l__searching_tags_clist #3
\tl_clear:N \l__searching_accumulate_text_tl
\tl_clear:N \l__searching_boolean_expression_tl
\str_map_inline:nn {#2}
{
\tl_set_rescan:Nnn \l__searching_text_item_tl {} {##1}
\tl_if_in:nVTF { | & ( ) } \l__searching_text_item_tl
{
\__searching_if_in:
\tl_put_right:NV \l__searching_boolean_expression_tl \l__searching_text_item_tl
}
{
\IfBooleanTF {#1}
{ \tl_put_right:NV \l__searching_accumulate_text_tl \l__searching_text_item_tl }
{ \tl_put_right:Ne \l__searching_accumulate_text_tl { \text_lowercase:n { \l__searching_text_item_tl } } }
}
}
\__searching_if_in:
\bool_if:nTF { \l__searching_boolean_expression_tl } {#4} {#5}
}
\ExplSyntaxOff
\newcommand{\tags}{foo , bar , baz qux , quux2 , Corge Grault}
\begin{document}
\mytest{(foo && BAR ) || garply}{\tags}{true}{false}
\mytest*{(foo && BAR ) || garply}{\tags}{true}{false}
\mytest{ bAr & & foO }{\tags}{true}{false}
\mytest{ baz qux }{\tags}{true}{false}
\end{document}