nav-left cat-right
cat-right
Matthias Pospiech > LaTeX > Definition von Makros und Umgebungen

Definition von Makros und Umgebungen

LaTeX kennt Befehlen (commands) und Umgebungen (environments). Der Unterschied ist das ein Befehl direkt abgearbeitet wird wohingegen eine Umgebung zu Beginn und zum Ende der Umgebung Code ausführt. Für ausführliche Beispiele zur Nutzung von selbstdefinierten Befehl und Umgebungen bitte ich weitere LaTeX Literatur zu Rate zu ziehen. Hier werde ich nur auf die grundsätzliche Syntax eingehen.
  1. Neue Befehle
  2. Lange und kurze Befehle
  3. Optionale Argumente
  4. Mehrfache optionale Argumente
  5. Verschachtelte Befehle
  6. Befehle mit *
  7. Umgebungen
  8. Protect, Fragile und Robust

Neue Befehle

Ein neuer Befehl wird definiert über
% \newcommand{cmd}[narg]{command definition}
\newcommand{\figureref}[1]{(Abbildung \ref{#1})}%

Dabei sind bis zu 9 Argumente (narg) möglich. Diese werden abgerufen über #1, …, #9.

Wie man mehr als 9 Argumente übegeben kann ist in der englischen FAQ erklärt:http://www.tex.ac.uk/cgi-bin/texfaq2html?label=moren9. Eine solche Anzahl von Argumenten ist jedoch nicht zu empfehlen. Besser ist es eine key=value Syntax zu verwenden.

Ist ein Befehl schon definiert löst ein \newcommand einen Fehler aus.

zur Definition gibt es noch weitere Befehle, jeweils mit der gleichen Syntax:

  • \renewcommand: definiert ein bestehenden Befehl um. Löst einen Fehler aus falls der Befehl noch nicht exisiter.
  • \providecommand: definiert einen Befehl unabhängig davon ob er schon existierte oder nicht.
  • \DeclareRobustCommand: wie \newcommand, definiert allerdings einenrobusten Befehl.

Lange und kurze Befehle

Lange Befehle, dass sind alle die mit den vorgestellten Befehle \newcommand, \renewcommand, \providecommand usw. erzeugt werden erlauben Paragraphenumbrüche in den Argumenten.

Es gibt auch alle Befehle mit einem *
\newcommand*
\renewcommand*
\providecommand*
...

die dann kurze Befehle erzeugen, die dann keine Paragraphenumbrüche in den Argumenten erlauben.

Intern sind die langen Befehl als \long\def definiert und die kurzen nur als \def

Optionale Argumente

Die Syntax für einen Befehl mit optionalem Argument ist wie folgt
\newcommand{cmd}[narg][default]{command definition}

In diesem Fall hat das Optionale Argument die Nummer #1 und wird durch den default Wert ersetzt wenn der optionale Parameter nicht genutzt wird.

Im Falle von
\newcommand{\foobar}[1][2]{#1}
gibt es nur ein optionales Argument. Die Ausgabe ist also standardmäßig „2“, es sein denn man schreibt \foobar[3] was dann „3“ ausgibt.

Mehrfache optionale Argumente

Für die Lösung gibt es mehrere Pakete. Zum einen das optparams Paket welches die folgende Syntax bietet
\long\def\test@[#1][#2][#3][#4]{%
	(#1) (#2) (#3) (#4)
}
\newcommand{\test}{%
	\optparams{\test@}{[one][two][three][four]}%
}
Hiernach gibt es bis zu 4 optionale Parameter, so dass sich folgende Ausgaben ergeben:
\test[this] % ergibt "(this) (two) (three) (four)"
\test[this][is] % ergibt  "(this) (is) (three) (four)"
\test[this][is][a]% ergibt "(this) (is) (a) (four)"
\test[this][is][a][test]% ergibt  "(this) (is) (a) (test)"
Ein nichtoptionales Argument wird dann wie folgt definiert
\long\def\test@[#1][#2][#3][#4]#5{%
	(#1) (#2) (#3) (#4) #5
}
\newcommand{\test}{%
	\optparams{\test@}{[one][two][three][four]}%
}

Allerdings muss bei dieser Methode der erste Befehl über ein \def definiert werden da ein \newcommand diese Syntax nicht versteht.

Zum Anderen gibt es das wesentlich mächtigere Paket xargs welches eine sehr flexible Lösung bietet.

In diesem Paket werden die Befehle

\newcommandx
\renewcommandx
\providecommandx
\DeclareRobustCommandx
\CheckCommandx
\newenvironmentx
\renewenvironmentx

definiert, welche sich durch die vordefiniertem jeweils durch das angehangene x unterscheiden und eine etwas andere Syntax bieten:

\newcommandx*{command}[number][list]{definition}
% zum Vergleich
\newcommand*{command}[number]{definition}

Die Definition eines Befehls unterscheidet sich somit in der Definition von list. Das folgende Beispiel definiert zwei optionale Argumente

\newcommandx*\coord[3][1=1, 3=n]{(#2_{#1},\ldots,#2_{#3})}
$\coord{x}$ % (x1, . . . , xn)
$\coord[0]{y}$ % (y0, . . . , yn)
$\coord{z}[m]$ % (z1, . . . , zm)
$\coord[0]{t}[m]$ % (t0, . . . , tm)

Der ‚value‘ Wert bei der Liste gibt dabei den Standardwert an.

Um ein optionales Argument zu übergehen, also nicht anzugeben, aber das darauffolgende anzugeben muss man der Liste den Wert „usedefault“ hinzufügen. Das Beispiel sieht dann wie folgt aus

\newcommandx*\coord[3][2=1,3=n,usedefault]{(#2_{#1},\ldots,#2_{#3})}
$\coord{x}$ % (1x, . . . , 1n)
$\coord{y}[0]$ % (0y, . . . , 0n)
$\coord{z}[][m]$ % (1z, . . . , 1m)
$\coord{t}[0][m]$ % (0t, . . . , 0m)
Für weitere Möglichkeiten und potenzielle Probleme bitte die Dokumentation des Paketes zu Rate ziehen.

Verschachtelte Befehle

Möchte man einen Befehl definieren, der einen weiteren Befehl umdefiniert benötigt man je nach Tiefer der Verschachtelung vorgestellte Raouten (#). Hier ein Beispiel:
\newcommand\TextZwischenAnfangUndEnde[1]{Anfang \ldots #1 \ldots Ende}
\newcommand\NeuerAnfangUndEnde[2]{%
   \renewcommand\TextZwischenAnfangUndEnde[1]{#1 \ldots ##1 \ldots #2}%
}

Mit der Voreingestellten Definition von \TextZwischenAnfangUndEnde erhält man dann die Ausgabe

[tex]\newcommand\TextZwischenAnfangUndEnde[1]{Anfang \ldots #1 \ldots Ende}\TextZwischenAnfangUndEnde{Das Maerchen}[/tex]

Benutzt man nun den Befehl zum Umdefinieren

\NeuerAnfangUndEnde{Es war einmal}{Sie lebten gluecklich bis an ihr Lebensende}
\TextZwischenAnfangUndEnde{Das Maerchen}

so erhält man

[tex]\newcommand\TextZwischenAnfangUndEnde[1]{Anfang \ldots #1 \ldots Ende}\newcommand\NeuerAnfangUndEnde[2]{ \renewcommand\TextZwischenAnfangUndEnde[1]{#1 \ldots ##1 \ldots #2}}\NeuerAnfangUndEnde{Es war einmal}{Sie lebten gluecklich bis an ihr Lebensende}\TextZwischenAnfangUndEnde{Das Maerchen}[/tex]

Befehle mit *

Vielleicht nicht die optimale, aber eine Möglichkeit diesen Unterschied abzufangen bietet der Befehl \@ifnextchar mit der folgenden Notation
\newcommand{\fancy}{\@ifnextchar*{Befehl mit *}{Befehl ohne *} sonstiges}

Umgebungen

Umgebungen werden definiert über
\newenvironment{cmd}[narg]{begin definition}{end definition}
\renewenvironment{cmd}[narg]{begin definition}{end definition}
% Erste Argument optional
\newenvironment{cmd}[narg][optional]{begin definition}{end definition}
Möchte man in der Anfangs oder Ende Sequenz weitere Umgebungen einbringen so kann man diese nicht über \begin{} und \end{} definieren. Stattdessen benötigt man die äquivalenten normalen Befehle. Hier ein Beispiel
% \newenvironment{myquote}[1]{\small\begin{quote}}{\end{quote}} % funktioniert nicht!
\newenvironment{myquote}[1]{\small\quote}{\endquote} % funktioniert

Protect, Fragile und Robust

Angeleht an einen Text aus der englische FAQ: LaTeX definiert Befehle deren Daten später nocheinmal eingelesen werden. Diese Daten können dann Argumetne von anderen Befehlen sein. Dies kann z.B. vorkommen bei Inhaltsverzeichnissen die aus aux Dateien wieder eingelesen werden und Daten die in den Kopf und Fusszeilen landen. Diese Befehle werden bei ihrer Ausführung und damit dem Speichern der Werte direkt expandiert. Manchmal erzeugt das einen Fehler wenn die Daten später nochmal eingelesen werden. Dies kann verhindert werden indem man ein \protect vor einen Befehl stellt:
\protect\somecommand
In diesem Fall wird \somecommand nicht expandiert.

Fragile Befehle sind dann solche die in ungültigem TeX Code beim Speichern resultieren, wohingegen Robuste Befehle in gültigen Code beim Speichern expandieren.

1 Antwort : “Definition von Makros und Umgebungen”

  1. Dominik sagt:

    Also

    \newenvironment{myquote}[1]{\small\begin{quote}}{\end{quote}}

    funktioniert bei mir ohne Probleme. Zwar macht die Angabe eines Parameters keinen Sinn, wenn es sich nur um eine einfach, kleine quote-Umgebungserweiterung handeln soll. Davon abgesehen kann ich ohne Fehler beim Kompilieren

    \begin{myquote}
    ein kleines Zitat
    \end{myquote}

    in mein Dokument einbauen…

    Davon abgesehen möchte ich dir auch mal kurz für deine LaTeX-Tipps im Allgemeinen danken. Die haben mir schon oft geholfen 🙂

    LG,
    Dominik

Einen Kommentar schreiben

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*

This blog is kept spam free by WP-SpamFree.