Sobald Sie in einem Paket oder in der Präambel nichttrivialen Code schreiben, brauchen Sie Dinge, die rohes TeX mühsam macht: Wahrheitsflags, Tests wie „ist dieser Befehl definiert?“, „ist diese Zeichenkette leer?“ und das Anhängen an vorhandene Befehle. etoolbox liefert genau diese Werkzeuge in einer LaTeX-nahen Form, und pgfkeys bildet die Grundlage für key=value-Konfigurationsschnittstellen. Beide stecken hinter vielen Paketen.
Was etoolbox ist
etoolbox (geschrieben von Philipp Lehman, heute betreut von Joseph Wright) ist ein Programmierwerkzeugkasten für Klassen- und Paketautoren. Es legt eine LaTeX-artige Oberfläche über die Low-Level-Primitiven von e-TeX und bündelt zudem viele nützliche allgemeine Werkzeuge, die nicht direkt an e-TeX gebunden sind. Da jede moderne TeX-Engine e-TeX enthält, genügt \usepackage{etoolbox}.
Auch seit expl3, die Programmierschicht von LaTeX3, verbreitet ist, bleibt etoolbox beliebt, weil es direkt in die LaTeX2e-Welt passt. Argumente lassen sich schlicht als #1 schreiben, Verzweigungen haben die vertraute Form {wahr}{falsch}, und vor allem \patchcmd (unten) erlaubt es, Befehle vorhandener Pakete nachträglich zu reparieren.
Wahrheitsflags: Toggles und Bools
Wenn Sie einen Wahr/Falsch-Zustand wie „sind wir im Entwurfsmodus?“ speichern wollen, bietet etoolbox zwei Familien. Empfohlen sind Toggles: Sie besitzen einen eigenen Namensraum und kollidieren nicht mit bestehenden Befehlen. Deklariert wird mit \newtoggle{flag}, geschaltet mit \toggletrue{flag} / \togglefalse{flag} oder \settoggle{flag}{true}, verzweigt mit \iftoggle{flag}{⟨true code⟩}{⟨false code⟩}. Für die Gegenrichtung gibt es \nottoggle{flag}{⟨if not true⟩}{⟨if not false⟩}.
\usepackage{etoolbox}
\newtoggle{draft} % フラグを宣言 / declare the flag
\toggletrue{draft} % 真にする / set it true
% 本文や命令の中で分岐 / branch on it
\iftoggle{draft}
{\textbf{[DRAFT]}\ } % 真のとき / when true
{} % 偽のとき / when falseDie andere Familie sind Bools: \newbool{flag} / \setbool{flag}{true} / \booltrue{flag} / \boolfalse{flag}, getestet mit \ifbool{flag}{⟨true⟩}{⟨false⟩}. Intern nutzt ein Bool dieselbe Mechanik wie LaTeXs \newif und belegt daher einen Befehlsnamen \ifflag. Meist reichen Toggles; Bools helfen, wenn Code auf \newif-Basis eingebunden werden muss.
| Befehl | Bedeutung | Hinweise |
|---|---|---|
\newtoggle{f} | Toggle f deklarieren (anfangs falsch) | Eigener Namensraum |
\settoggle{f}{v} | f auf v setzen (true/false) | Oder \toggletrue / \togglefalse |
\iftoggle{f}{T}{F} | T wenn wahr, F wenn falsch | Nimmt drei Argumente |
\ifbool{f}{T}{F} | Die Bool-Variante der Verzweigung | Dieselbe Mechanik wie \newif |
Definitionen und Zeichenketten testen
Für sichere Paketprogrammierung will man oft wissen: „Ist dieser Befehl schon definiert?“ oder „Ist das Argument leer?“ In etoolbox verwenden alle Tests dieselbe {⟨true⟩}{⟨false⟩}-Verzweigung. Definitionen prüft \ifdef{\cmd}{⟨true⟩}{⟨false⟩}, Namen als Zeichenketten prüft \ifcsdef{name}{⟨true⟩}{⟨false⟩}. Die Gegenstücke \ifundef / \ifcsundef gibt es ebenfalls.
Vorsicht: Das ähnlich benannte \ifdefined ist ein e-TeX-Primitiv, kein etoolbox-Befehl der Form {true}{false}. Für eine Zweigverzweigung benutzen Sie \ifdef aus etoolbox und übergeben den tatsächlichen Befehl mitsamt Backslash. Für Zeichenketten gibt es \ifblank{⟨string⟩}{⟨true⟩}{⟨false⟩} für „nur Leerraum?“, die Umkehrung \notblank, \ifstrequal{⟨string⟩}{⟨string⟩}{⟨true⟩}{⟨false⟩} für Gleichheit und \ifstrempty für Leere.
% 命令が未定義のときだけ用意する / provide a command only if missing
\ifdef{\highlight}
{} % 既にあれば何もしない / leave it alone
{\newcommand{\highlight}[1]{\textbf{#1}}}
% 引数が空かどうかで出し分け / vary on an empty argument
\newcommand{\field}[1]{\ifblank{#1}{(none)}{#1}}Hooks und Anhängen an Befehle
etoolbox bietet auch Befehle für Hooks, also Ablagen für Code, der zu bestimmten Zeitpunkten läuft. \AtBeginDocument / \AtEndDocument gehören zum LaTeX-Kernel; etoolbox ergänzt \AtEndPreamble am Ende der Präambel, \AfterEndDocument ganz am Schluss und Hooks um bestimmte Umgebungen: \AtBeginEnvironment{⟨env⟩}{⟨code⟩} / \AtEndEnvironment / \BeforeBeginEnvironment / \AfterEndEnvironment.
Um solchen Hooks oder beliebigen Makros nachträglich Inhalt hinzuzufügen, dienen die Anhängebefehle. \appto{\cmd}{⟨code⟩} hängt hinten an, \preto{\cmd}{⟨code⟩} vorne (\gappto ist global, \eappto expandiert vorher). Für Makros mit Argumenten verwenden Sie sicherer \apptocmd{\cmd}{⟨code⟩}{⟨success⟩}{⟨failure⟩} / \pretocmd, die Erfolgs- und Fehlerzweige haben.
% すべての itemize の冒頭に行間設定を差し込む
\AtBeginEnvironment{itemize}{\setlength{\itemsep}{2pt}}
% 文書開始時に走るフックへ追記 / append to the begin-document hook
\appto{\@begindocumenthook}{\typeout{Hello from etoolbox}}Befehle mit \patchcmd reparieren
Das wohl bekannteste Werkzeug in etoolbox ist \patchcmd. Es ersetzt nur einen Teil des Körpers eines bereits definierten Befehls — nützlich, wenn ein Befehl aus einem Paket oder dem Kernel leicht verändert werden soll, ohne ihn komplett neu zu definieren. Die Form hat fünf Argumente:
\patchcmd{\cmd}{⟨search⟩}{⟨replace⟩}{⟨success⟩}{⟨failure⟩}Es sucht in der Definition von \cmd nach dem ersten Vorkommen, das ⟨search⟩ entspricht. Wird es gefunden, ersetzt es durch ⟨replace⟩ und führt ⟨success⟩ aus; sonst bleibt der Befehl unverändert und ⟨failure⟩ läuft. Ersetzt wird nur die erste Stelle. ⟨success⟩ / ⟨failure⟩ können leer sein, aber ein Warnhinweis im Fehlerzweig ist sicherer, damit ein nicht mehr greifender Patch auffällt.
Zwei praktische Hinweise. Erstens enthalten Zielbefehl und ⟨search⟩ fast immer @, weil sie intern sind; umschließen Sie den Patch mit \makeatletter … \makeatother, oder verlassen Sie sich darauf, dass \patchcmd @ während der Arbeit kurz zu einem Buchstaben macht. Zweitens: Wenn ein Patch nicht greift, setzen Sie \tracingpatches in die Präambel; das Log meldet dann Diagnosen wie „undefiniert“ oder „Muster nicht gefunden“. Für Argumentspezifikationen oder mehrere Ersetzungen ist das Paket xpatch, eine Erweiterung von etoolbox, praktisch.
\usepackage{etoolbox}
\makeatletter
% 例:ある内部命令 \@foo の定義中の \small を \footnotesize に差し替える
\patchcmd{\@foo}
{\small} % 探す / search
{\footnotesize} % 置き換える / replace
{} % 成功時 / on success
{\PackageWarning{mypkg}{Patch to \protect\@foo\space failed}} % 失敗時
\makeatotherListen und Schleifen
etoolbox enthält auch leichte interne Listen und Iteration darüber. Mit \listadd{\mylist}{⟨item⟩} wird ein Element hinzugefügt; \forlistloop{⟨handler⟩}{\mylist} ruft für jedes Element einen einargumentigen Handler auf. Eine vorhandene komma-getrennte Zeichenkette verarbeitet man bequem mit \docsvlist{a,b,c} oder \forcsvlist{⟨handler⟩}{a,b,c}. Für eigene Trennzeichen gibt es \DeclareListParser.
% カンマ区切りの各要素を箇条書きにする / each CSV item becomes a bullet
\newcommand{\asitem}[1]{\item #1}
\begin{itemize}
\forcsvlist{\asitem}{apples, pears, plums}
\end{itemize}pgfkeys: Grundlage für key=value-Schnittstellen
pgfkeys ist die mächtige Key-Value-Engine in PGF/TikZ. TikZs vertraute Syntax [draw, thick, fill=blue] und viele \…setup{...}-Schnittstellen von Paketen werden weitgehend damit umgesetzt. Im Zentrum steht \pgfkeys{/my/key=value}. Schlüssel sind durch /-getrennte Pfade (Familien) in Namensräume gegliedert, und jedem Schlüssel wird ein Handler zugewiesen, der sagt, was beim Aufruf geschehen soll.
Entscheidend sind die Handler zum Definieren von Schlüsseln. Soll der Wert unverändert in einem Makro landen, verwenden Sie .store in=\macro (intern \def\macro{value}). Soll mit dem Wert Code laufen, verwenden Sie .code={... #1 ...}; der übergebene Wert kommt im Code als #1 an. Den Standardwert bei Aufruf ohne =value setzt .default=value, den Anfangswert .initial=value. Auswahlmöglichkeiten lassen sich mit .is choice aufzählen.
\usepackage{pgfkeys}
% キーを定義する / define keys under /book
\pgfkeys{
/book/title/.store in = \bookTitle, % 値をマクロに格納
/book/edition/.code = {Edition #1}, % #1 は渡された値
/book/edition/.default = 1, % =値 省略時の既定
/book/draft/.initial = false, % 初期値
}
% キーを設定する / set them
\pgfkeys{/book/title=TeX by Topic, /book/edition=3}Wenn ein Paket einen Einstieg wie \mypkgsetup{...} anbietet, setzt es meist einen Standardpfad, damit Nutzer nicht jedes Mal /mypkg/ voranstellen müssen. Das Idiom ist \pgfqkeys{/mypkg}{⟨key list⟩} („q“ für quick), eine Kurzform von \pgfkeys{/mypkg/.cd, ⟨key list⟩}. Mit einem einzeiligen Wrapper wie unten konfigurieren Nutzer nur noch mit kurzen Schlüsseln.
% パッケージ側:設定窓口を一行で / the package: a one-line entry point
\newcommand{\mypkgsetup}[1]{\pgfqkeys{/mypkg}{#1}}
% 利用者側:短いキー名で設定 / the user: short key names
\mypkgsetup{title = My Report, edition = 2}Auf der LaTeX3-Seite gibt es die Entsprechung l3keys, das Key-Value-Modul von expl3, mit dem ähnliche Schnittstellen über \keys_define:nn und Verwandte deklariert werden. Eine sinnvolle Trennung: l3keys für neue Pakete in expl3, pgfkeys für Code im TikZ/pgf-Umfeld oder vorhandene Bestände.