# Macro to add starred version of command

How can one write a meta-macro that adds a starred version to a command?

Intended use would be along the lines of

\newcommand\foo[1]{foo is #1}
\addstarred\foo[2]{foo is #1, bar is #2}

• Something like \WithSuffix? Than this answer can be usefull: tex.stackexchange.com/a/4388/3061 – quinmars Sep 22 '14 at 9:05
• Could you maybe explain how the \WithSuffix command works? – user53911 Sep 22 '14 at 9:11
• Sorry I have no idea how it works internally. But a possible use case is shown in the linked answer. – quinmars Sep 22 '14 at 9:13
• This is definitely a duplicate. Maybe you want to turn it into a question about how \WithSuffix works. It does quite similarly to what you propose, by the way. The code is \WithSuffix\newcommand\foo*[2]{foo is #1, bar is #2} (with \usepackage{suffix}). – egreg Sep 22 '14 at 9:44
• I do not actually ask how to define starred versions, I can do that quickly enough with three separate commands. Being a programmer, I am curious how to do macro-writing macros in LaTeX. And I figured this is an interesting case that is actually useful. – user53911 Sep 22 '14 at 10:03

A method is already available with the package suffix by David Kastrup. Needless to say, it's full of clever tricks.

You can say

\usepackage{suffix}

\newcommand{\foo}[1]{foo is #1}
\WithSuffix\newcommand\foo*[2]{foo is #1, bar is #2}


and it may be instructive to see how the objective is achieved.

If we do \show\foo after the second instruction, we find

> \foo=\protected macro:
->\WSF@suffixcheck \foo .


so we learn that suffix requires e-TeX (not a problem nowadays) and redefines \foo to mean \WSF@suffixcheck\foo. So we add \makeatletter and try \show\WSF@suffixcheck, getting

> \WSF@suffixcheck=macro:
#1->\begingroup \def \reserved@a {#1}\futurelet \reserved@b \WSF@suffixcheckii


so the argument is saved in \reserved@a and

\futurelet\reserved@b\WSF@suffixcheckii


is executed. This makes \reserved@b to be equivalent to the token that follows \WSF@suffixcheckii. If the call is

\foo{foo}


then \reserved@b will be \bgroup; if the call is

\foo*{foo}{bar}


then \reserved@b will be *. Now we need to know what \WSF@suffixcheckii does:

> \WSF@suffixcheckii=macro:
->\ifcsname \expandafter \SuffixName \reserved@a \reserved@b \endcsname
\expandafter \WSF@suffixcheckiii \else \expandafter \WSF@suffixcheckiv \fi .


OK, let's see what happens in the \foo{foo} case: \reserved@a expands to \foo, while \reserved@b is \bgroup (unexpandable), so TeX is first presented with

\ifcsname\SuffixName\foo\reserved@b\endcsname


and \SuffixName is defined by

> \SuffixName=\long macro:
#1->WSF:\string #1 \meaning .


so the next step is

\ifcsname WSF:\string\foo \meaning\reserved@b\endcsname


and we finally get

\ifcsname WSF:\foo begin-group character {\endcsname


where all characters have category code 12 (but spaces have 10). In the \foo*{foo}{bar} case we would get

\ifcsname WSF:\foo the character *\endcsname


The command \csname WSF:\foo begin-group character {\endcsname is not defined, so the false branch is followed, that is

\expandafter \WSF@suffixcheckiv \fi


which simply leaves

\WSF@suffixcheckiv{foo}


in the input stream. Now \show\WSF@suffixcheckiv gives

> \WSF@suffixcheckiv=macro:
->\expandafter \endgroup \csname \expandafter \NoSuffixName \reserved@a \endcsname .


so the group previously opened is closed but first

\csname \expandafter \NoSuffixName \reserved@a \endcsname


is formed. Recall that \reserved@a expands to \foo, so we get

\csname \NoSuffixName \foo \endcsname


and \NoSuffixName is

> \NoSuffixName=macro:
->WSF:\string .


so finally we obtain

\csname WSF:\string\foo\encsname


OK, let's issue \expandafter\show\csname WSF:\string\foo\endcsname:

> \WSF:\foo=\long macro:
#1->foo is #1.


that is, this complicated macro is a copy of the original \foo.

In the case of \foo*{foo}{bar} we'd have

\ifcsname WSF:\foo the character *\endcsname


but in this case this is defined; indeed

\expandafter\show\csname WSF:\string\foo\space the character *\endcsname


produces

> \WSF:\foo the character *=\long macro:
#1#2->foo is #1, bar is #2.


so this macro with a complicated name is what you have defined as *-variant.

Almost any token can be used as a suffix, with this package. But the essential idea is no different from what you have devised; the protections against overwriting possible existing macro names are better. What the package does when

\WithSuffix\newcommand\foo*[2]{foo is #1, bar is #2}


is processed is

1. Save the original \foo command under

\csname WSF:\string\foo\endcsname


(if this already exists because of a preceding \WithSuffix applied to \foo this step is of course omitted)

2. Save the new definition under

\csname WSF:\string\foo\space the character *\endcsname

3. Use the abstract interface described above to choose among different suffixes.

• Great explanation. If I understood the method well, this basically turns the simplistic if next-token == '*' into a switch-like construct selecting whatever command has been defined for a given suffix. – user53911 Sep 22 '14 at 12:54
• @Nicolas Yes, and in a clever way for transforming the suffix into a string and avoiding expansion problems. However I much prefer the xparse method. – egreg Sep 22 '14 at 13:18

My own attempt at a solution is below, with improvements kindly provided by @egreg and @DavidCarlisle.

\documentclass{standalone}

\makeatletter
\expandafter\let\csname\string#1@nostar\endcsname#1%
\edef#1{\noexpand\@ifstar\expandafter\noexpand\csname\string#1@star\endcsname\expandafter\noexpand\csname\string#1@nostar\endcsname}%
\expandafter\newcommand\csname\string#1@star\endcsname%
}
\makeatother

\newcommand\foo[1]{foo is #1}
\addstarred\foo[2]{foo is #1, bar is #2}

\begin{document}
\foo{red} --- \foo*{red}{green}
\end{document}


Result:

Explanation:

• A copy of the current definition of the command \foo is stored as \\foo@nostar.
• The command \foo is redefined to check for a star and call either \\foo@star or \\foo@nostar. This is done with edef so that the constructed token names can be expanded in place and not every time the command is invoked.
• A \newcommand for \\foo@star is started and will take the rest of the definition as follows \addstarred\foo.
• Storing \foo in \\foo will definitely conflict if \foo had been defined to have an optional argument. – egreg Sep 22 '14 at 9:09
• Ah, interesting. Maybe the name of the commands should have been a little less obvious. – user53911 Sep 22 '14 at 9:12
• I have since edited the answer to be an epsilon amount less obvious. – user53911 Sep 22 '14 at 9:21
• You need a % on each of the lines of the definition that doesn't have a % and do not need a % on the line that has one. – David Carlisle Sep 22 '14 at 9:35
• @DavidCarlisle I have added the % to all lines now. I assumed that, since this should appear in the preamble, extra line breaks would not matter. – user53911 Sep 22 '14 at 9:45