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}
xparse
and\NewDocumentCommand
which supports this out of the box. It is part of the development of the LaTeX 3 project.