No projeto em que estou trabalhando atualmente, o usuário pode definir, dentro de um ambiente definido pelo projeto, uma lista de tags, armazenadas internamente em uma macro (por exemplo, \tags
). Cada item nesta lista consiste em uma ou mais palavras e espaços e números supérfluos (por exemplo, \tags
poderia ser {foo, bar, baz qux , quux2, Corge Grault}
).
Gostaria de saber como definir um \mytest
comando que teste se uma ou mais palavras fornecidas pelo usuário pertencem ou não à \tags
lista e execute um código de acordo com o resultado do teste. O usuário deve ser capaz de usar operadores booleanos (e, ou, não), quaisquer espaços supérfluos devem ser eliminados e pode haver uma opção para determinar se a pesquisa deve ou não levar em consideração as maiúsculas e minúsculas.
Por exemplo, if \tags={foo, bar, baz qux , quux2, Corge Grault}
e if \userinput=(foo && BAR ) || garply
then \mytest{\userinput}{\tags}{true}{false}
retornaria true
while \mytest[1]{\userinput}{\tags}{true}{false}
retornaria false
, assumindo que o parâmetro opcional [1]
fornecido significa que a pesquisa diferencia maiúsculas de minúsculas.
Tenho a sensação de que o LaTeX3 poderia ser particularmente útil para resolver este problema, mas infelizmente não sou competente o suficiente para alcançar o resultado desejado.
Qualquer ajuda seria muito bem-vinda.
Responder1
O comando \mytest
tem um opcional *
para diferenciar maiúsculas de minúsculas.
Ele usa \str_map_inline:nn
para fazer um loop no segundo argumento.
Em cada item deste loop, \tl_set_rescan:Nnn
é executado. Então é verificado se este elemento é |
, &
, (
ou )
.
A função \__searching_if_in:
começa com \tl_trim_spaces:N
. Ele constrói \l__searching_boolean_expression_tl
. No final, isso é 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}