14

My question is about declaring a "newcommand" with an option.

I have defined

\newcommand{\bforall}[2]{\forall #1\, (#2)}

so that $\bforall{x}{x \in A}$ writes $\forall x (x \in A)$.

I would like some control over the brackets. Namely, I would like

\bforall[s]{x}{x \in A} 

to use square braces, and

\bforall[c]{x}{x \in A} 

to use curly braces.

How can this be accomplished?

I've search the forum and found 1/ Different command definitions with and without optional argument and 2/ Optional argument for newcommand? and neither helped me.

vrbatim
  • 731
  • 6
  • 13

4 Answers4

15

Here is a way, without packages.

\documentclass{article}
\newcommand\bforall[3][r]{%
  \ifx r#1\forall #2\, (#3)\else
  \ifx s#1\forall #2\, [#3]\else
  \ifx c#1\forall #2\, \{#3\}\else
  \mathrm{Illegal~option}%
  \fi\fi\fi
}
\begin{document}
$\bforall{x}{x \in A}$

$\bforall[r]{x}{x \in A}$

$\bforall[s]{x}{x \in A}$

$\bforall[c]{x}{x \in A}$

\end{document}

enter image description here

As touhami rightly points out, the penalty for using the simplicity of the \ifx construct is that an accidental syntax error such as using a two character optional argument like [rs] will not produce an error message, but rather just wrongly set the term.

  • see @egreg comment to my answer http://tex.stackexchange.com/questions/254158/new-command-with-two-definitions/254164#254164 – touhami Aug 04 '15 at 03:12
  • @touhami I see the point, but I'm not sure if it applies, since my optional argument has a default non-empty value. To run into the problem, one would have to pass a blank optional argument, I think. But it certainly doesn't hurt to add a \relax after #1 to address that case. In fact, I just tried the case, and it throws the expected error already. – Steven B. Segletes Aug 04 '15 at 09:50
  • Sorry, i mean @egreg's last comment, in this case $\bforall[rs]{x}{x \in A}$ – touhami Aug 04 '15 at 10:04
  • @touhami In your case, the optional argument was a mathematical term that could be one or more characters. In my case, the optional argument is a single letter indicating round, square, or curly braces. A 2-character optional argument in my case is indicative of a syntax error. – Steven B. Segletes Aug 04 '15 at 10:12
  • here is the prolem $\bforall[rs]{x}{x \in A}$ will not idicate error. – touhami Aug 04 '15 at 10:46
  • @touhami I have edited my answer to note your comment. – Steven B. Segletes Aug 04 '15 at 10:52
6

Here is one way to do that using the xstring package's \IfStrEqCase:

enter image description here

The default option is round braces, curly braces and square braces. You can also add an optional second parameter to control the brace size:

enter image description here

Code:

\documentclass{article}
\usepackage{xstring}

\newcommand{\bforall}[3][r]{% \forall #2, \IfStrEqCase{#1}{% {r}{(#3)}% {c}{{#3}}% {s}{{[#3]}}% }[% %% Issue error message here about unsuported bracket type ]% }

\begin{document} $\bforall{x}{x \in A}$

$\bforall[r]{x}{x \in A}$

$\bforall[c]{x}{x \in A}$

$\bforall[s]{x}{x \in A}$

\end{document}

Code Resizing Brackets:

\documentclass{article}
\usepackage{xstring}
\usepackage{xparse}
\usepackage{amsmath}

\NewDocumentCommand{\bforall}{% O{r}% #1 = r, c or s (bracket shape) O{}% #2 = optional size specifier m% #3 m% #4 }{% \forall #3, \IfStrEqCase{#1}{% {r}{#2(#4#2)}% {c}{#2{#4#2}}% {s}{{#2[#4#2]}}% }[% %% Issue error message here about unsupported bracket type \PackageError{tree}{Undefined option to tree: #1}{} ]% }

\begin{document} \begin{minipage}{0.25\linewidth} $\bforall{x}{x \in A}$

$\bforall[r]{x}{x \in A}$

$\bforall[c]{x}{x \in A}$

$\bforall[s]{x}{x \in A}$ \end{minipage} \hspace*{0.5cm} \begin{minipage}{0.25\linewidth} $\bforall[r][\Big]{x}{x \in A, x > \dfrac{1}{2}}$

$\bforall[c][\Big]{x}{x \in A, x > \dfrac{1}{2}}$

$\bforall[s][\bigg]{x}{x \in A, x > \dfrac{1}{2}}$ \end{minipage} \end{document}

Peter Grill
  • 223,288
3

For a case switch macro the best is expl3; I used the letters already common with amsmath, p for parentheses, b for brackets, B for braces.

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\bforall}{O{p}mm}
 {
  \forall #2\,
  \str_case:nnF { #1 }
   {
    {p}{(#3)}
    {b}{[#3]}
    {B}{\{#3\}}
   }
   {\@latex@error{Illegal~option~#1}{I~used~p}}
 }

\ExplSyntaxOff

\begin{document}

$\bforall{x}{x \in A}$

$\bforall[p]{x}{x \in A}$

$\bforall[b]{x}{x \in A}$

$\bforall[B]{x}{x \in A}$

\end{document}

enter image description here

egreg
  • 1,121,712
2

A plain TeX one with a different syntax

\def\bforall#1{\forall#1\,\futurelet\tmptoken\dobforall}
\def\dobforall{\ifx\tmptoken\bgroup\expandafter\bforallbraces\fi
               \ifx\tmptoken[\expandafter\bforallbrackets\fi
               \ifx\tmptoken(\expandafter\bforallparenthesis\fi
               \relax}
\def\bforallbraces#1\relax#2{\{#2\}}
\def\bforallbrackets#1\relax[#2]{[#2]}
\def\bforallparenthesis#1\relax(#2){(#2)}

$\bforall{x}(x \in A)$\par
$\bforall{x}{x \in A}$\par
$\bforall{x}[x \in A]$\par

\bye

enter image description here

You can use those definitions also in LaTeX without the need of any package. The syntax seems easier for me \bforall{x}(x\in A), \bforall{x}{x\in A} and \bforall{x}[x\in A]. In any case, for your needs, may be you don't need that macro at all, just \def\bforall#1{\forall#1\,} and then it's followed by whatever you input?


With a little bit of refinement to let you use \bforall x {x \in A} syntax. (In LaTeX it would be easier because of \@ifnextchar.)

\def\bforall#1{\forall#1\,\futurelet\tmptoken\dobforall}
\def\dobforall{\ifx\tmptoken\spacetoken\expandafter\bforallspace\fi
               \ifx\tmptoken\bgroup\expandafter\bforallbraces\fi
               \ifx\tmptoken[\expandafter\bforallbrackets\fi
               \ifx\tmptoken(\expandafter\bforallparenthesis\fi
               \relax}
\def\bforallbraces#1\relax#2{\{#2\}}
\def\bforallbrackets#1\relax[#2]{[#2]}
\def\bforallparenthesis#1\relax(#2){(#2)}
\def\bforallspace#1\relax{\dobforallspace}
\expandafter\def\expandafter\dobforallspace\space{\futurelet\tmptoken\dobforall}
\lowercase{\let\spacetoken= } %

$\bforall x (x \in A)$\par
$\bforall x {x \in A}$\par
$\bforall x [x \in A]$\par

\bye
Manuel
  • 27,118