TUGboat, Volume 42 (2021), No. 1

41kernel, and in a parallel article (starts on the preceding page) I’ve provided some ideas about how best
to exploit that.
In this article, I want to look at a related issue:
why to use this ‘xparse’ approach, and how it compares to existing solutions, both in the LATEX kernel
and the wider package sphere. Here, I’m going toavoid talking about ‘simple’ shortcuts (things such as\newcommand\myname{Joseph}): these are best left
to \newcommand. Instead, I want to deal with commands which take arguments and have some elementof ‘programming’ to them.
What I’ll seek to highlight here is that using\NewDocumentCommand, we get a single consistentand reliable way to create a variety of commands.
There’s no need to worry about clashes between
approaches, and it all ‘just works’.
1\NewDocumentCommand versus \newcommandversus . . .
Joseph WrightCreating new document commands in LATEX has
traditionally been the job of \newcommand. This lets
you create a command with mandatory arguments,and also support a first optional argument. However,it can’t create more complex commands: LATEX uses
stars, multiple optional arguments, and plenty more.
To define commands using such syntaxes, the kernel
itself uses lower-level TEX programming. But thisis opaque to many users, and a variety of packages
have been created to ease the burden.
Over the last decade, the LATEX team have developed xparse, a generic document command parser,
as a way to unify many ideas and provide a single
consistent way to create document commands. Thebulk of that code has now been moved to the LATEXPreliminaries: Protected commands andoptional arguments

Before we start, a couple of things are worth mentioning. First, there is the idea of ‘protected’ commands.
In some places, we need commands not to ‘expand’(turn into their definition). With a modern TEX
system, that can be arranged by the engine itself(pdfTEX or similar), using ε-TEX’s \protected primitive (built-in). The LATEX kernel doesn’t use thatmechanism in \newcommand, but lots of other tools
do. I’m going to assume that we want to make protected commands unless I mention otherwise. Almost
always, unless you are creating a ‘shortcut’ for sometext, you want your commands to be protected.
The second thing to note is that TEX itself has
no concept of optional arguments, so they are always arranged using some clever look-ahead code.
In xparse, nested optional arguments are handled
automatically, but again, \newcommand and similar
do not do that.
2

The kernel: versus \newcommand

