Defining a command to define an asterisk command
No dependencies on packages, only on the LaTeX kernel.
\documentclass{article}
\newcommand{\genericcmd}[3]{#1 #3 #2}
\newcommand{\genericcmdstarred}[3]{#1 starred, #3 #2}
\makeatletter
\newcommand\metadef[3]{%
\DeclareRobustCommand#1{%
\@ifstar{\csname s\string#1\endcsname}{\csname n\string#1\endcsname}%
}%
\@namedef{s\string#1}##1{\genericcmdstarred{#2}{#3}{##1}}%
\@namedef{n\string#1}##1{\genericcmd{#2}{#3}{##1}}%
}
\makeatother
\metadef{\mynewcommand}{Hello}{world}
\begin{document}
\mynewcommand{big}.
\mynewcommand*{big}.
\end{document}
More interesting, perhaps, is a definition without the need to define \genericcmd
and \genericcmdstarred
. The command \metadef
has the same syntax as \newcommand
(but no *
version, which could be added with some more trickery), but with an argument more:
\metadef{<macro name>}[<args>]{<code for normal version>}{<code for starred version>}
Optional arguments to the defined macro are not allowed, use the following xparse
based code for adding whatever list of arguments you want.
\documentclass{article}
\makeatletter
\newcommand{\metadef}[1]{%
\DeclareRobustCommand#1{%
\@ifstar{\csname s\string#1\endcsname}{\csname n\string#1\endcsname}%
}%
\edef\meta@def@name{\string#1}%
\meta@def
}
\newcommand\meta@def[3][0]{%
\expandafter\newcommand\csname n\meta@def@name\endcsname[#1]{#2}%
\expandafter\newcommand\csname s\meta@def@name\endcsname[#1]{#3}%
}
\makeatother
\metadef{\mynewcommand}[1]{Hello #1 world}{Hello starred, #1 world}
\begin{document}
\mynewcommand{big}.
\mynewcommand*{big}.
\end{document}
The same with suffix
:
\documentclass{article}
\usepackage{suffix}
\makeatletter
\newcommand{\metadef}[1]{%
\def\meta@def@name{#1}%
\meta@def
}
\newcommand\meta@def[3][0]{%
\expandafter\newcommand\meta@def@name[#1]{#2}%
\WithSuffix\expandafter\newcommand\meta@def@name*[#1]{#3}%
}
\makeatother
\metadef{\mynewcommand}[1]{Hello #1 world}{Hello starred, #1 world}
\begin{document}
\mynewcommand{big}.
\mynewcommand*{big}.
\end{document}
The same with xparse
, where you just have to remember of shifting by one the number of the arguments, because #1
is the possible *
. The arguments to the “metadefined” macro must be expressed in xparse
syntax, of course.
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\metadef}{mmmm}{%
\NewDocumentCommand{#1}{s#2}{%
\IfBooleanTF{##1}{#4}{#3}%
}%
}
\metadef{\mynewcommand}{m}{Hello #2 world}{Hello starred, #2 world}
\begin{document}
\mynewcommand{big}.
\mynewcommand*{big}.
\end{document}
I would recommend using xparse
which is part of the work by the LaTeX 3 project developers.
The following emulates the code in the question except that it eliminates the spurious space caused by the unstarred version of the command.
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand \mynewcommand { s m }
{%
Hello
\IfBooleanT {#1}
{%
starred,
}%
#2 world%
}
\begin{document}
\mynewcommand{big}.
\mynewcommand*{big}.
\end{document}
No dependencies on packages, no dependencies on LaTeX kernel:).
\def\isnextchar#1#2#3{\toks0={#2}\toks1={#3}%
\let\tmp=#1\futurelet\next\isnextcharA}
\def\isnextcharA{\the\toks\ifx\tmp\next0\else1\fi\space}
\def\metadef#1#2#3{\def#1{\isnextchar*{\metadefA{#3}}{\metadefB{#2}}}}
\def\metadefA#1*{\def\tmp##1{#1}\tmp}
\def\metadefB#1{\def\tmp##1{#1}\tmp}
\metadef \mynewcommand {Hello ##1 world} {Hello starred, ##1 world}
\mynewcommand{big}.
\mynewcommand*{big}.