130

I would like to define a *'d version of a command, something like

\newcommand{\foo}{blah}
\newcommand{\foo*}{blahblah}

If I try to do this, LaTeX complains that I'm trying to redefine \foo, so I guess I need to do something special to handle *s. But what?

1
  • 5
    Of the different replies given: what is currently the recommended answer to this question? Feb 23, 2016 at 7:49

3 Answers 3

85

See this entry in the TeX FAQ.

The "elegant" way is to use the suffix package (which requires eTeX):

\documentclass{article}

\usepackage{suffix}
\newcommand\foo{blah}
\WithSuffix\newcommand\foo*{blahblah}

\begin{document}

\foo

\foo*

\end{document}
5
  • Does this work with commands with optional arguments too? If so how?
    – jan-glx
    Mar 11, 2014 at 10:59
  • 1
    @YAK I don't know. Note that the combination starred/optional is very rare.
    – lockstep
    Mar 11, 2014 at 11:37
  • 1
    Ups, I meant normal arguments, not optionals. And it works (\WithSuffix\newcommand\foo*[1]{Foo #1}) but warns "No 2nd argument following newcommand"...
    – jan-glx
    Mar 11, 2014 at 12:13
  • Maybe I misunderstood what you meant, and maybe the package has changed since then, but; \WithSuffix\newcommand\mycommand*[3]{starred command #1 #2 #3} works fine (\mycommand*{1}{2}{3})
    – Mogu
    Jul 25, 2019 at 9:22
  • 1
    Note that when using \WithSuffix, the name of the new command \foo* apparently cannot be surrounded by brackets {...} in the definition.
    – Paul Wintz
    Sep 25, 2022 at 5:48
89

If you look at source2e you might see a lot of lines that look like

\def\foo{\@ifstar\@foo\@@foo}
\def\@foo#1{...}
\def\@@foo#1{...}

This makes \foo a one-argument command that has regular and starred versions. The starred version is the expansion of \@foo while the nonstarred version is that of \@@foo. Using the @ sign in the auxiliary macros is a TeX convention which some authors embrace and some avoid.

There are higher-level ways to do it (as lockstep points out) but once you learn this pattern it's not too hard to use. Just make sure it's between \makeatletter...\makeatother or in a .sty file.

Edits removed some inaccuracies and editorializing.

3
  • 1
    What's the controversy with @? FWIW, it's also used in Plain and ConTeXt (although far less in the latter, which do is more common, leading to some funny command names such as \dodohideblock). Oct 22, 2010 at 3:22
  • 2
    Let me be clear that I follow the @-convention and am not advocating against it. But I can also see the point of view that the name \@foo (or \f@o or \f@@) doesn't help the human reader understand the relationship. \@foowithstar and \@foowithoutstar might be better. Sorry if I blew that internal ambivalence into a controversy. :-) Also, I wanted to point out that @'s are not required in auxiliary macros. Oct 22, 2010 at 11:12
  • 14
    Yes, using '@' in place of vowels is a pain in the neck, whereas using it as a divider is fine.
    – Joseph Wright
    Oct 23, 2010 at 17:39
81

LaTeX3 solution:

\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\foo{s}{%
  \IfBooleanTF#1%
    {blahblah}% If a star is seen
    {blah}%     If no star is seen
}
1
  • 1
    This was the only solution that worked for me when using \dekotenize in the command and invoking the command from the caption of a lstlisting. Oct 5, 2021 at 20:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .