Sobald ein Befehl mehrere optionale Argumente oder eine echte Sternvariante haben soll, skaliert das Argumentzählen von \newcommand nicht mehr. Die moderne Antwort ist \NewDocumentCommand: Es deklariert die *Art* jedes Arguments als Buchstabenfolge. Ursprünglich war das eine Funktion des Pakets xparse, heute gehört es zum LaTeX-Kernel. Diese Seite behandelt die Mini-Sprache der Argumentspezifikation und die Tests, mit denen geprüft wird, was der Nutzer tatsächlich angegeben hat.
Heute Teil des Kernels
Früher brauchte man \usepackage{xparse}, aber seit der LaTeX-Version vom Oktober 2020 lebt diese Mechanik im Kernel selbst. Befehle wie \NewDocumentCommand sind sofort verfügbar, und xparse muss selten geladen werden. Die Kerneldatei dafür heißt ltcmd, und das Paket xparse selbst wird offiziell als „obsolete“ bezeichnet. Von wenigen veralteten Argumenttypen abgesehen, kann neuer Code diese Befehle ohne Zusatzpaket verwenden.
Die Idee dieser Schnittstelle ist, Bedeutung, also Interface, von der Implementierung zu trennen. Die Argumentfolge, die Nutzer sehen — Pflichtargumente, Optionen, Stern — wird als Argumentspezifikation (arg-spec) deklariert; der Körper erhält die Argumente immer in normalisierter Form als #1, #2 usw. Die Grundlagen von \newcommand stehen auf der Seite „Makros definieren“; wer sie kennt, sieht den Unterschied leichter.
Befehle und Umgebungen definieren
Die Grundform ist \NewDocumentCommand{\cmd}{⟨arg-spec⟩}{⟨code⟩}: Befehlsname, Argumentspezifikation, Körper. Wie \newcommand hat es Geschwister für verschiedene Zwecke; der Unterschied ist, wie sie auf bereits definierte Namen reagieren.
| Befehl | Bei vorhandenem Namen |
|---|---|
\NewDocumentCommand | Fehler, wenn schon definiert |
\RenewDocumentCommand | Fehler, wenn noch nicht definiert (arbeitet vorhandenen Befehl um) |
\ProvideDocumentCommand | Definiert nur, wenn noch nicht vorhanden |
\DeclareDocumentCommand | Überschreibt immer (sparsam verwenden) |
Für Umgebungen gibt es dieselbe Mechanik mit \NewDocumentEnvironment{⟨env⟩}{⟨arg-spec⟩}{⟨start code⟩}{⟨end code⟩} (sowie \Renew…, \Provide…, \Declare…). Die Argumente werden nach \begin{⟨env⟩} gegeben und sind sowohl im Start- als auch im Endcode sichtbar; siehe die Seite „Eigene Umgebungen“. Ein Bonus: Alle so erzeugten Befehle sind automatisch robust, intern über e-TeXs \protected, sodass in Überschriften oder Beschriftungen kein \protect nötig ist.
Es gibt außerdem die expandierbare Variante \NewExpandableDocumentCommand. Sie funktioniert in Kontexten, in denen ein Befehl expandiert wird, etwa in \edef oder \write; dafür sind die erlaubten Argumenttypen eingeschränkt. Boolesche Tests wie s/t und Verbatim v stehen dort nicht zur Verfügung. Für gewöhnliche Dokumente ist die normale Form richtig.
Die Sprache der Argumentspezifikation
Eine Argumentspezifikation ist eine Zeichenkette, in der jeder Buchstabe den Typ eines Arguments benennt: pflichtig, optional, Stern, durch bestimmte Zeichen begrenzt usw. Jeder Typ kommt im Körper als #1, #2 usw. an; die wichtige Feinheit ist, dass ein nicht angegebenes optionales Argument einen besonderen Wert erhält. Die wichtigsten Typen stehen in der Tabelle.
| Typ | Schreibweise | Bedeutung | Ankunft im Körper |
|---|---|---|---|
m | m | Pflichtargument {} | Normales #1 |
o | o | Optionales [...]-Argument | -NoValue-, wenn fehlend |
O | O{default} | Optional mit Standardwert | default, wenn fehlend |
s | s | Optionaler Stern * | \BooleanTrue / \BooleanFalse |
t | t⟨char⟩ | Optionales bestimmtes Zeichentoken | \BooleanTrue / \BooleanFalse |
r | r⟨d1⟩⟨d2⟩ | Pflichtargument, begrenzt durch d1…d2 | -NoValue- nach Fehler, wenn fehlend |
d | d⟨d1⟩⟨d2⟩ | Optional, begrenzt durch d1…d2 | -NoValue-, wenn fehlend |
e | e{⟨tokens⟩} | Verzierungen, z. B. ^, _ | Jeweils -NoValue-, wenn fehlend |
v | v | Verbatim-Argument | Die wörtlichen Zeichen |
m ist das grundlegende Pflichtargument; es akzeptiert eine Klammergruppe oder ein einzelnes Token, und äußere {} werden entfernt, bevor der Körper es sieht. o ist das übliche optionale [...]-Argument, O{default} dasselbe mit Standardwert. Großbuchstabentypen wie O und D erlauben einen Standardwert; die Kleinbuchstaben o/d liefern stattdessen den Spezialmarker -NoValue-.
s erkennt einen führenden Stern *: vorhanden ergibt \BooleanTrue, fehlend \BooleanFalse. Die Verallgemeinerung auf ein einzelnes Zeichen ist t⟨char⟩; t+ meldet etwa das Vorhandensein von + als Bool. r⟨d1⟩⟨d2⟩ ist ein pflichtiges, von selbst gewählten Begrenzern eingeschlossenes Argument, etwa r() für runde Klammern; fehlt der öffnende Begrenzer, gibt es einen Fehler und -NoValue-. d⟨d1⟩⟨d2⟩ ist die optionale begrenzte Variante.
Etwas spezieller ist e{⟨tokens⟩}, das Verzierungen wie ^ und _ sammelt. Mit e{^_} nimmt es ^{...} und _{...} in beliebiger Reihenfolge auf; nicht angegebene Verzierungen werden -NoValue-. Die angegebenen Tokens müssen verschieden sein. v liest ein Verbatim-Argument ähnlich \verb. Bei begrenzten Typen wie r und d dürfen die TeX-Gruppierungszeichen { und } nicht als Begrenzer dienen; üblich sind natürlich gepaarte Zeichen wie [], () oder "".
Argumente prüfen: die Tests
Für optionale Argumente oder Sterne muss der Körper prüfen, ob etwas angegeben wurde. Dafür gibt es zwei Befehlsfamilien. \IfNoValueTF{#1}{⟨if no value⟩}{⟨if value⟩} prüft, ob das Argument -NoValue- ist, also fehlte: Fehlt es, läuft der erste Zweig, andernfalls der zweite. Die Umkehrung \IfValueTF existiert ebenfalls, ebenso Einzelzweigformen (\IfNoValueT / \IfNoValueF, \IfValueT / \IfValueF).
Für Boolesche Werte aus s oder t verwendet man \IfBooleanTF{#1}{⟨if starred⟩}{⟨if not⟩}. Ist #1 \BooleanTrue, läuft der erste Zweig; bei \BooleanFalse der zweite. Auch \IfBooleanT / \IfBooleanF gibt es. Faustregel: \IfNoValueTF und Verwandte sind für optionale Argumente wie o/d; \IfBooleanTF und Verwandte für Bool-Argumente aus s/t. Außerdem ist -NoValue- so gebaut, dass es nicht mit dem wörtlichen Text -NoValue- übereinstimmt; testen Sie es daher immer mit \IfNoValueTF.
Ein Beispiel: Stern plus Option mit Standard
Mit der Spezifikation s O{} m bauen wir einen Befehl mit Sternvariante und optionalem Argument mit Standard. Als Beispiel dient ein Überschriftenbefehl: #1 ist der Stern, geprüft mit \IfBooleanTF, #2 die optionale Kurzüberschrift mit leerem Standard, #3 die Hauptüberschrift.
\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} % 星つき: 太字の無番号見出しEine Feinheit: Verwechseln Sie o und O{} nicht. Mit o wird ein nicht angegebenes Argument zu -NoValue-, also verzweigt man wie oben mit \IfNoValueTF. Mit O{} ist dagegen immer ein Wert vorhanden, leer wenn ausgelassen; dann prüft man auf Leere, etwa mit \tl_if_blank:nTF (expl3) oder \ifblank (etoolbox), nicht mit \IfNoValueTF. Im obigen Beispiel müsste das optionale Argument o ohne Standard sein, damit der \IfNoValueTF-Zweig wie beabsichtigt arbeitet.
Warum es \newcommand schlägt
\newcommand erlaubt nur ein optionales Argument, und zwar das erste, und bietet keine eingebaute Sternvariante. Klassisch schrieb man dafür Low-Level-Mechanik wie \@ifstar und \@ifnextchar von Hand; diese braucht \makeatletter, ist bei Leerraum und Schachtelung empfindlich und schlecht lesbar.
- Mehrere unabhängige optionale Argumente (
o o m,O{a} O{b} musw.). - Echte Sternvarianten über
splus\IfBooleanTF, ohne\@ifstar-Trick. - Deklarative Standardwerte:
O{default}legt den Wert bei Auslassung fest. - Von Anfang an robust: kein
\protectin Überschriften oder Beschriftungen. - Eingabesyntaxen, die
\newcommandnicht ausdrücken kann: begrenzte Argumente (r,d) und Verzierungen (e).
Kurz: Eine einfache Abkürzung ist mit \newcommand gut aufgehoben, aber sobald die Argumentstruktur nur etwas anspruchsvoller wird, ist \NewDocumentCommand die erste Wahl. Wenn der Körper danach als kleines Programm geschrieben werden soll, ist die Kombination mit expl3, der LaTeX3-Programmierschicht, der natürliche nächste Schritt. Für Klassen und Pakete siehe die Autorenseite.