10

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.

11

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 tex.stackexchange.com/questions/254158/… – touhami Aug 4 '15 at 3: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 4 '15 at 9:50
  • Sorry, i mean @egreg's last comment, in this case $\bforall[rs]{x}{x \in A}$ – touhami Aug 4 '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 4 '15 at 10:12
  • here is the prolem $\bforall[rs]{x}{x \in A}$ will not idicate error. – touhami Aug 4 '15 at 10:46
5

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

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

1

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

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.