Wie definiere ich eigene Kommandos?
Bitte nicht vor der Länge des Beitrages erschrecken 😉
LaTeX stellt sehr viele Anweisungen zur Verfügung, die einem die Formatierung des Dokumentes erleichtern. Diese Vielfalt wird durch eine große Zahl von Paketen erweitert. Ob LaTeX oder Pakete, es ist nicht möglich alle Nutzerwünsche abzudecken. So kommt es sehr häufig vor, dass eigene Anweisungen definiert werden sollen.
In TeX selbst konnte das mittels [cce lang=”latex” inline=”true”]\def[/cce] realisiert werden. Diese Anweisung ist in LaTeX2e durch [cce lang=”latex” inline=”true”]\newcommand[/cce] bzw. [cce lang=”latex” inline=”true”]\renewcommand[/cce] erweitert bzw. ersetzt worden. Aber auch diese Anweisungen sind in ihrer Funktionalität sehr stark beschränkt. Das “neue” Paket [cce lang=”latex” inline=”true”]xparse[/cce] soll in diesem Post aufzeigen, wie einfach neue Definitionen mit verschiedensten Einstellungen möglich sind.
Bevor ich auf die neuen Möglichkeiten zu sprechen komme, möchte ich ein kurzes Resümee über die genannten Anweisungen geben. Allerdings sind zu Beginn einige Grundlagen zu legen.
Grundlagen
Im weiteren müssen wir zwischen optionalen und verpflichtenden Argumenten unterscheiden. Als Regel könnt ihr euch folgendes merken: Optionale Argumente werden durch das Klammerpaar [] angegeben. Verpflichtende Argumente werden durch das Klammerpaar {} angegeben.
Ein weitere Grundlage ist etwas anglizistisch. Egal ob bei TeX oder LaTeX, es mussen zwischen long und nicht long arguments unterschieden werden. long sind Argumente, die einen Absatzumbruch enthalten dürfen, nicht long arguments dürfen es entsprechend nicht ;-). Die Definition von long und nicht long arguments hat direkte Auswirkungen auf evtl. Fehlermeldungen, worauf wir aber im späteren eingehen.
Was macht [cce lang=”latex” inline=”true”]\def[/cce]?
Es ist bereits angesprochen worden, dass [cce lang=”latex” inline=”true”]\def[/cce] aus der TeX-Welt kommt. Die Syntax ist
[cce lang=”latex”]
\def\Anweisungen{Was soll die Anweisung tun}
[/cce]
Auch Argumente sind möglich, wobei die einfachste Form nur mittels verpflichtenden Argumenten auskommt.
[cce lang=”latex”]
\def\Anweisungen#1{Drucke die Eingabe fett \textbf{#1}}
[/cce]
Insgesamt sind 9 Argumente möglich, wobei keines als long deklariert ist. Möchte man die Argumente als long definieren, muss mit dem Prefix [cce lang=”latex” inline=”true”]\long[/cce] gearbeitet werden.
[cce lang=”latex”]
\long\def\Anweisungen#1{Drucke die Eingabe des long arguments #1}
[/cce]
Was macht [cce lang=”latex” inline=”true”]\def[/cce] noch? Es definiert die [cce lang=”latex” inline=”true”]\Anweisung[/cce] ohne vorher zu prüfen, ob die Anweisung existiert. Es wird also alles gnadenlos überschrieben.
Insgesamt lassen sich also folgende Punkte festhalten:
- Anweisungen werden nicht getestet, ob sie bereits existieren.
- Optionale Argumente sind nur mit Aufwand realisierbar.
- Alle Argumente sind per default keine long arguments.
- Es ist nicht möglich, Argumente separat als long bzw. nicht long zu definieren.
Was macht [cce lang=”latex” inline=”true”]\newcommand[/cce] bzw. [cce lang=”latex” inline=”true”]\renewcommand[/cce]?
Diese beiden Anweisungen sind durch LaTeX2e eingeführt worden und sollten bereits heute [cce lang=”latex” inline=”true”]\def[/cce] komplett ersetzen. Die allgemeine Syntax ist:
[cce lang=”latex”]
\newcommand{\Anweisungsname}{Was soll die Anweisung tun}
[/cce]
Für [cce lang=”latex” inline=”true”]\renewcommand[/cce] ist die Syntax äquivalent. Die Anweisung [cce lang=”latex” inline=”true”]\newcommand[/cce] testet, ob der gewünschte Befehlsname bereits existiert. Sollte dies der Fall sein, so wird eine entsprechende Fehlermeldung generiert. [cce lang=”latex” inline=”true”]\renewcommand[/cce] macht nun genau das Gegenteil. Es redefiniert eine existierende Anweisung. Sollte die Anweisung allerdings nicht existieren, so gibt es eine entsprechende Fehlermeldung. Somit ist durch die Einführung dieser beiden Anweisungen eine höhere Sicherheit gewährleistet, wobei durch [cce lang=”latex” inline=”true”]\renewcommand[/cce] der Nutzer explizit auf eine Redefinition hingewiesen wird bzw. diese erlauben muss.
Möchte man mit Argumenten arbeiten, kann die Anzahl der Argumente einfach in eckigen Klammern angegeben werden.
[cce lang=”latex”]
\newcommand{\Anweisungsname}[1]{Drucke die Eingabe fett \textbf{#1}}
[/cce]
Auch hier ist die Zahl der Argumente auf 9 limitiert. Allerdings erlauben die Anweisungen die Definition von einem optionalen Argument. welches stets mit [cce lang=”latex” inline=”true”]#1[/cce] angesprochen wird.
[cce lang=”latex”]
\newcommand{\Anweisungsname}[2][default]{\textbf{#2} — das optionale Argument ist: #1}
[/cce]
[cce lang=”latex” inline=”true”]\Anweisungsname[/cce] ist nun mit zwei Argumenten definiert, wobei das erste ein optionales Argument ist. Das Argument der zweiten eckigen Klammer wird hierbei als Defaultwert genommen, falls kein optionales Argument angegeben ist. In unserem Beispiel also “default”.
Die Anweisungen [cce lang=”latex” inline=”true”]\newcommand[/cce] bzw. [cce lang=”latex” inline=”true”]\renewcommand[/cce] definieren ihre Argumente stets als long. Möchte man dies nicht, so können die Sternvarianten der Anweisungen genutzt werden: [cce lang=”latex” inline=”true”]\newcommand*[/cce] bzw. [cce lang=”latex” inline=”true”]\renewcommand*[/cce]. Aber auch hier werden alle Argumente mit dem gleichen Typ versehen.
Fassen wir also zusammen:
- [cce lang=”latex” inline=”true”]\newcommand[/cce] testet, ob eine Anweisungen bereits existiert. Ist es der Fall, so gibt es einen Fehler.
- [cce lang=”latex” inline=”true”]\renewcommand[/cce] testet, ob eine Anweisungen bereits existiert und überschreibt diese. Ist die Anweisung unbekannt, gibt es einen Fehler.
- Die Anweisungen erlauben die Definition von einem optionalen Argument, welches stets das erste sein muss.
- Alle Argumente sind per default long arguments.
- Es ist nicht möglich, Argumente separat als long bzw. nicht long zu definieren.
Bevor wir zum Hauptteil und zum eigentlichen Paket [cce lang=”latex” inline=”true”]xparse[/cce] kommen, noch ein kleiner Exkurs.
Exkurs: Unterschied der Fehlermeldung bei long und nicht long.
Auf die Unterschiede zwischen long und nicht long bin ich bereits eingegangen. Jetzt ist auch die Frage berechtigt, warum es überhaupt diese Unterscheidung gibt bzw. was es für Vorteile hat, ein Makro als nicht long zu definieren. Hierzu nehmen wir ein Beispiel:
[cce lang=”latex”]
\documentclass{article}
%Definition als long
\newcommand\Anweisung[1]{Argument: \textbf{#1}}
\begin{document}
%Klammer vergessen zuzumachen
\Anweisung{foo
\end{document}
[/cce]
Die zugehörige Fehlermeldung lautet:
[cce lang=”latex”]
Runaway argument?
{foo \par \end {document}
! File ended while scanning use of \Anweisung.
<inserted text>
\par
<*> test.tex
[/cce]
Nutze ich hingegen die Definition [cce lang=”latex” inline=”true”]\newcommand*\Anweisung[1]{Argument: \textbf{#1}}[/cce] (also nicht long), so ist die Fehlermeldung:
[cce lang=”latex”]
Runaway argument?
{foo
! Paragraph ended before \Anweisung was complete.
<to be read again>
\par
l.22
[/cce]
Wie wir sehen, ist bei der nicht long Definition die entsprechende Zeilennummer angegeben. In unserem kleinen Beispiel macht das nicht viel aus, aber stellt euch größere Dokumente vor, bei denen die Anweisung [cce lang=”latex” inline=”true”]\Anweisung[/cce] öfter aufgerufen wird. Ich denke es wird deutlich, dass bevorzugt Makros des Typs nicht long aguments genutzt werden sollte.
Definition von Kommandos mittels [cce lang=”latex” inline=”true”]xparse[/cce]?
[cce lang=”latex” inline=”true”]xparse[/cce] ist ein Paket und muss entsprechend geladen werden.
[cce lang=”latex”]
\usepackage{xparse}
[/cce]
[cce lang=”latex” inline=”true”]xparse[/cce] basiert auf LaTeX3. Dazu vielleicht in einem späteren Blog-Post ein wenig mehr.
Das Paket definiert verschiedenste Funktionen, um die Definition von neuen Anweisungen zu gewährleisten. Wir wollen uns hier auf die zwei wesentlichen Konzentrieren: [cce lang=”latex” inline=”true”]\NewDocumentCommand[/cce] und [cce lang=”latex” inline=”true”]\RenewDocumentCommand[/cce].
Wie bereits im vorigen Abschnitt ausgeführt, lassen sich folgende Analogien feststellen. [cce lang=”latex” inline=”true”]\NewDocumentCommand[/cce] definiert eine Anweisung; sollte die Anweisung jedoch bereits existieren, so wird eine entsprechende Fehlermeldung generiert. Entsprechend ist [cce lang=”latex” inline=”true”]\RenewDocumentCommand[/cce] zu verstehen. Sollte die Anweisung nicht existieren, so gibt es eine Fehlermeldung. Nebenbei bemerkt haben die Entwickler von [cce lang=”latex” inline=”true”]xparse[/cce] auf verständlichere Fehlermeldungen geachtet.
Die vorgestellten Funktionen weichen von der Syntax und der Deklaration von Argumenten geringfügig zu den bereits vorgestellten Möglichkeiten ab. Aber dadurch ist eine höhere Flexibilität gegeben. Die Syntax ist:
[cce lang=”latex”]
\NewDocumentCommand{\Anweisung}{<Anweisungsspezifikation>}{Was soll getan werden}
[/cce]
Wir sehen also, dass insgesamt drei verpflichtende Argumente existieren. Die Argumentenspezifikation ist hier nicht gezeigt, weil diese einen extra Absatz bedarf.
Wie bereits in den vorherigen Ausführungen sind maximal 9 Argumente zulässig. Die Angabe der Argumente erfolgt nicht mit Zahlen, sondern mit definierten Buchstaben. Die Liste ist ziemlich lang, so dass ich hier nur zwei (eigentlich drei) wesentliche vorstelle.
Arg | Erläuterung |
---|---|
m | verpflichtendes Argument (engl.: mandatory) |
o | optionales Argument (engl.: optional), bei dem kein Defaultwert angegeben werden kann. Allerdings kann mittels [cce lang=”latex” inline=”true”]\IfNoValue(TF)[/cce] getestet werden, ob ein optionales Argument existiert. |
O{} | optionales Argument (engl.: optional), default wird in Klammern angegeben |
Alle diese Argumenttypen sind von Hause aus als nicht long definiert. Möchte man ein Argument als long definieren, so muss ein [cce lang=”latex” inline=”true”]+[/cce] (plus) davor gesetzt werden. Um das erworbene Wissen zu nutzen, ein Beispiel. Die nachstehende Definition deklariert [cce lang=”latex” inline=”true”]\Anweisung[/cce] mit drei Argumenten, wobei das erste und dritte verpflichtend sind und das zweite optional ist. Zudem soll das dritte Argument als long deklariert sein. Das lässt sich nun wie folgt bewerkstelligen
[cce lang=”latex”]
\NewDocumentCommand{\Anweisung}{m O{} +m}%
{%
Argument 1: #1\\
Argument 2: #2\\
Argument 3: #3\\
}
[/cce]
Fassen wir zusammen:
- [cce lang=”latex” inline=”true”]\NewDocumentCommand[/cce] testet, ob eine Anweisungen bereits existiert. Ist es der Fall, so gibt es einen Fehler.
- [cce lang=”latex” inline=”true”]\RenewDocumentCommand[/cce] testet, ob eine Anweisungen bereits existiert und überschreibt diese. Ist die Anweisung unbekannt, gibt es einen Fehler.
- Die Anweisungen erlauben die Definition von mehreren optionalen Argumenten, wobei die Reihenfolge durch den Nutzer bestimmt wird.
- Alle Argumente sind per default nicht long arguments.
- Es ist möglich, Argumente separat als long bzw. nicht long zu definieren.
Das Paket bietet noch viele weitere Argumententypen und auch Tests der optionalen Argumente. Dieser kleine Blog soll euch einen ersten Einstieg geben, was alles möglich ist. Zum Abschluss dieses Abschnittes noch eine kleine Motivation für [cce lang=”latex” inline=”true”]xparse[/cce]. Es behebt einen Bug von [cce lang=”latex” inline=”true”]\newcommand[/cce], der Nutzer schon lange ärgert. Das soll folgendes Beispiel zeigen.
[cce lang=”latex”]
\documentclass{article}
\usepackage{xparse}
\newcommand*\AnweisungAlt[2][]{Argument: \textbf{#1} — !#2!}
\NewDocumentCommand\AnweisungNeu{O{} m }{Argument: \textbf{#1} — !#2!}
\begin{document}
\AnweisungAlt[[Argument mit eckigen Klammern]]{foobar}
\AnweisungNeu[[Argument mit eckigen Klammern]]{foobar}
\end{document}
[/cce]
Einfach mal Kompilieren und die Ergebnisse vergleichen 😉
Fazit
Die Anweisung von Nutzerkommandos ist von Begin an bedacht worden. Die Möglichkeiten sind aber erst in den letzten Jahren gewachsen und sicherer geworden. Mit der Einführung von [cce lang=”latex” inline=”true”]xparse[/cce] stehen dem Nutzer eine Mannigfaltigkeit von Optionen zur Verfügung, die eine Formatierung des Dokumentes erheblich vereinfachen. Der Blogpost kann leider nur einen kleinen Ausschnitt wiedergeben. Es sollte aber deutlich geworden sein, dass anstelle von [cce lang=”latex” inline=”true”]\def[/cce] oder [cce lang=”latex” inline=”true”]\newcommand[/cce] die Anweisung [cce lang=”latex” inline=”true”]\NewDocumentCommand[/cce] genutzt werden sollte. Um sich mit [cce lang=”latex” inline=”true”]xparse[/cce] vertraut zu machen, solltet ihr die Dokumentation konsultieren.
Quellen
- LaTeX3 Team. [cce lang=”latex” inline=”true”]xparse[/cce], 2013: CTAN [cce lang=”latex” inline=”true”]xparse[/cce]
- Frank Mittelbach et al. Der LaTeX Begleiter, 2. Aufl., Pearson Studium, 2005.
Kommentare (9)