The kernel’s \newcommand can, as I’ve said, createcommands with multiple mandatory arguments butwith only one optional one. A simple example:\newcommand\foo[3][default]{%
Code perhaps using #1 anddefinitely using #2 and #3%}
We can of course create an equivalent command using\NewDocumentCommand:\NewDocumentCommand\foo{+O{default} +m +m}{%
Code perhaps using #1 anddefinitely using #2 and #3%}
\NewDocumentCommand versus \newcommand versus . . .

doi.org/10.47397/tb/42-1/tb130wright-newdoccmd

42

TUGboat, Volume 42 (2021), No. 1

You may notice that I’ve used +m for both of themandatory arguments, as that matches \newcommand:
the arguments can accept paragraphs (is \long, inTEX terms). With \newcommand, all arguments either
accept \par or do not: with \NewDocumentCommand
we can select on a per-argument level what happens.
The optional argument with a default works
using O{default}, and the result will be the samefunctionality as \newcommand. We gain the idea thatnested optional arguments are parsed properly, somebetter error messages if we use \foo incorrectly, andan engine-robust definition of \foo.
We can’t do a lot more with \newcommand, so
rather than try to show other \NewDocumentCommandfeatures here, we’ll first consider how we might makemore complex syntaxes using just the classical LATEX
kernel.

\NewDocumentCommand\section{s +O{#3} +m}{%% Here:% #1 is "true"/"false" for a star% #2 is the optional argument% #3 is the mandatory argument}

3The etoolboxpackage offers \newrobustcmd as a complement to \newcommand. It provides exactly thesame interface as \newcommand, except it uses ε-TEXto make engine-protected commands. Here’s an interface point of view, there’s nothing new here.

. . . versus \def: The primitive

Using the TEX primitive \def, plus the kernel internal commands \@ifstar and \@ifnextchar, wecan construct more complex syntaxes. For example,
let’s create the syntax for \section: a star, an optional argument and a mandatory one. I’ll assume
we have @ defined as a letter here. I’m also goingto pass the presence of a star as the text true or
false, as it makes things clearer.
\newcommand\section{%\@ifstar{\section@auxi{true}}{\section@auxi{false}}%}\def\section@starred#1{%\@ifnextchar[%]{\section@auxii{#1}}{\section@auxii{#1}[]}%}\long\def\section@auxii#1[#2]#3{%% Here:% #1 is "true"/"false" for a star% #2 is the optional argument% #3 is the mandatory argument}
As you can see, this is a bit tricky already, andit doesn’t cover the case where we want to have theoptional argument default to the mandatory one,when it’s not given. It also doesn’t allow for nested
optional arguments, and it’s not engine-robust. We
might of course use more complex paths for the star:
we could have independent routes.
Using \NewDocumentCommand, things are mucheasier:Joseph Wright

The minor difference now is that #1 is a special
token that we can test for truth using \IFBooleanTF.
I’ve also allowed for the optional argument picking
up the mandatory one (#3), when it’s not given.
We could make more complex examples, but thebottom line is: using \NewDocumentCommand, we aregoing to have simple one-line interface descriptions,and the behind-the-scenes TEX argument parsing ishidden away.
4

5. . . versus \newrobustcmd: etoolbox. . . versus \newcommandtwoopt: twoopt

The twoopt package supports a syntax similar to\newcommand but for creating two optional arguments. We’ll take an example from its documentation:\newcommandtwoopt\bsp[3][AA][BB]{%\typeout{\string\bsp: #1,#2,#3}%}
This is reasonably clear: we have an optional argument #1, and optional argument #2 and a mandatory
argument #3. The two optional arguments each here
have a default.
How does this look with \NewDocumentCommand?
\NewDocumentCommand\bsp{+O{AA} +O{BB} +m}{%\typeout{\string\bsp: #1,#2,#3}%}
You’ll see that we stay consistent here: the same syntax is used to create one, two or even more optional
arguments. I wouldn’t recommend using multiple
optional arguments in most cases, but when we do,it’s a lot easier using \NewDocumentCommand.
One thing that \NewDocumentCommand can do,
but twoopt cannot, is create optional arguments thatare not in the first or second positions. With twoopt, that would require either the TEX coding we’vealready seen, or using a different tool again.

TUGboat, Volume 42 (2021), No. 1
643. . . versus \withsuffix: suffix

The suffix package allows one to extend an existingcommand to look for an optional token (‘suffix’)
immediately after the command name. Taking asimple example from StackExchange (https://tex.
stackexchange.com/a/4388), we start with
\newcommand\foo{blah}\WithSuffix\newcommand\foo*{blahblah}which translates to\NewDocumentCommand\foo{s}{%\IFBooleanTF{#1}{blah}{blahblah}}
This means we only need one line for the interface set up, and don’t need, for example, to split
up grabbing optional arguments into two different
places (as in the previous example with \section).
7. . . versus \newcommandx: xargs

The xargs package is perhaps the most complete approach to extending \newcommand as far as optional
arguments are concerned. It provides \newcommandx,
which has the same syntax as \newcommand but
where the second optional argument is a key–value
list, which then describes which arguments are optional, and what their defaults are. Taking an example from the documentation:\newcommandx*\coord[3][2=1,3=n]{%(#2_{#1},\ldots,#2_{#3})}
would create a command with two optional arguments, #2 and #3 (each with defaults), leaving #1
mandatory. Translating into \NewDocumentCommand
syntax might make that clearer!
\NewDocumentCommand\coord{m O{1} O{n}}{%(#2_{#1},\ldots,#2_{#3})%}
The xargs package has the idea of usedefault,
which allows [] to be the same as [default]. That’s
not something xparse does, as it is pretty confusing:what happens when you want an empty optional
argument? This links to something I’ve said before: avoid consecutive optional arguments unlessthe second is dependent on the first.
8. . . versus newcommand.py: newcommand

Stepping outside of TEX itself, Scott Pakin’s Python script newcommand.py provides a description
language somewhat like xparse, and converts this intoa ‘template’ of TEX code, allowing a ‘fill in the blanks’approach to creating commands. It can cover severalof the ideas that xparse can, including a few that will

not be migrated to the LATEX kernel. It can also setup a command taking more than 9 arguments, but
that’s always going to be tricky as a user.
What is important is that using a script means
we have to work in two steps, and it’s hard to see
what’s happening from the TEX source. It alsodoesn’t offer anything that the kernel doesn’t alreadydo: no protected commands, no nested optional arguments, no improved error messages. So in manyways this is using techniques we’ve already seen, justmade a little more accessible, at least if you have
Python installed.
9. . . versus \NewEnviron: environ

As well as document commands, the xparse syntax
can be used to create document environments: thesame relationship we have between \newcommand and\newenvironment. What people sometimes want to
do is grab an entire document environment body anduse it like a command argument. Classically, one
does that using the environ package. Again, taking
an example from the documentation:\NewEnviron{test}{%\fbox{\parbox{1.5cm}{\BODY}}\color{red}\fbox{\parbox{1.5cm}{\BODY}}%}
would grab all of the body of the environment test
and typeset it twice, the first time in red. That is,
the environment body is saved as \BODY.
Using \NewDocumentEnvironment, we have asyntax similar to \newenvironment\NewDocumentEnvironment{test}{+b}{%\fbox{\parbox{1.5cm}{#1}}\color{red}\fbox{\parbox{1.5cm}{#1}}%}{}
with the argument grabbed in the normal way as(here) #1. We can therefore have ‘real’ arguments
first, then grab the body.
10SummaryUsing the tools set up in \NewDocumentCommand, we
can have a consistent way of creating a wide rangeof document commands. Rather than use a mixtureof tools, from the kernel, the TEX engine, and the
package sphere, it is far preferable to use the single
interface of \NewDocumentCommand for defining newcommands today.
⋄ Joseph WrightNorthampton, United Kingdom
joseph dot wright (at)morningstar2.co.uk\NewDocumentCommand versus \newcommand versus . . .