如何在 Latex 中创建比较字符串的开关结构

如何在 Latex 中创建比较字符串的开关结构

我想处理传递给包的选项kvoptions

然后将字符串保存在 中\bugs@errorlevel。我想测试它是否包含 [info, warning, error] 之一并相应地设置命令。

我可以考虑将一个 bool 变量设置为 false,并测试它是否一直被设置为 true 或保持 false。这可以通过级联 if 表达式来实现。

例如,可以使用以下方法测试字符串是否相等etoolbox\ifstrequalxstring\IfStrEq。两者都是\ifthen使用括号的包类型。

另一方面,可以使用包进行“真正的”切换boolexpr。但是在这种情况下,我需要返回纯布尔表达式的命令,而上述命令都不具备这种功能。顺序原则如下:

\switch
\case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$%
\case{3<10}$> 5$ and $< 10$%
\case{3>10}$\geq 10$%
\endswitch

但是我不知道在字符串比较的case结构中应该输入什么。最后应该是这样的

\switch
\case{\isequal{\bugs@errorlevel}{info}}
   \renewcommand\tplbugs@BugAction[1]{\PackageInfo{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{warning}}
   \renewcommand\tplbugs@BugAction[1]{\PackageWarning{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{error}}
   \renewcommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}{}}%
\otherwise
   \PackageError{templatebugs}{
     \MessageBreak
     value >\bugs@errorlevel< unkown \MessageBreak
     possible values are: info,warning,error. \MessageBreak
   }{}
\endswitch

但该代码不起作用,因为\isequal不存在。

答案1

与安德烈的回答类似,但坚持使用与之兼容的包装器boolexpr

\documentclass{article}
\usepackage{boolexpr,pdftexcmds,trace}
\makeatletter
\long\def\isequal#1#2{\pdf@strcmp{#1}{#2}}
\def\bugs@errorlevel{error}
\def\tplbugs@BugAction#1{}
\switch
\case{\isequal{\bugs@errorlevel}{info}}
   \renewcommand\tplbugs@BugAction[1]{\PackageInfo{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{warning}}
   \renewcommand\tplbugs@BugAction[1]{\PackageWarning{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{error}}
   \renewcommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}{}}%
\otherwise
   \PackageError{templatebugs}{
     \MessageBreak
     value >\bugs@errorlevel< unkown \MessageBreak
     possible values are: info,warning,error. \MessageBreak
   }{}
\endswitch
\show\tplbugs@BugAction

答案2

你可以使用 pdfTeX 的原语\pdfstrcmp。引用 pdfTeX 手册:

此命令比较两个字符串,如果两个字符串相等,则扩展为 0;如果第一个字符串排在第二个字符串之前,则扩展为 -1;否则,扩展为 1。

此外,该包pdftexcmds\pdf@strcmp提供适用于所有 TeX 引擎的类似命令。

因此,概念验证代码是:

\documentclass{article}

\usepackage{pdftexcmds}

\makeatletter
\newcommand{\switch}[1]{%
  \ifnum\pdf@strcmp{#1}{info}=0
    first%
  \else\ifnum\pdf@strcmp{#1}{warning}=0
    second%
  \else\ifnum\pdf@strcmp{#1}{error}=0
    third%
  \else
    unknown%
  \fi\fi\fi}
\makeatother

\begin{document}

\switch{info}
\switch{warning}
\switch{error}
\switch{something}

\end{document}

如果您想采用旧的 TeX 方式,则可以使用条件\ifx,该条件测试标记是否相等。如果后面的两个标记\ifx是宏,则比较它们的参数文本和替换文本。

\documentclass{article}

\def\infotext{info}
\def\warningtext{warning}
\def\errortext{error}
\newcommand{\switch}[1]{%
  \begingroup
    \def\tmp{#1}%
    \ifx\tmp\infotext
      first%
    \else\ifx\tmp\warningtext
      second%
    \else\ifx\tmp\errortext
      third%
    \else
      unknown%
    \fi\fi\fi
  \endgroup}

\begin{document}

\switch{info}
\switch{warning}
\switch{error}
\switch{something}

\end{document}

请注意在宏定义中\ifx考虑\long和,因此混合和或定义将无法成功比较!\outer\newcommand\newcommand*\def

答案3

实现如下expl3

\documentclass{article}
\usepackage{expl3}
\makeatletter
\def\bugs@errorlevel{info} % change for testing

\ExplSyntaxOn
\prg_case_str:onn { \bugs@errorlevel }
  {
   {info}    { \providecommand\tplbugs@BugAction[1]{\PackageInfo{templatebugs}{#1}} }
   {warning} { \providecommand\tplbugs@BugAction[1]{\PackageWarning{templatebugs}{#1}} }
   {error}   { \providecommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}} }
  }
  {
   % set a default
   \providecommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}}
   % issue an error
   \PackageError{templatebugs}
     {
      \MessageBreak
      value~>\bugs@errorlevel<~unkown \MessageBreak
      possible~values~are:~info,~warning,~error.
     }
     {
      The~value~must~be~one~of~`info',~`warning',~or~`error';
      \MessageBreak
      I'll~do~as~if~`error'~had~been~requested
     }
   }
\ExplSyntaxOff
\show\tplbugs@BugAction

相关内容