xparse (\NewDocumentCommand)

Once you want a command with several optional arguments, or a proper starred variant, counting arguments the \newcommand way no longer scales. The modern answer is \NewDocumentCommand, which declares the *kind* of each argument as a string of letters. It began life in the xparse package but is now part of the LaTeX kernel. This page covers the argument-specification mini-language and the test commands that inspect what the user actually supplied.

Now part of the kernel

You used to need \usepackage{xparse}, but since the October 2020 LaTeX release this machinery lives in the kernel itself. Commands like \NewDocumentCommand are available out of the box, and loading xparse is rarely necessary. The kernel file that implements it is called **ltcmd**, and the xparse package is now officially described as “obsolete.” Apart from a handful of deprecated argument types, new code can simply use these commands without loading anything.

The idea behind this interface is to separate meaning from implementation. You declare the sequence of arguments a user sees — mandatory, optional, starred — as an *argument specification* (arg-spec), and your body code always receives the arguments in a normalized form as #1, #2, and so on. The basics of \newcommand are covered on the “Defining macros” page; if you have not read it, doing so first makes the contrast clearer.

Defining commands and environments

The basic form is **\NewDocumentCommand{\cmd}{⟨arg-spec⟩}{⟨code⟩}**: the command name, then the argument specification, then the body. As with \newcommand, there are siblings for different purposes; what differs is how each behaves toward a name that is already defined.

CommandOn an existing name
\NewDocumentCommandErrors if already defined
\RenewDocumentCommandErrors if not yet defined (reworks it)
\ProvideDocumentCommandDefines it only if not already given
\DeclareDocumentCommandAlways overwrites (use sparingly)

Environments get the same treatment via **\NewDocumentEnvironment{⟨env⟩}{⟨arg-spec⟩}{⟨start code⟩}{⟨end code⟩}** (with \Renew…, \Provide…, and \Declare… too). The arguments are given after \begin{⟨env⟩} and are visible to both the start and end code; see the “Custom environments” page. One bonus: every command made this way is automatically robust (it uses ε-TeX’s \protected mechanism internally), so you need not worry about \protect in a heading or caption.

There is also an expandable variant, **\NewExpandableDocumentCommand**. It can be used in contexts where a command is *expanded* — inside \edef or \write, say — but in exchange the argument types it allows are restricted (boolean tests like s/t and verbatim v, below, are not available). For ordinary document work the standard definer is what you want.

The argument-specification language

An argument specification is **a string in which each letter names the *type* of one argument** — mandatory, optional, starred, delimited by particular characters, and so on. Each type arrives in the body as #1, #2, and so on, but the key subtlety is that an optional argument that was not supplied receives a special value. The main types are summarized below.

TypeWritten asMeaningHow it arrives
mmMandatory {} argumentAn ordinary #1
ooOptional [...] argument-NoValue- if absent
OO{default}Optional, with a defaultThe default if absent
ssAn optional star *\BooleanTrue / \BooleanFalse
tt⟨char⟩An optional given char token\BooleanTrue / \BooleanFalse
rr⟨d1⟩⟨d2⟩Required, delimited by d1d2-NoValue- after an error if absent
dd⟨d1⟩⟨d2⟩Optional, delimited by d1d2-NoValue- if absent
ee{⟨tokens⟩}Embellishments (e.g. ^, _)Each -NoValue- if absent
vvA verbatim argumentThe literal characters

m** is the basic mandatory argument; it accepts a braced group or a single token, and the outer {} is stripped before the body sees it. **o** is the standard optional [...] argument, and **O{default} is the same with a default value. The uppercase types such as O and D let you give a default**, while their lowercase counterparts o/d return the special marker -NoValue- instead.

s** detects a leading star *: present gives \BooleanTrue, absent gives \BooleanFalse. Generalized to any single character, **t⟨char⟩** tests for that token — t+, for instance, reports the presence of + as a boolean. **r⟨d1⟩⟨d2⟩** is a *required* delimited argument enclosed by delimiters you choose (say r() for parentheses); if the opening one is missing it raises an error and inserts -NoValue-. The optional-but-delimited version is **d⟨d1⟩⟨d2⟩**.

