LaTeX Optionale Argumente

Antworten:

176

Beispiel aus der Anleitung :

\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.
miku
quelle
21
Ich denke, die Frage war, wie festgestellt werden kann, ob ein optionales Argument angegeben wurde, ohne einen Standardwert bereitzustellen.
Konrad Rudolph
43
Obwohl dies zutrifft, habe ich diese Frage gefunden, als ich nach einer Möglichkeit gesucht habe, ein Standardargument bereitzustellen. Daher war diese Antwort für mich die nützlichste.
Tanner Swett
26

Die allgemeine Idee hinter dem Erstellen von "optionalen Argumenten" besteht darin, zuerst einen Zwischenbefehl zu definieren, der im Voraus scannt, um zu erkennen, welche Zeichen als nächstes im Token-Stream auftauchen, und dann die relevanten Makros einfügt, um die anstehenden Argumente entsprechend zu verarbeiten. Dies kann mit der generischen TeX-Programmierung ziemlich mühsam (wenn auch nicht schwierig) sein. LaTeX \@ifnextcharist für solche Dinge sehr nützlich.

Die beste Antwort auf Ihre Frage ist die Verwendung des neuen xparsePakets. Es ist Teil der LaTeX3-Programmiersuite und enthält umfangreiche Funktionen zum Definieren von Befehlen mit ganz beliebigen optionalen Argumenten.

In Ihrem Beispiel haben Sie ein \secMakro, das entweder ein oder zwei geschweifte Argumente akzeptiert. Dies würde xparsemit folgendem implementiert werden :

\ documentclass {article}
\ usepackage {xparse}
\ begin {document}
\ DeclareDocumentCommand \ sec {mg} {%
    {# 1%
        \ IfNoValueF {# 2} {und # 2}%
    }%
}}
(\ sec {Hallo})
(\ sec {Hallo} {Hallo})
\ end {document}

Das Argument { m g }definiert die Argumente von \sec; mbedeutet "obligatorisches Argument" und gist "optionales Klammerargument". \IfNoValue(T)(F)kann dann verwendet werden, um zu überprüfen, ob das zweite Argument tatsächlich vorhanden war oder nicht. In der Dokumentation finden Sie weitere Arten von optionalen Argumenten, die zulässig sind.

Will Robertson
quelle
4
Wille! Es funktioniert nicht. Ausgabe:(Hello and ) (Hello and Hi)
Alexey Malistov
Danke für das Feedback, Alexey. Ich vermute, Sie verwenden eine ältere Version von xparse. In letzter Zeit wurde viel daran gearbeitet. TeX Live 2009 wurde gerade veröffentlicht :)
Will Robertson
24

All dies zeigt, dass es schwierig sein kann, eine schöne, flexible (oder überlastete) Funktion in LaTeX zu erstellen !!! (Dieser TeX-Code sieht für mich wie Griechisch aus.)

Nun, nur um meine jüngste (wenn auch nicht so flexible) Entwicklung hinzuzufügen, hier ist, was ich kürzlich in meinem Diplomarbeitsdokument verwendet habe, mit

\usepackage{ifthen}  % provides conditonals...

Starten Sie den Befehl, wobei der Befehl "optional" standardmäßig leer ist:

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

Ich habe dann das Makro eine temporäre Variable \ temp {} gesetzt, je nachdem, ob das optionale Argument leer ist oder nicht. Dies kann auf jedes übergebene Argument ausgedehnt 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 Variablen \ temp {} für die beiden Fälle aus. (Hier wird nur die kurze Beschriftung so eingestellt, dass sie 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 das einzelne "optionale" Argument, das \ newcommand {} bereitstellt. Wenn Sie es beispielsweise 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 albern, ich weiß, aber das ist ungefähr so ​​weit, wie ich es mit LaTeX machen werde - es ist einfach nicht so sinnlich, wenn ich mir TeX-Code anschaue ... Ich mag die xparse-Methode von Mr. Robertson, vielleicht auch ich werde es versuchen ...

Demis
quelle
Ich mag diesen Ansatz. Ist eher "programmierartig" und daher leichter zu lesen. Gut gemacht!
Geliebt.von.Jesus
11

Sie benötigen lediglich Folgendes:

\makeatletter
\def\sec#1{\def\tempa{#1}\futurelet\next\sec@i}% Save first argument
\def\sec@i{\ifx\next\bgroup\expandafter\sec@ii\else\expandafter\sec@end\fi}%Check brace
\def\sec@ii#1{\section*{\tempa\ and #1}}%Two args
\def\sec@end{\section*{\tempa}}%Single args
\makeatother

\sec{Hello}
%Output: Hello
\sec{Hello}{Hi}
%Output: Hello and Hi
Alexey Malistov
quelle
Ich dachte, TeX versteht als Parameter die angemessene Anzahl der ersten "Kästchen" nach dem Befehl. Diese 'Box' ist in geschweiften Klammern geschrieben oder es ist ein Symbol. Dh. x^2+1oder x^{2+1} Ich habe also die Frage, ob Ihr Befehl das Vorhandensein von Zahnspangen testet. Ist es möglich, einen LaTeX-Befehl zu erstellen, der Folgendes \secerzeugt: "A, b, c und d" für den Befehl \sec{A}[b,c,d], "A und b" für \sec{A}[b] and "A" for \ sec {A} `?
Crowley
Sie haben zwei Fragen. 1) Ja, mein Befehl testet das Vorhandensein von Zahnspangen. 2) Ja, es ist möglich, ein Makro für \sec{A}[b,c,d]oder \sec{A}[b]oder zu erstellen \sec{A}.
Alexey Malistov
6

Ich hatte ein ähnliches Problem, als ich einen Befehl erstellen wollte, um \dxabzukürzen \;\mathrm{d}x(dh ein zusätzliches Leerzeichen vor das Differential des Integrals zu setzen und das "d" ebenfalls aufrecht zu halten). Aber dann wollte ich es auch flexibel genug machen, um die Integrationsvariable als optionales Argument aufzunehmen. Ich habe den folgenden Code in die Präambel eingefügt.

\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 mit optionalem Argument an

Zar
quelle
-1

Hier ist mein Versuch, er folgt jedoch nicht genau Ihren Spezifikationen. Nicht vollständig getestet, seien Sie also 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"
Dreamlax
quelle