2009-11-28 11 views
88

Wie erstellen Sie einen Befehl mit optionalen Argumenten in LaTeX? Etwas wie:LaTeX Optionale Argumente

\newcommand{\sec}[2][]{ 
    \section*{#1 
     \ifsecondargument 
      and #2 
     \fi} 
    } 
} 

Dann kann ich es nennen wie

\sec{Hello} 
%Output: Hello 
\sec{Hello}{Hi} 
%Output: Hello and Hi 
+5

Relevante Frage: [Verschiedene Befehlsdefinitionen mit und ohne optionales Argument] (http://tex.stackexchange.com/q/308/1347) . –

Antwort

111

Beispiel aus dem guide:

\newcommand{\example}[2][YYY]{Mandatory arg: #2; 
           Optional arg: #1.} 

This defines \example to be a command with two arguments, 
referred to as #1 and #2 in the {<definition>}--nothing new so far. 
But by adding a second optional argument to this \newcommand 
(the [YYY]) the first argument (#1) of the newly defined 
command \example is made optional with its default value being YYY. 

Thus the usage of \example is either: 

    \example{BBB} 
which prints: 
Mandatory arg: BBB; Optional arg: YYY. 
or: 
    \example[XXX]{AAA} 
which prints: 
Mandatory arg: AAA; Optional arg: XXX. 
+15

Ich denke, die Frage war, wie man bestimmen kann * ob * ein optionales Argument gegeben wurde, nicht als Vorgabe. –

+28

Obwohl das stimmt, habe ich diese Frage bei der Suche nach einer Möglichkeit gefunden, ein Standardargument anzugeben. Daher war diese Antwort für mich die nützlichste. –

18

Die allgemeine Idee "optionale Argumente" hinter der Erstellung ist es, zunächst zu definieren ein Zwischenbefehl, der voraus scannt, um zu erkennen, welche Zeichen als nächstes im Token-Datenstrom erscheinen, und dann die relevanten Makros einfügt, um die aufkommenden Argumente zu verarbeiten wie angemessen. Dies kann ziemlich mühsam (wenn auch nicht schwierig) mit der generischen TeX-Programmierung sein. LaTeX's \@ifnextchar ist ziemlich nützlich für solche Dinge.

Die beste Antwort für Ihre Frage ist die Verwendung des neuen xparse Pakets. Es ist Teil der LaTeX3-Programmierumgebung und enthält umfangreiche Funktionen zur Definition von Befehlen mit beliebigen optionalen Argumenten.

In Ihrem Beispiel haben Sie einen \sec Makro, der entweder ein oder zwei Argumente akzeptiert. Dies würde unter Verwendung umgesetzt xparse mit den folgenden:

 
\documentclass{article} 
\usepackage{xparse} 
\begin{document} 
\DeclareDocumentCommand\sec{ m g }{% 
    {#1% 
     \IfNoValueF {#2} { and #2}% 
    }% 
} 
(\sec{Hello}) 
(\sec{Hello}{Hi}) 
\end{document} 

Das Argument { m g } die Argumente von \sec definiert; m bedeutet "obligatorisches Argument" und g ist "optionale Klammer Argument". \IfNoValue(T)(F) kann dann verwendet werden, um zu überprüfen, ob das zweite Argument tatsächlich vorhanden war oder nicht. Weitere mögliche optionale Argumente finden Sie in der Dokumentation.

+4

Wird! Es funktioniert nicht. Ausgabe: '(Hallo und) (Hallo und Hallo)' –

+0

Danke für das Feedback, Alexey. Ich vermute, dass Sie eine ältere Version von Xparse verwenden; In letzter Zeit wurde viel daran gearbeitet. TeX Live 2009 wurde gerade veröffentlicht :) –

12

Alles, was Sie brauchen, ist die folgende:

\makeatletter 
\def\sec#1{\def\tempa{#1}\futurelet\next\[email protected]}% Save first argument 
\def\[email protected]{\ifx\next\bgroup\expandafter\[email protected]\else\expandafter\[email protected]\fi}%Check brace 
\def\[email protected]#1{\section*{\tempa\ and #1}}%Two args 
\def\[email protected]{\section*{\tempa}}%Single args 
\makeatother 

\sec{Hello} 
%Output: Hello 
\sec{Hello}{Hi} 
%Output: Hello and Hi 
+0

Ich dachte, TeX versteht als Parameter die richtige Anzahl der ersten 'Boxen' nach dem Befehl. Diese 'Box' ist in geschweiften Klammern geschrieben oder es ist ein Symbol. Ie. 'x^2 + 1' oder' x^{2 + 1} ' Also habe ich Frage, testet Ihr Befehl Vorhandensein von Zahnspangen? Ist es möglich, den LaTeX-Befehl '\ sec' zu erzeugen: " A, b, c und d "für Befehl' \ sec {A} [b, c, d] ', " A und b "für' \ sec {A} [b] und "A" für '\ sec {A}'? – Crowley

+0

Sie haben zwei Fragen. 1) Ja, mein Befehl testet die Anwesenheit von Zahnspangen. 2) Ja, es ist möglich, ein Makro für '\ sec {A} [b, c, d]' oder '\ sec {A} [b]' oder '\ sec {A}' zu erstellen. –

-1

Hier ist mein Versuch, es nicht Ihren Angaben genau obwohl folgen. Nicht vollständig getestet, also sei vorsichtig.

\newcount\seccount 

\def\sec{% 
    \seccount0% 
    \let\go\secnext\go 
} 

\def\secnext#1{% 
    \def\last{#1}% 
    \futurelet\next\secparse 
} 

\def\secparse{% 
    \ifx\next\bgroup 
     \let\go\secparseii 
    \else 
     \let\go\seclast 
    \fi 
    \go 
} 

\def\secparseii#1{% 
    \ifnum\seccount>0, \fi 
    \advance\seccount1\relax 
    \last 
    \def\last{#1}% 
    \futurelet\next\secparse 
} 

\def\seclast{\ifnum\seccount>0{} and \fi\last}% 

\sec{a}{b}{c}{d}{e} 
% outputs "a, b, c, d and e" 

\sec{a} 
% outputs "a" 

\sec{a}{b} 
% outputs "a and b" 
17

Alle oben genannten Show schwer es sein kann, ein schöner zu machen, flexibel (oder eine überlastete bewahre) Funktion in LaTeX !!! (Der TeX-Code wie griechisch ich aussieht)

gut, nur meine letzte hinzuzufügen (wenn auch nicht so flexibel) Entwicklung, ist hier, was ich vor kurzem in meiner Arbeit doc verwendet habe, mit

\usepackage{ifthen} % provides conditonals... 

starten der Befehl, mit dem „optional“ Befehl standardmäßig leer:

\newcommand {\figHoriz} [4] [] { 

ich dann das Makro gesetzt habe eine temporäre Variable, \ temp {}, unterschiedlich, je nachdem, ob das optionale Argument ist leer. Dies könnte auf jedes bestandene Argument erweitert werden.

\ifthenelse { \equal {#1} {} } %if short caption not specified, use long caption (no slant) 
    { \def\temp {\caption[#4]{\textsl{#4}}} } % if #1 == blank 
    { \def\temp {\caption[#1]{\textsl{#4}}} } % else (not blank) 

Dann führe ich das Makro mit der Variable \ temp {} für die beiden Fälle. (Hier wird nur die kurze Überschrift festgelegt, die der langen Beschriftung entspricht, wenn sie nicht vom Benutzer angegeben wurde).

\begin{figure}[!] 
    \begin{center} 
     \includegraphics[width=350 pt]{#3} 
     \temp %see above for caption etc. 
     \label{#2} 
    \end{center} 
\end{figure} 
} 

In diesem Fall überprüfe ich nur für das einzelne, "optionale" Argument, das \ newcommand {} zur Verfügung stellt. Wenn Sie es zum Beispiel für 3 "optionale" Argumente einrichten würden, müssten Sie immer noch die 3 leeren Argumente senden ... z.

\MyCommand {first arg} {} {} {} 

das ist ziemlich dumm, ich weiß, aber das ist so weit ich mit LaTeX gehen werde - es ist einfach nicht so unsinnig, wenn ich bei TeX-Code starten auf der Suche ... Ich mag Mr. Robertsons xparse Methode aber vielleicht werde ich versuchen, es ...

+0

Ich mag diesen Ansatz. Ist "programmierbarer" und daher leichter zu lesen. Gut gemacht! –

1

ich hatte ein ähnliches Problem, wenn ich einen Befehl erstellen wollte, \dx, abzukürzen \;\mathrm{d}x (dh stellte einen zusätzlichen Raum vor dem Differential der integralen und habe das "d" auch aufrecht). Aber ich wollte es auch flexibel genug machen, um die Variable der Integration als optionales Argument einzubeziehen. Ich habe den folgenden Code in die Präambel geschrieben.

\usepackage{ifthen} 

\newcommand{\dx}[1][]{% 
    \ifthenelse{ \equal{#1}{} } 
     {\ensuremath{\;\mathrm{d}x}} 
     {\ensuremath{\;\mathrm{d}#1}} 
} 

Dann

\begin{document} 
    $$\int x\dx$$ 
    $$\int t\dx[t]$$ 
\end{document} 

gibt \dx with optional argument

Verwandte Themen