PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Command mit optinalem Argument



latexy
10-10-2012, 17:09
Hallo,

ich wollte einen eigenen Befehl definieren und zwar mit einem optinalen Argument.

Vereinfachtes (aber für die Sache völlig ausreichendes) Beispiel:

Wird nur ein Argument angegeben, soll das hier passieren:
\newcommand{\myCommand}[1]{#1}
Kommt das zweite, optinale, Argument hinzu, so wird ein " - #2" angefügt:
\newcommand{\myCommand}[2]{#1 - #2}

Im Command soll also ein bestimmter Teil nur auftauchen, wenn ein optionales Argument belegt wurde. Wie geht das?

Danke!

bobmalaria
10-10-2012, 18:13
hi,

es gibt viele moeglichkeiten, aber die vielleicht modernste ist das mit xparse zu machen. das ist ein paket aus latex3 (geht aber natuerlich auch mit dem aktuellen latex2e)


\documentclass{article}
\usepackage{xparse}

\DeclareDocumentCommand \my { m o } {% %ein manadtory argument und ein optionales
\IfNoValueTF{#2}{% Wenn #2 leer ist, dann gib nur #1 aus
#1%
}{%
#1-#2 %sonst, gibt #1-#2 aus
}%
}
\begin{document}
\my{Love}\\
\my{Love}[Hate]
\end{document}


das ergibt folgendes:
\my{Love} => Love
\my{Love}[Hate] => Love-Hate

localghost
10-10-2012, 18:20
Dann übernehme ich das mal mit der Syntax aus LaTeX2e.

\documentclass{scrartcl}
\usepackage[T1]{fontenc}

\newcommand{\mycmd}[2][]{#2\ifx#1\empty\else –-#1\fi}

\begin{document}
\mycmd{1} \mycmd[2]{1}
\end{document}


Thorsten

latexy
10-10-2012, 18:33
Danke für eure Hilfe. In localghosts Lösung setzt er bei mir aber kein - dazwischen.

localghost
10-10-2012, 19:16
Ich sollte das besser testen.

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage{selinput}
\SelectInputMappings{
adieresis={ä},
germandbls={ß},
Euro={€}
}

\newcommand{\mycmd}[2][]{#2\ifx#1\empty\else --#1\fi}

\begin{document}
\mycmd{1} \mycmd[2]{1}
\end{document}

cgnieder
10-10-2012, 21:44
\newcommand{\mycmd}[2][]{#2\ifx#1\empty\else --#1\fi}

Clever! Ich hatte mich für einen Moment gewundert, warum der Test funktioniert, wenn #1 leer ist. Aber dann wurde mir klar, dass dann getestet wird, ob \empty gleich \else ist, was natürlich falsch ist. Da es dann aber auch keine \else-Verzweigung mehr gibt, passiert trotzdem nichts :)

latexy
10-10-2012, 22:07
Vielen Dank, war mein Fehler, dass es erst nicht klappte. Jedoch verstehe ich nicht so ganz, was da abläuft. Wo finde ich denn eine Dokumentation der hier verwendeten Befehle? Denn ich würde gerne genau nachvollziehen können, wie die Sache funktioniert.

cgnieder
10-10-2012, 22:30
\ifx ist ein TeX-Befehl, der die beiden nachfolgenden Token (einzelne Buchstaben, Zahlen, Zeichen oder Befehle) auf Gleichheit testet. Gleichheit heißt hier: gleicher character code und gleicher category code. Beschrieben ist er unter anderem in TeX By Topic (http://texdoc.net/pkg/texbytopic). Hier passiert folgendes:


#1 = ""
Wenn "\empty"="\else" (immer falsch) dann "--"
=> nichts passiert

#1 = " "
Wenn " "="\empty" (falsch)
sonst "-- " (wahr)
=> "-- " wird ausgeführt

#1 = "text"
Wenn "text"="\empty" (falsch)
sonst "--text" (wahr)
=> "--text" wird ausgeführt

Mehr LaTeX-artig wird der Befehl mit etoolbox (http://www.ctan.org/pkg/etoolbox):


\usepackage{etoolbox}
\newcommand{\mycmd}[2][]{#2\ifstrempty{#1}{}{--#1}}

Grüße

klops
11-10-2012, 08:54
Ich sollte das besser testen.
Stimmt:

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage{selinput}
\SelectInputMappings{
adieresis={ä},
germandbls={ß},
Euro={€}
}

\newcommand{\mycmd}[2][]{#2\ifx#1\empty\else --#1\fi}

\begin{document}
\mycmd{1} \mycmd[2]{1}
\mycmd[aaber]{ohje}
\end{document}
Da Du in Deiner Lösung ohnehin bereits eine KOMA-Script-Klasse verwendest:

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage{selinput}
\SelectInputMappings{
adieresis={ä},
germandbls={ß},
Euro={€}
}

\newcommand{\mycmd}[2][]{#2\ifstr{#1}{}{}{--#1}}

\begin{document}
\mycmd[aaber]{auch}
\end{document}
oder ohne KOMA-Script-Klasse:
\documentclass{minimal}
\usepackage{scrbase}

\newcommand{\mycmd}[2][]{#2\ifstr{#1}{}{}{--#1}}

\begin{document}
\mycmd{geht}

\mycmd[aaber]{auch}
\end{document}
Wobei es dabei AFAIK Einschränkungen gibt, wenn das Argument nicht voll expandierbar ist.

Oder eben mit etoolbox wie von cgnieger gezeigt.

cgnieder
11-10-2012, 10:03
Da Du in Deiner Lösung ohnehin bereits eine KOMA-Script-Klasse verwendest [...]

\newcommand{\mycmd}[2][]{#2\ifstr{#1}{}{}{--#1}}

Nett! Ich muss wohl das scrbase-Kapitel mal wieder durchlesen...

andere, eher plain-eTeX-Variante die ebenfalls funktioniert (auch in dem Fall in dem #1 mit \relax beginnen sollte):


\newcommand{\mycmd}[2][]{#2\if\relax\detokenize{#1}\relax\else --#1\fi}

Grüße

localghost
11-10-2012, 18:47
Ich werde TeX wohl nie wirklich verstehen.

cgnieder
11-10-2012, 20:41
Ich werde TeX wohl nie wirklich verstehen.

Wie sagte noch Peter Quincy Taggart: „Never give up, never surrender!“ ;)

Der Grund, warum die erste Variante mit dem Argument aaber versagt, sind die beiden a am Anfang. Sie sind die beiden ersten Token, die von \ifx gesehen werden und sie werden konsequenterweise als gleich erkannt:


\ifx#1\empty\else --#1\fi

Argument einsetzen => \ifx aaber\empty\else --aaber\fi
eine Expansion => ber\empty

Grüße

klops
12-10-2012, 11:30
Was man sich bei TeX immer wieder vergegenwärtigen muss ist, dass es eine Makro-Sprache ist, die um einige typisierte Variablen erweitert wurde. Wie Clemens bereits gezeigt hat, bedeutet "Makro-Sprache", dass man keine Funktionen hat, die ausgeführt werden, sondern Makros, die zur Laufzeit expandiert werden. Expansion bedeutet, dass die Definition der Makros wie von Clemens gezeigt direkt eingesetzt wird, wobei Argumente ebenfalls direkt eingesetzt werden. Kompliziert wird das dadurch, dass nicht einfach die String-Definition eingesetzt wird, sondern die Definition zum Zeitpunkt der Definition in Token umgewandelt wird. Das ist bei vielen anderen Makro-Sprachen auch so, wird aber bei TeX durch die vielen Token-Klassen etwas kompliziert. Ebenfalls werden die Argumente bereits in Token umgewandelt, bevor das Makro expandiert wird. Alles tatsächlich nicht trivial.

Der Teil von TeX ist aber tatsächlich recht logisch aufgebaut. So dass man ihn mit ständiger Übung verstehen kann (wenn man erst einmal die Erklärung zu den Primitiven gelesen und verstanden hat). ;)