看起来,如果使用\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
开关调用宏;如果在宏中给出了开关,则该行旨在使用不带该开关的开关调用宏。它不能这样工作,我想知道如何让它工作。W
W
\block
W
\block
答案1
条件\if
在扩展以下标记之后比较它找到的前两个不可扩展标记。
在 的情况下\copyArg
,扩展以 结尾K
,因此与\if
进行比较并且测试返回 true。K
K
在第二种情况下,第一个不可扩展的标记是\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”分支。\relax
W