4

I have a macros.tex included in the preamble that creates some useful dumb macros. I want to define a macro for writing fractions that adds a brace if the argument is longer than 1 character, what I have so far is:

\usepackage{xstrings}
\newcommand{\fracdivide}[3]{%
    \StrLen{#2}[\arglen]%
    \ifthenelse{\arglen > 1}
    {%
        \frac{#1\left(#2\right)}{#1#3}
    }%
    {%
        \frac{#1#2}{#1#3}
    }%
}

That produces the following error: !Incomplete \iffalse; all text was ignored after line 16.

line 16 is exactly the line where I have the \StrLen command. If I remove it (for example using 2 instead of \arglen), it compiles correctly.

Why do I get this error? And how do I solve it?

Here's a MWE, it seems related to the \text command of amsmath.

\documentclass{minimal}
\usepackage{mathtools}
\usepackage{xstring}
\usepackage{ifthen}
\newcommand{\vect}[1]{\boldsymbol{\mathbf{#1}}}
\newcommand{\fracdivide}[3]{%
    \StrLen{#2}[\arglen]%
    \ifthenelse{\arglen > 1}
    {%
        \frac{#1\left(#2\right)}{#1#3}
    }%
    {%
        \frac{#1#2}{#1#3}
    }%
}
\newcommand{\partialdd}[2]{\fracdivide{\partial}{#1}{#2}}
\newcommand{\ddt}[1]{\partialdd{#1}{t}}

\begin{document}
$\ddt{f^\text{big}}$
\end{document}
  • 1
    Make a complete example. One can't run tests with snippets. – Ulrike Fischer Jun 9 '17 at 17:03
  • I tried a couple of examples, but got no failure. – egreg Jun 9 '17 at 17:11
  • My best guess is something that's not fully-expandable is being passed as the second argument to \fracdivide. Possibly some other command from xstrings, but I've never used that package before. – TH. Jun 9 '17 at 17:14
  • @UlrikeFischer you are right. I'm sorry. I uploaded a MWE. – DiTTiD Jun 9 '17 at 18:28
3

You are better using \noexpandargs:

\documentclass{article}
\usepackage{mathtools}
\usepackage{xstring}
\usepackage{ifthen}
\newcommand{\vect}[1]{\boldsymbol{\mathbf{#1}}}
\newcommand{\fracdivide}[3]{%
  \begingroup\noexpandarg
  \StrLen{#2}[\arglen]%
  \ifthenelse{\arglen > 1}
    {%
     \frac{#1(#2)}{#1#3}%
    }%
    {%
     \frac{#1#2}{#1#3}%
    }%
  \endgroup
}
\newcommand{\partialdd}[2]{\fracdivide{\partial}{#1}{#2}}
\newcommand{\ddt}[1]{\partialdd{#1}{t}}

\begin{document}

\[
\ddt{f^{\mathrm{big}}} + \ddt{\Gamma}
\]

\end{document}

enter image description here

Note: I removed the useless (and harmful) \left and \right.

The problem is that commands such as \mathrm or \text won't survive the full expansion performed by default by \StrLen. With \noexpandargs this is avoided.

However, something like \ddt{\vect{x}} will be parenthesized. I don't think this is a really useful macro.

Probably a macro with a *-version is easier to work with.

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}

\NewDocumentCommand{\fracdivide}{smmm}{%
  \frac{#2\IfBooleanTF{#1}{(#3)}{#3}}{#2#4}%
}

\NewDocumentCommand{\partialdd}{smm}{%
  \IfBooleanTF{#1}{\fracdivide*}{\fracdivide}{\partial}{#2}{#3}%
}
\NewDocumentCommand{\ddt}{sm}{%
  \IfBooleanTF{#1}{\partialdd*}{\partialdd}{#2}{t}%
}

\newcommand{\vect}[1]{\boldsymbol{\mathbf{#1}}}

\begin{document}

\[
\ddt*{f^{\mathrm{big}}} + \ddt{f_1}
- \ddt{\vect{x}} + \ddt*{\vect{x}+\vect{y}}
\]

\end{document}

enter image description here

| improve this answer | |
  • Thanks for your effort! In fact I just realized that it puts braces in the situation you mention. Is there a way to strip all the "operators" acting on a argument to retrieve the actual length of the argument so that \vect{x} results in length of 1? Or also \hat{\vect{x}}? – DiTTiD Jun 9 '17 at 20:59
  • @SolidSnake Not really, I'm afraid. Much better to specify yourself whether you want parentheses or not. – egreg Jun 9 '17 at 21:56
  • It's actually a dumb macro. :). I edited the question accordingly. And thanks for your help. – DiTTiD Jun 9 '17 at 21:58
1

Your attempt at extracting the length of the string requires the argument to expand to a string. However, f^\text{big} does not. We can \detokenize the input:

\documentclass{article}

\usepackage{mathtools,xstring}

\newcommand{\fracdivide}[3]{
    \StrLen{\detokenize{#2}}[\arglen]
    \ifnum\arglen>1
      \frac{#1\left(#2\right)}{#1#3}
    \else
      \frac{#1#2}{#1#3}
    \fi
}
\newcommand{\partialdd}[2]{\fracdivide{\partial}{#1}{#2}}
\newcommand{\ddt}[1]{\partialdd{#1}{t}}

\begin{document}
$\ddt{f^\text{big}}$
\end{document}
| improve this answer | |
  • 1
    This way \fracdivide{d}{\alpha}{x} will choose the parenthesized branch. – egreg Jun 9 '17 at 20:35
  • @egreg: Yes. Hopefully an edge case. – Werner Jun 9 '17 at 20:54
1

You need something like this:

\def\ddt#1{{\partial\maybebraces{#1}\over\partial t}}
\def\maybebraces#1{\maybebracesA#1&}
\def\maybebracesA#1#2&{\ifx&#2&#1\else\left(#1#2\right)\fi}


$$\ddt{f^{\rm big}} + \ddt{\Gamma}$$

\bye

In contrast to the other solutions here we do not mix the problem of construction of the fraction (with "partial" sign and with "t" in denominator) with the problem of "maybebraces". And (of course) no special packages (and no LaTeX) is explicitly needed.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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