[en] LaTeX-package 'exp-testopt' - expandable variant of \@testopt Author: Paul Ebermann License: LPPL 1.3b or later, maintained (see http://www.latex-project.org/lppl/). Version: 0.3 All Documentation (other than this file) is in Esperanto. This package is meant for use by other packages. This package provides an expandable variant of the LaTeX kernel command \@testopt, named \@expandable@testopt, and a more general \@expandable@ifopt, both intended for package writers. Also we have a variant of \newcommand which uses these macros to check for optional arguments. This Package needs no other packages for running. The typesetting of the documentation needs additionally class scrartcl (KOMA-script), gmdoc-enhance (from me) and gmdoc (from Grzegorz `Natror' Murzynowski), gmdoc's dependencies, and some required LaTeX packages. The package comes as .dtx + .ins. Run "tex exp-testopt.ins" to create the style file (and maybe put it to texmf/tex/latex/paul/, if your docstrip is configured accordingly), run (after that and maybe updating your TeX hash) "latex exp-testopt.dtx" to create the documentation. (Docstrip also creates an exp-testopt.test in the same directory, which is to be used by the documentation.) Usage ------- There are two main commands for package writers: \@expandable@ifopt{}{} \@expandable@testopt{}{} Both of them try to check, wether following them is a optional argument (this is, some stuff enclosed in []). In this case, they expand to: In the other case, they expand to: [] So, \@expandable@ifopt is a general branch command, while \@expandable@testopt is meant as a replacement for \@testopt, where is "any sequence of commands that 'expects' to be followed by [." (Quoted from ltdefns.dtx.) This replacement has the advantage of being expandable (if is so), but also has quite some limitations. A third command is: \expnewcommand*{}[][]{} This works like \newcommand, but when a command with an optional argument is defined, it uses our expandable check for the existence of the optional argument. (Without the default argument it should work exactly the same.) Examples ---------- The main usage is in definitions of commands, which are to accept optional arguments. \expnewcommand*{\example}[1][Default]{% \fbox{#1}% } Thus \example outputs an box with "Default" in it, while \example[Test] hat "Test" in it. From another package (to be published soon): \expnewcommand*\monthName[2][\languagename]{% \@format@month@name{#1}{\value{#2}}% } This outputs the value of a given LaTeX counter as a name of the like-numbered month, in the given language, the default language being the current babel language. (And here the expansibility is important, since we don't want the value of the counter when this is printed, but now, also when this ends up in the table of contents.) When you want more control, you may use \@expandable@ifopt{}{}: \def\exampleOne{% \@expandable@ifopt{% \exampleOneOpt}{% \exampleOneNoOpt}% } \def\exampleOneOpt[#1]{#2}{ % do something with #1 and #2 } \def\exampleOneNoOpt#1{% % do some other thing with #1 } With \@expandable@testopt{}{} you may also create commands which accept more than one optional argument. Benefits ---------- The advantages of \expnewcommand and \@expandable@testopt to \newcommand and \@testopt are in the expandibility of the created commands - you can use them in moving arguments (like inside of \protected@edef, \protected@write and so on), and the accessed variables then have their current meanings (or the meaning at shipout time, for write), not the meanings when the thing is finally typeset. \newcommand, on the other hand, creates protected commands - you can use them also in moving arguments, but they are evaluated only at typesetting time. What to use when depends heavily on the use case. Limitations ------------- Since we want to be expandable, we really can't check the next token, but only the next "macro argument". And comparing also is not so easy when you can't assign something to a macro. So, we use as a workaround making a control sequence from the next argument (trying to neutralize a bit things like control sequences), and comparing them to a known control sequence. This has the following consequences: - we cant distinguish between [ and {[} - the second one is also regarded as a "start of optional argument". - the next argument (when it is not simple '[') has to be of a "friendly" kind - it should not contain braces, and any "dangerous" token (anything not of category 10, 11, 12) should come as the first token (only then it is neutralized). (Often the next argument is only one token, then this is no problem. Or it will be simple text, also no problem.) Otherwise, there will be strange errormessages. - multiple space tokens before the [ may irritate our macros. So, before using this macros, make sure the limitations don't affect you. Have fun! ------------- [de] LaTeX-Paket 'exp-testopt' - Expandierbare Variante von \@testopt. Autor: Paul Ebermann (Paul-Ebermann@gmx.de). Lizenz: LPPL 1.3b oder später, mit Maintenance-Status "author-maintained". Siehe http://www.latex-project.org/lppl/. Version 0.3 Geschrieben für eigenen Gebrauch (d.h. für Nutzung in anderen LaTeX-Paketen von Paul Ebermann), aber vielleicht ist es auch für andere von Nutzen. Die Dokumentation (außer dieser Datei) ist nur auf Esperanto. Dieses Paket ist für Verwendung in anderen LaTeX-Paketen gedacht. Es enthält eine expandierbare Variante des LaTeX-Kernel-Kommandos \@testopt unter dem Namen \@expandable@testopt, eine Verallgemeinerung davon als \@expandable@ifopt sowie eine Variante von \newcommand, welche diese Makros nutzt, um die Existenz optionaler Argumente festzustellen. Das Paket kommt als .dtx + .ins. Mit "latex exp-testopt.ins" wird die .sty-Datei erstellt (und eventuell gleich nach texmf/tex/latex/paul/ installiert, wenn docstrip entsprechend eingerichtet ist), mit "latex exp-testopt.dtx" kann (danach und eventuell nach einer Aktualisierung der TeX-Dateidatenbank) die Dokumentation neu erstellt werden. Docstrip erstellt auch eine Datei exp-testopt.test, welche nur von der Dokumentation verwendet wird (vom Paket nicht verwendet). Anwendung ---------- Die beiden Haupt-Kommandos für Package-Autoren: \@expandable@ifopt{}{} \@expandable@testopt{}{} Beide versuchen herauszufinden, ob nach ihnen ein optionales Argument folgt (das ist irgend etwas, was in [...] eingeschlossen ist). In diesem Fall expandieren diese Makros zu: Im anderen Fall expandieren sie zu: [] \@expandable@ifopt ist also ein genereller Verzweigungsbefehl, während \@expandable@testopt (welches dem Paket den Namen gab) ein Ersatz für \@testopt aus dem LaTeX-Kernes ist: hier sollte eine beliebige Sequenz von Kommandos sein, welche es 'erwartet', von [ gefolgt zu werden. (Frei übersetzt aus ltdefns.dtx.) Damit kann man Makros mit optionalen Argumenten und Defaultwerten für diese bauen. Dieser Ersatz hat den Vorteil, expandierbar zu sein (falls dies ist), hat aber auch einige Beschränkungen (siehe unten). Ein drittes Kommando ist: \expnewcommand*{}[][]{} Es funktioniert analog zu \newcommand, mit dem Unterschied, dass (falls gegeben ist) die Überprüfung auf optionale Argumente mit unserem \@expandable@testopt anstatt mit \@testopt (bzw. seiner protected-Variante) geschieht. (Ohne diesen Default-Wert sollten beide Definitionen exakt identisch sein.) Beispiele ----------- Die Hauptverwendung wird die Definition von Kommandos mit optionalen Argumenten sein: \expnewcommand*{\example}[1][Default]{% \fbox{#1}% } Hier gibt \example einen Kasten mit "Default" drin aus, wobei \example[Test] ein "Test" im Kasten hat. Aus einem meiner anderen Packages (wird bald veröffentlicht) sinngemäß: \expnewcommand*\monthName[2][\languagename]{% \@format@month@name{#1}{\value{#2}}% } Das gibt den Wert eines LaTeX-Zählers in der Form eines Monatsnamens in der gewählten Sprache aus, wobei der Default die aktuelle Babel-Sprache ist. (Hierbei braucht man die Expansibilität wirklich, denn wir wollen ja den aktuellen Wert des Zählers (und der Sprache) haben, auch wenn das ganze nachher im Inhaltsverzeichnis landet, wo eventuell andere Werte aktuell sind.) Mehr Kontrolle bekommt man mit \@expandable@ifopt: \def\exampleOne{% \@expandable@ifopt{% \exampleOneOpt}{% \exampleOneNoOpt}% } \def\exampleOneOpt[#1]#2{ % mache etwas mit #1 und #2 } \def\exampleOneNoOpt#1{% % mache etwas ganz anderes mit #1 } Mit \@expandable@testopt kann man auch Kommandos basteln, welche mehr als ein optionales Argument enthalten. Vorteile --------- Die Vorteile von \expnewcommand sowie \@expandable@testopt im Vergleich zu \newcommand und \@testopt aus dem Kernel liegen in der Expandierbarkeit der erstellten Kommandos - man kann sie innerhalb von bewegten Argumenten nutzen (wie \protexted@edef, \@protected@write etc.) und die darin verwendeten Variablen haben dann ihre aktuellen Werte, nicht die Werte, wenn der Text endlich gesetzt wird. \newcommand (mit den optionalen Argumenten) erstellt "geschützte" Kommandos - man kann sie in bewegten Argumenten verwenden, aber sie werden erst dann ausgewertet, wenn sie gesetzt werden. Welche der beiden Möglichkeiten besser ist, hängt stark von der jeweiligen Situation ab. Begrenzungen -------------- Weil wir expandierbare Makros haben wollen, können wir nicht wirklich (wie es \@testopt macht) das nächste Token überprüfen, sondern nur das "nächste Makro-Argument". Der Vergleich ist auch nicht einfach, wenn man keine Zuweisungen/Definitionen machen darf. Als Workaround erstellen wir eine Kontrollsequenz aus dem nächsten Argument (und versuchen dabei, es etwas unschädlich zu machen), und vergleichen diese mit einer bekannten Kontrollsequenz. Das hat die folgenden Konsequenzen: - Wir können nicht zwischen [ und {[} unterscheiden - auch das zweite wird als "Anfang eines optionalen Argumentes" interpretiert. - Das nächste Argument (wenn es denn nicht ein einfaches '[' ist) muss sich friedlich verhalten - es sollte keine {} enthalten, und andere gefährliche Token (alles, was nicht Kategorie 10, 11, 12 hat) sollten nur an erster Stelle auftauchen (da können sie unschädlich gemacht werden). (Wenn das nächste Argument nur aus einem Token besteht, ist das kein Problem, auch nicht, wenn es einfach nur Text ist.) Andernfalls kann es zu merkwürdigen Fehlermeldungen kommen. - Falls vor dem '[' mehrere Leerzeichen-Token kommen, kann das unsere Makros verwirren. Also, bitte vor dem Verwenden dieser Makros aufpassen, dass die Beschränkungen nicht stören. Viel Spaß! ---------- [eo] LaTeX-pakaĵo 'exp-testopt' - plibonigoj por gmdoc. (Se vi ne scias, kio estas gmdoc, legu sube.) Aŭtoro: Paŭlo Ebermann (Paul-Ebermann@gmx.de). Licenzo: LPPL 1.3, 'maintained' (-> http://www.latex-project.org/lppl/). Versio 0.3 Kreitaj por propra uzo, sed eble iom de ĝi ankaŭ uzeblas por aliaj. La dokumentaro (escepte tiu ĉi dosiero) estas nur en la germana lingvo. La pakaĵo ne bezonas ajnajn aliajn pakaĵojn. Por la dokumentado bezonatas gmdoc, gmdoc-enhance kaj scrartcl (KOMA-script). La pakaĵo venas en .dtx + .ins. Voku "latex exp-testopt.ins" por krei la .sty-dosieron (kaj eble meti ĝin al texmf/tex/latex/paul/, se via docstrip estis konfigurita laŭe), voku "latex exp-testopt.dtx" por rekrei la dokumentaron. La dokumentaĵo estas en exp-testopt.pdf.