Makros definieren

Wenn Sie dasselbe immer wieder tippen oder später überall zugleich ändern wollen, definieren Sie einen eigenen Befehl, also ein Makro. Die Grundlage ist \newcommand. Diese Seite behandelt die Basis eigener Befehle: Argumente, Neudefinition bestehender Befehle, das moderne \NewDocumentCommand und die Kunst, „fragile“ Befehle zu vermeiden.

Befehle mit \newcommand definieren

Das einfachste Werkzeug ist \newcommand{\name}{definition}. Das erste Argument ist der gewünschte Befehlsname, das zweite dessen Bedeutung. Wenn der Name Ihrer Arbeitsgruppe immer wieder auftaucht, definieren Sie ihn einmal in der Präambel; danach expandiert \name im Text zu definition.

latex
% プリアンブルで定義 / define in the preamble
\newcommand{\grp}{Knuth Typesetting Lab}

% 本文で使う / use it in the body
Welcome to the \grp. The \grp{} was founded in 1978.

Beachten Sie die {} hinter dem zweiten \grp. Ein nur aus Buchstaben bestehender Befehl wie \grp verschluckt das folgende Leerzeichen als Trenner des Befehlsnamens. \grp was verliert daher den Abstand und setzt eher „Labwas“ als „Lab was“. Die übliche Lösung ist ein leeres Klammerpaar {}, das das Namensende markiert; die Syntaxseite erklärt das genauer.

Eine wichtige Regel: \newcommand gelingt nur, wenn der Name noch nicht definiert ist. Wird ein vorhandener Befehlsname verwendet, auch aus Kernel oder Paket, stoppt LaTeX mit Command \name already defined. Das ist ein absichtliches Sicherheitsnetz gegen stilles Überschreiben. Um einen bestehenden Befehl bewusst umzubauen, dient \renewcommand.

Makros mit Argumenten