A more unusual one is **e{⟨tokens⟩}, which gathers embellishments** such as ^ and _. With e{^_} it picks up ^{...} and _{...} in any order, and any that are not supplied become -NoValue- (the tokens you list must all be distinct). **v reads a verbatim** argument, much like \verb. Note that the delimiters for the delimited types (r, d, …) cannot be the TeX grouping characters { and }, so the convention is to pick naturally paired characters such as [], (), or "".

Inspecting arguments: the tests

To handle an optional argument or a star, you need to test inside the body whether it was supplied. Two families of commands do this. First, **\IfNoValueTF{#1}{⟨if no value⟩}{⟨if value⟩}** checks whether the argument is -NoValue- (i.e. was not given): if there is no value it runs the first branch, otherwise the second. The reverse, **\IfValueTF**, also exists, and there are single-branch forms (\IfNoValueT / \IfNoValueF, \IfValueT / \IfValueF).

For the boolean produced by s or t, use the dedicated **\IfBooleanTF{#1}{⟨if starred⟩}{⟨if not⟩}**: if #1 is \BooleanTrue it runs the first branch, if \BooleanFalse the second (single-branch \IfBooleanT / \IfBooleanF exist too). The rule of thumb: **\IfNoValueTF and friends are for optional arguments like o/d; \IfBooleanTF and friends are for the boolean s/t.** Also, -NoValue- is built so that it does *not* match the literal text -NoValue-, so always test it with \IfNoValueTF rather than comparing strings.

A worked example: star plus a defaulted option

Let us build a command with both a starred variant and an optional argument with a default, using the spec s O{} m. Here it is a heading command: #1 is the star (tested with \IfBooleanTF), #2 is an optional short title (default empty), and #3 is the main title.

latex
\NewDocumentCommand{\heading}{s O{} m}{%
  \IfBooleanTF{#1}%
    {\textbf{#3}}%                       星つき: 番号なしの見出し / starred: unnumbered
    {\section%
       \IfNoValueTF{#2}%
         {{#3}}%                          短縮見出しなし / no short title
         {[#2]{#3}}%                       短縮見出しあり / with short title
    }%
}

% 使用例 / usage
\heading{Introduction}             % 通常の番号つき節
\heading[Intro]{A Long Introduction} % 目次用に短縮見出しを指定
\heading*{Preface}                 % 星つき: 太字の無番号見出し

A subtlety: do not mix up o and O{}. With o, an unsupplied argument becomes -NoValue-, so you branch on it with \IfNoValueTF exactly as above. With O{}, by contrast, a value is *always* present (empty when omitted), so there you test for *emptiness* — with \tl_if_blank:nTF (expl3) or \ifblank (etoolbox) — rather than \IfNoValueTF. In the example above, making the optional argument o (no default) is what makes the \IfNoValueTF branch behave as intended.

Why it beats \newcommand

\newcommand allows only one optional argument — the first — and offers no built-in starred variant. The classic workaround was to hand-write low-level plumbing like \@ifstar and \@ifnextchar, but those require \makeatletter, are fragile around spaces and nesting, and are hard to read.

  • Multiple, independent optional arguments (o o m, O{a} O{b} m, …).
  • True starred variants via s plus \IfBooleanTF — no \@ifstar hack.
  • Declarative defaults: writing O{default} is all it takes to fix the value when omitted.
  • Robust from the start: no \protect needed in headings or captions.
  • Input syntaxes \newcommand cannot express — delimited arguments (r, d) and embellishments (e).

In short, a plain abbreviation is fine with \newcommand, but **the moment the argument structure gets even slightly elaborate, \NewDocumentCommand is the first choice.** When you then want to write the body as a small program, pairing it with expl3 (the LaTeX3 programming layer) is the natural next step. For building classes and packages, see the “Authoring classes & packages” page.