Usando \notblank na instrução \ifboolexpr do etoolbox

Usando \notblank na instrução \ifboolexpr do etoolbox

Como o título diz, atualmente estou tentando usar \ifboolexpra declaração do etoolbox sobre \notblankas condições, mas estou tendo problemas com isso. O código em questão é assim:

\ifboolexpr{%
  test {\notblank{\Temp@Temp@Text@a}} or %
  test {\notblank{\Temp@Temp@Text@b}} or %
  test {\notblank{\Temp@Temp@Text@c}}    %
}%
{}{}%

No entanto, gera vários erros. Mesmo tentar algo assim não parece funcionar melhor:

\ifboolexpr{%
  test {\notblank{}} or %
  test {\notblank{}} or %
  test {\notblank{}}    %
}%
{}{}%

O máximo que consigo usar sem problemas é (fornecido como MWE. Para reproduzir meus problemas, basta substituir a \ifbookexprdeclaração):

\documentclass[10pt,a4paper,titlepage,twoside,onecolumn]{report}
\RequirePackage{etoolbox}

\makeatletter
\def\Temp@Temp@Text@a{testa}
\def\Temp@Temp@Text@b{testb}
\def\Temp@Temp@Text@c{testc}

\makeatother

\begin{document}

\makeatletter

\ifboolexpr{%
  test {} or %
  test {} or %
  test {}    %
}%
{true}{false}%

\makeatother

\end{document}

Então minha pergunta é:

  • O que estou fazendo de errado ?
  • Como resolver isso?

Responder1

A documentação de etoolboxafirma que o argumento para \ifblanke para \notblankénãoexpandido. Portanto \notblank{\xyz}retornará "true" independentemente da definição de \xyz.

Se você deseja uma expansão completa, você deve solicitá-la explicitamente, por exemplo

\documentclass[10pt,a4paper,titlepage,twoside,onecolumn]{report}
\usepackage{etoolbox}

\begin{document}

\makeatletter

\def\Temp@Temp@Text@a{testa}
\def\Temp@Temp@Text@b{testb}
\def\Temp@Temp@Text@c{testc}

\begingroup\edef\x{\endgroup
  \noexpand\ifboolexpr{%
    test {\noexpand\notblank{\Temp@Temp@Text@a}} or 
    test {\noexpand\notblank{\Temp@Temp@Text@b}} or 
    test {\noexpand\notblank{\Temp@Temp@Text@c}}    
  }}\x{\typeout{true}}{\typeout{false}}%

\def\Temp@Temp@Text@a{}
\def\Temp@Temp@Text@b{}
\def\Temp@Temp@Text@c{}

\begingroup\edef\x{\endgroup
  \noexpand\ifboolexpr{%
    test {\noexpand\notblank{\Temp@Temp@Text@a}} or 
    test {\noexpand\notblank{\Temp@Temp@Text@b}} or 
    test {\noexpand\notblank{\Temp@Temp@Text@c}}    
  }}\x{\typeout{true}}{\typeout{false}}%

\makeatother

\end{document}

A primeira instância retorna true, enquanto a segunda retorna false.

Responder2

O catoptionspacote tem exatamente o que você precisa, sem mais código. \xifblankFTsignificatotalmente expandido, não em branco. Há também \oifblankFT, significandoexpandido em uma etapa, não em branco.

\documentclass{report}
\usepackage{catoptions}
\def\vgap{\par\bigskip}

\begin{document}
\def\tempa{testa}
\def\tempb{testb}
\def\tempc{testc}

First test (true):
\ifexprTF{%
  test {\xifblankFT{\tempa}} or
  test {\xifblankFT{\tempb}} or
  test {\xifblankFT{\tempc}}
}{
  true
}{
  false
}

\vgap
\def\tempa{}
\def\tempb{}
\def\tempc{}

Second test (false):
\ifexprTF{%
  test {\xifblankFT{\tempa}} or
  test {\xifblankFT{\tempb}} or
  test {\xifblankFT{\tempc}}
}{
  true
}{
  false
}

\def\tempd{x}

\vgap
Third test (false):
\ifexprTF{%
  ( test {\xifblankTF{\tempa}} or test {\xifblankTF{\tempb}} )
  and
  ( test {\xifblankFT{\tempc}} and test {\xifblankFT{\tempd}} )
}{
  true
}{
  false
}

\vgap
\def\tempe{00}
\newif\iftestbool

Fourth test (true):
\ifexprTF{%
  ( switch {tempe} or bool {testbool} )
  and
  (  ( test {\xifblankTF{\tempc}} and not test {\xifblankTF{\tempd}} )
     or
     ( test {\xifstrcmpTF\tempa\tempb} or not test {\ifxTF\tempc\tempd} )
  )
}{
  true
}{
  false
}
\end{document}

Este tipo de cálculo booleano é caro. Você só precisa olhar o tracelog para confirmar esta afirmação. 99% das vezes você pode fazer um teste muito mais simples. Por exemplo, como \xifstrcmpFTé expansível, temos um teste econômico:

\def\do#1{\ifx\do#1\relax\else+\xifstrcmpFT{#1}{}01\expandafter\do\fi}
\ifnum0=\numexpr0\do\tempa\tempb\tempc\tempd\do
  true
\else
  false
\fi

informação relacionada