Soll der Inhalt pro Aufruf variieren, geben Sie dem Befehl Argumente. Schreiben Sie die Anzahl der Argumente in eckige Klammern nach dem Namen — \newcommand{\name}[⟨nargs⟩]{... #1 #2 ...} — und greifen Sie in der Definition mit #1, #2 usw. darauf zu. Die Parameter laufen von #1 bis #9, höchstens neun.

latex
\newcommand{\unit}[2]{#1\,\mathrm{#2}}

% \unit{9.8}{m/s^2} → 9.8 m/s^2(数と単位の間に細い空き)
$a = \unit{9.8}{m/s^2}$

Außerdem kann das erste Argument optional werden und einen Standardwert erhalten. Doppelte Klammern — \newcommand{\name}[⟨nargs⟩][⟨default⟩]{...} — machen #1 optional mit Standard ⟨default⟩. Aufgerufen wird mit \name (Standardwert) oder \name[x] (#1 wird x); die übrigen Pflichtargumente beginnen bei #2.

latex
% 全 2 引数、うち #1 は省略可能で既定値 2
\newcommand{\plusbinomial}[2][2]{(x + y)^{#1}_{#2}}

$\plusbinomial{n}$      % → (x + y)^2_n   (#1 は既定の 2)
$\plusbinomial[3]{n}$   % → (x + y)^3_n   (#1 を 3 に)

Wichtig ist die Zählweise: ⟨nargs⟩ in [⟨nargs⟩] ist die Gesamtzahl der Argumente einschließlich des optionalen. Das Beispiel bedeutet also zwei Argumente, von denen das erste optional ist. Außerdem ist es etwas anderes, [⟨default⟩] wegzulassen, als leere Klammern [] zu schreiben: Letzteres gibt ein optionales Argument mit leerem Standardwert.

Neu definieren, bereitstellen und robust machen

\newcommand hat drei Geschwister mit verschiedenen Zwecken. Alle nehmen Argumente wie \newcommand ([⟨nargs⟩][⟨default⟩]); der Unterschied liegt im Verhalten gegenüber bereits definierten Namen.

BefehlBei vorhandenem NamenVerwendung
\newcommandStoppt mit FehlerNeuen Befehl sicher erzeugen
\renewcommandÜberschreibt ihn (Fehler, falls undefiniert)Bestehenden Befehl umbauen
\providecommandTut nichts (alte Definition bleibt)Style-Dateien, die mehrfach geladen werden können
\DeclareRobustCommandÜberschreibt und notiert im LogRobuste Befehle für bewegliche Argumente

\renewcommand definiert einen bestehenden Befehl neu. Es ist das Spiegelbild von \newcommand: Das Ziel muss bereits definiert sein, sonst gibt es einen Fehler. Damit ersetzt man Inhalte, die LaTeX schon bereitstellt, etwa das Aufzählungszeichen einer Liste.

latex
% itemize の第 1 階層の記号をダッシュに
\renewcommand{\labelitemi}{--}

% 既存マクロを新しい中身で作り直す
\renewcommand{\grp}{Lamport Typesetting Lab}

\providecommand definiert einen Befehl nur, wenn es ihn noch nicht gibt. Ist der Name undefiniert, verhält es sich wie \newcommand; existiert er schon, geschieht nichts und die alte Definition bleibt. Das passt zu Style-Dateien, die mehrfach geladen werden können und einen Befehl vorsorglich bereitstellen.

\DeclareRobustCommand erzeugt einen robusten Befehl, auch wenn sein Inneres fragile Teile enthält. Anders als \newcommand meldet es bei vorhandenem Namen keinen Fehler; bei Neudefinition wird nur eine Notiz ins Log geschrieben. Solche Befehle sind etwas weniger effizient, daher sollte man sie nur verwenden, wenn der Inhalt fragile ist und in beweglichen Argumenten erscheint; sonst bleibt \newcommand vorzuziehen.

Fragile Befehle und \protect

LaTeX kennt besondere Kontexte namens bewegliche Argumente. Der Titel in \section{...} wird nicht nur im Text gesetzt, sondern auch ins Inhaltsverzeichnis, in Kopfzeilen und in die .aux-Datei geschrieben und wandert so an mehrere Orte. \caption{...}, \thanks{...} und Inhalte von @{...} in tabular/array gehören ebenfalls dazu.

Ein Befehl, der beim Expandieren in solchem Kontext zu ungültigem TeX-Code zerfällt, heißt fragile command; einer, der überlebt, robust command. Klassisch setzt man \protect direkt vor einen fragilen Befehl und sagt LaTeX damit: „Hier nicht expandieren, sondern so hinausschreiben.“ Schutz gilt pro Befehl; jedes \protect schützt nur den unmittelbar folgenden.

latex
% 可動引数の中で壊れやすい \verb を保護する
\section{The \protect\verb|\par| primitive}

Es gibt aber gute Nachrichten: Seit LaTeX vom Oktober 2019 wurden viele früher fragile Befehle robust gemacht. Befehle mit optionalen Argumenten wie \raisebox und Inline-Mathematik \(...\) können heute ohne \protect in Überschriften stehen. Ein häufiger Ausreißer bleibt \verb; es lässt sich oft auch mit \protect nicht retten. In Überschriften und Beschriftungen ist \texttt{...} meist die schnelle Lösung. Eigene Makros können Sie von Anfang an mit \DeclareRobustCommand robust definieren.

Das moderne \NewDocumentCommand

Modernes LaTeX bietet eine weitere, mächtigere Definitionsform: \NewDocumentCommand{\name}{⟨arg-spec⟩}{...}. Ursprünglich Teil des Pakets xparse, ist sie heute im LaTeX-Kernel (ltcmd) und ohne \usepackage verfügbar. Statt einer Argumentzahl deklarieren Sie eine Argumentspezifikation (arg-spec), also eine Buchstabenfolge, die die Art jedes Arguments benennt.

SpezifiziererBedeutungAnkunft im Körper
mPflichtargumentNormales Argument wie #1
oOptionales Argument [...]No-value-Marker, wenn fehlend
O{default}Optional mit Standardwertdefault, wenn fehlend
sOptionaler Stern *Mit \IfBooleanTF testen

Mächtiger als \newcommand ist es aus zwei Gründen: Es kann mehrere optionale Argumente annehmen und Sternvarianten korrekt behandeln. Im Beispiel unten wird mit \IfBooleanTF nach dem Stern verzweigt (#1 ist der Stern, #2 das Pflichtargument). Für neuen Code ist diese moderne Schnittstelle empfehlenswert; die xparse-Seite behandelt sie ausführlich.

latex
\NewDocumentCommand{\diff}{s m}{%
  \IfBooleanTF{#1}%
    {\frac{\mathrm{d}}{\mathrm{d}#2}}%   星つき: d/dx 形
    {\mathrm{d}#2}%                      星なし: dx 形
}

$\diff{x}$    % → dx
$\diff*{x}$   % → d/dx

Gute Makropraxis

Makros sind am stärksten als semantische Makros. Wenn Dinge nach dem benannt werden, was sie sind — die reellen Zahlen als \newcommand{\R}{\mathbb{R}}, das Differential d als \newcommand{\dd}{\mathrm{d}} — bleibt die Notation im ganzen Dokument einheitlich. Soll die Darstellung später anders aussehen, genügt eine geänderte Definitionszeile.

latex
\newcommand{\R}{\mathbb{R}}
\newcommand{\dd}{\mathrm{d}}

% 統一された表記で書ける / write with consistent notation
$\int_{\R} f(x)\,\dd x$

Zu viele Makros schaden allerdings der Lesbarkeit. Eine extreme Abkürzung wie \newcommand{\x}{\xi} kann Monate später für Sie oder Mitautoren wie Geheimschrift wirken. Reservieren Sie Makros für Dinge, die oft wiederholt werden, wahrscheinlich gesammelt geändert werden oder einen semantischen Namen verdienen; anderes ist ausgeschrieben oft lesbarer.

Vermeiden Sie zuletzt Namenskollisionen. Kernel- oder Paketbefehle nicht leichtfertig mit \renewcommand überschreiben; Nebenwirkungen können überraschen. Für eigene Befehle keine zu kurzen Namen wählen und möglichst ein projektspezifisches Präfix nutzen, etwa \myR oder \bookTitle. Im Zweifel zuerst mit \newcommand definieren; ein already defined-Fehler zeigt, dass der Name belegt ist.