Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

It seem that if macro \IfSubStr from package xstring is used as parameter it is not expanded like other macros are.

Here is minimal demonstration:

\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}

I would expect this to print in then in then. Instead \test{\IfSubStr{WKS}{W}{W}{N}} behaves differently to previous macro and the output is in then in else. Why is that? How can I tweak my code or replace \IfSubStr by another macro so that I get expected result?


Edit

Here I should explain what I need do. There is a macro like the \test macro shown in minimal example above. This macro has optional argument that works like switch - in very similar way it is shown in example above. If optional argument is W some actions are taken, it is unset or anything else then W some other actions are taken. It uses the same \if \else condition that I have used in demo.

I am creating new macro that uses this existing macro. My macro has also first argument optional that may contain number of switches. One of them is that W switch. This switch is to be delegated existing macro. I thought I might code like this in my macro would do the trick \theExistingMacro[\IfSubStr{#1}{W}{W}{}]{...}{...} but it does not work. So how do I make it work?


Edit 2

To clarify here is real life example.

There is a macro like this (simplified code)

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

I am creating new macro that calls different other macros one of which is \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           
  }%
}

The line \addLabelAbove[\IfSubStr{#1}{W}{W}{}]{\theBoxCount}{#2}{#3}% intends to call macro \addLabelAbove with switch W if there is W among switches given to macro \block or with without that switch if there is no W switch among switches given to \block. It does not work this way and I'd like to know how to make it work.

share|improve this question
    
@cmhughes \ifx would compare \IfSubStr to {, which is surely not what's wanted. ;-) –  egreg Jan 17 '13 at 18:57
    
Re the edit: is the optional argument expected to contain something like AWK? And in this case, should the macro take the W branch? –  egreg Jan 17 '13 at 22:46
    
@egreg Yes, optional argument of macro I am creating is expected to contain something like AWK (multiple swithes). But the existing macro that I cannot alter is only expecting one switch - that is W. I'm not sure I understand your second question... The predefined macro (that I cannot alter) should get the W switch if and only if W was one of switches given to macro that I am creating. –  drasto Jan 17 '13 at 23:03
1  
The definition of \addLabelAbove is definitely wrong. If you call \addLabelAbove[aa]{X}{Y}{Z} it will follow the true branch and you'll have a W in the output. And if you call it with an empty optional argument you'll be in big trouble, because the first token of the expansion of \saveToNewBox will be eaten up. –  egreg Jan 17 '13 at 23:42
    
@egreg I thought it might be wrong (because of all the trouble it is causeing me). I'm not supposed to alter this code - it is in another package but I can redefine \addLabelAbove command. What should the correct definition look like? –  drasto Jan 17 '13 at 23:47

1 Answer 1

The conditional \if compares the first two unexpandable tokens it finds after expanding the following tokens.

In the case of \copyArg, the expansion ends with K, so \if compares K to K and the test returns true.

In the second case, the first unexpandable token is \let, followed by \reserved@d whose value is not predictable. In any case the result of \IfSubStr is still very far from being computed to begin with.

It's not easy to understand what you want to do; surely, mixing these very differently behaving tests is not the right thing to try.


Let's assume your macro \theMacro takes an optional argument and a mandatory one; moreover it should call \yesW with the specified mandatory argument if W is a substring of the optional argument and \noW otherwise. Then this would do the job:

\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}

enter image description here

Without a "real life" example it's hard to say more.

An alternative way similar to your \test macro would be

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

that is, you delegate the test to \ifW instead of trying directly with the given optional argument.


Now, assuming you need to use the (faulty) macro \addLabelAbove, you can do just like in the above suggestion:

\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
  }%
}

The \relax in the "non W" case is meant to fix the problem with \addLabelAbove, where the \if will compare \relax to W, so following the "else" branch correctly.

share|improve this answer
    
I have added explanation of what I want to do as an edit to the original question. Please have a look on it. –  drasto Jan 17 '13 at 22:44
    
@drasto I added something for you. –  egreg Jan 17 '13 at 23:07
    
I see that my problem is hard to understand. I'll add real life example to my question. My problem is that instead of those 2 commands noW and yesW there is only one long and complicated macro that I have to use (otherwise I would introduce a lot of code duplication). That long macro is something like \test macro from my original question. –  drasto Jan 17 '13 at 23:16
    
I have added "real life example" to the question, well a little simplified. I do not think I can explain it much better. Any ideas on how can I do this are welcome. –  drasto Jan 17 '13 at 23:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.