В проекте, над которым я сейчас работаю, пользователь может определить в среде, определенной проектом, список тегов, хранящихся внутри макроса (например, \tags
). Каждый элемент в этом списке состоит из одного или нескольких слов и лишних пробелов и цифр (например, \tags
может быть {foo, bar, baz qux , quux2, Corge Grault}
).
Я хотел бы знать, как определить \mytest
команду, которая будет проверять, принадлежат ли одно или несколько слов, предоставленных пользователем, списку \tags
, и выполнять код в соответствии с результатом теста. Пользователь должен иметь возможность использовать булевы операторы (и, или, не), все лишние пробелы должны быть удалены, и может быть возможность определить, следует ли при поиске учитывать регистр слов.
Например, если \tags={foo, bar, baz qux , quux2, Corge Grault}
и если \userinput=(foo && BAR ) || garply
then \mytest{\userinput}{\tags}{true}{false}
вернут true
while \mytest[1]{\userinput}{\tags}{true}{false}
вернут false
, предполагая, что предоставленный необязательный параметр [1]
означает, что поиск чувствителен к регистру.
У меня есть ощущение, что LaTeX3 мог бы оказаться особенно полезным в решении этой проблемы, но, к сожалению, я недостаточно компетентен, чтобы достичь желаемого результата.
Любая помощь будет принята с благодарностью.
решение1
Команда \mytest
имеет необязательный параметр *
чувствительности к регистру.
Он используется \str_map_inline:nn
для перебора второго аргумента.
На каждом элементе в этом цикле \tl_set_rescan:Nnn
выполняется. Затем проверяется, является ли этот элемент |
, &
, (
или )
.
Функция \__searching_if_in:
начинается с \tl_trim_spaces:N
. Она создает \l__searching_boolean_expression_tl
. В конце это интерпретируется как \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}