\IfSubStr 作为另一个宏的参数使用时不起作用

\IfSubStr 作为另一个宏的参数使用时不起作用

看起来,如果使用\IfSubStr包中的宏作为参数,它就不会像其他宏那样被扩展。xstring

以下是最简单的演示:

\usepackage{xstring}
\newcommand{\copyArg}[1]{#1}
\newcommand{\test}[1]{%
  \if#1W
    in then%
  \else
    in else%
  \fi
}
\begin{document}
  \test{\copyArg{W}}
  \test{\IfSubStr{WKS}{W}{W}{N}}
\end{document}

我希望它打印in then in then。但\test{\IfSubStr{WKS}{W}{W}{N}}与上一个宏的行为不同,输出为in then in else。这是为什么?我该如何调整代码或\IfSubStr用另一个宏替换以获得预期结果?


编辑

在这里我应该解释一下我需要做什么。有一个宏,就像\test上面最小示例中显示的宏一样。这个宏有一个可选参数,其工作方式与 switch 非常相似 - 非常类似于上面示例中显示的方式。如果可选参数是W采取某些操作,则取消设置或其他任何操作,然后W采取其他操作。它使用 \if \else我在演示中使用的相同条件。

我正在创建使用此现有宏的新宏。我的宏还有第一个可选参数,可能包含多个开关。其中一个就是该W开关。此开关将被委托给现有宏。我以为我可以在宏中编写这样的代码来解决问题,\theExistingMacro[\IfSubStr{#1}{W}{W}{}]{...}{...}但它不起作用。那么我该如何让它工作呢?


编辑2

这里需要澄清的是现实生活中的例子。

有一个这样的宏(简化代码)

\newcommand{\addLabelAbove}[4][]{%
  \if#1W%
    \saveToNewBox{#2}{\vbox{\noindent#4\\*\noindent#3}}%
  \else%
    \saveToNewBox{#2}{\pbox{\textwidth}{\noindent#4\\*\noindent#3}}%
  \fi%
}%

我正在创建新的宏来调用其他不同的宏,其中一个是\addLabelAbove

\newcommand{\block}[6][]{
  \uppercase{\IfSubStr{#1}}{A}{%then
    \uppercase{\IfSubStr{#1}}{L}{%then
      \doSomething{#2}{#3}{#4}{#5}{#6}
    }{%else
      \stepcounter{BoxCount}%
      \addLabelAbove[\IfSubStr{#1}{W}{W}{}]{\theBoxCount}{#2}{#3}%
      \someMoreMacrosSkiped
    }%
  }{%else
    \someOtherUnimportantCommands           
  }%
}

如果在宏中给出了开关,则该行\addLabelAbove[\IfSubStr{#1}{W}{W}{}]{\theBoxCount}{#2}{#3}%旨在使用\addLabelAbove开关调用宏;如果在宏中给出了开关,则该行旨在使用不带该开关的开关调用宏。它不能这样工作,我想知道如何让它工作。WW\blockW\block

答案1

条件\if在扩展以下标记之后比较它找到的前两个不可扩展标记。

在 的情况下\copyArg,扩展以 结尾K,因此与\if进行比较并且测试返回 true。KK

在第二种情况下,第一个不可扩展的标记是\let,后面跟着 ,\reserved@d其值不可预测。无论如何, 的结果\IfSubStr仍然远远不能被计算出来。

理解您想要做什么并不容易;当然,混合这些行为非常不同的测试并不是正确的尝试。


假设您的宏\theMacro采用一个可选参数和一个强制参数;此外,如果是可选参数的子字符串,则它应该\yesW使用指定的强制参数进行调用,否则。那么这将完成工作:W\noW

\documentclass{article}
\usepackage{xstring}

\newcommand{\noW}[1]{Do something with #1 (no \texttt{W})}
\newcommand{\yesW}[1]{Do something else with #1 (\texttt{W} seen)}

\newcommand\theMacro[2][]{%
  \IfSubStr{#1}{W}
    {\yesW{#2}}
    {\noW{#2}}}

\begin{document}

\texttt{W} should not be seen: \theMacro{`hello'}

\texttt{W} should not be seen: \theMacro[ABC]{`hello'}

\texttt{W} should be seen: \theMacro[W]{`world'}

\texttt{W} should be seen: \theMacro[AWK]{`world'}

\end{document}

在此处输入图片描述

如果没有“现实生活中”的例子,就很难多说什么。

与宏类似的另一种方法\test

\newif\ifW
\newcommand{\theMacro}[1][]{%
   \IfSubStr{#1}{W}{\Wtrue}{\Wfalse}%
   \ifW
      <then code>
   \else
      <else code>
   \fi}

也就是说,您将测试委托给,\ifW而不是直接使用给定的可选参数进行尝试。


现在,假设您需要使用(有故障的)宏\addLabelAbove,您可以按照上述建议进行操作:

\newif\ifW
\newcommand{\block}[6][]{%
  \uppercase{\IfSubStr{#1}}{A}{%then
    \uppercase{\IfSubStr{#1}}{L}{%then
      \doSomething{#2}{#3}{#4}{#5}{#6}
    }{%else
      \stepcounter{BoxCount}%
      \IfSubStr{#1}{#}{\Wtrue}{\Wfalse}%
      \ifW
        \addLabelAbove[W]{\theBoxCount}{#2}{#3}%
      \else
        \addLabelAbove[\relax]{\theBoxCount}{#2}{#3}%
      \fi
      \someMoreMacrosSkiped
    }%
  }{%else
    \someOtherUnimportantCommands
  }%
}

“非 W” 案例中的\relax旨在修复 的问题\addLabelAbove,其中 将与\if进行比较,从而正确遵循“else”分支。\relaxW

相关内容