
Nachdem ich ein funktionierendes Makro hatte, habe ich versucht, es zu verbessern, indem ich einige Parameter optional machte. Leider funktioniert das Makro nicht mehr. Stattdessen erhalte ich Fehlermeldungen, die ich nicht verstehe, zum Beispiel:
LaTeX Warning: Label `####5' multiply defined.
LaTeX Warning: Label `####5' multiply defined.
! LaTeX Error: \fLab undefined.
! Illegal parameter number in definition of \fLab.
! Illegal parameter number in definition of \reserved@a.
! LaTeX Error: \fCap undefined.
...und so weiter. Der letzte Code, den ich ausprobiert habe, sah so aus:
%% Graphics figure with caption and label
% [1:placement,] 2:relative width, 3:file name[, 4:caption[, 5:label]]
\newcommand{\figCapLab}[5][htbp]{%
\ifthenelse{\equal{#5}{}}%
{\renewcommand{\fLab}{}}%
{\renewcommand{\fLab}{\label{##5}}}%
\ifthenelse{\equal{#4}{}}%
{\renewcommand{\fCap}{\fLab}}%
{\renewcommand{\fCap}{\caption{\fLab{\small{}##4}}}}%
\begin{figure}[#1]%
\centering%
\begin{minipage}[t]{#2\textwidth}%
\includegraphics[width=\textwidth]{#3}% is width of surrounding minipage
\fCap%
\end{minipage}%
\end{figure}
}
%% Graphics figure with caption
% [1:placement,] 2:relative width, 3:file name, 4:caption
\newcommand{\figCap}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{#4}{}}%
{\figCapLab[#1]{#2}{#3}{#4}{}}%
}
%% Graphics figure with label
% [1:placement,] 2:relative width, 3:file name, 4:label
\newcommand{\figLab}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{}{#4}}%
{\figCapLab[#1]{#2}{#3}{}{#4}}%
}
Wer kann erklären, was schief gelaufen ist?
Wer vollständige Beispiele mag, sollte diesen Prolog hinzufügen:
\documentclass[a4paper,twoside]{report}
\usepackage{german}
\usepackage[latin1]{inputenc}
\usepackage{a4}
\usepackage{amsmath}
\usepackage{url}
\usepackage{graphicx}
\usepackage{ifthen}
...und dieser Epilog:
\begin{document}
See \ref{foo}.
\figCapLab{0.9}{whatever.pdf}{Caption}{foo}
\end{document}
Antwort1
Wenn ich Ihren vagen Anweisungen folge, um selbst ein kompilierbares Beispiel zu erstellen, das das fehlerhafte Verhalten aufweist
\documentclass[a4paper,twoside]{report}
\usepackage{german}
\usepackage[latin1]{inputenc}
\usepackage{a4}
\usepackage{amsmath}
\usepackage{url}
\usepackage{graphicx}
\usepackage{ifthen}
%% Graphics figure with caption and label
% [1:placement,] 2:relative width, 3:file name[, 4:caption[, 5:label]]
\newcommand{\figCapLab}[5][htbp]{%
\ifthenelse{\equal{#5}{}}%
{\renewcommand{\fLab}{}}%
{\renewcommand{\fLab}{\label{##5}}}%
\ifthenelse{\equal{#4}{}}%
{\renewcommand{\fCap}{\fLab}}%
{\renewcommand{\fCap}{\caption{\fLab{\small{}##4}}}}%
\begin{figure}[#1]%
\centering%
\begin{minipage}[t]{#2\textwidth}%
\includegraphics[width=\textwidth]{#3}% is width of surrounding minipage
\fCap%
\end{minipage}%
\end{figure}
}
%% Graphics figure with caption
% [1:placement,] 2:relative width, 3:file name, 4:caption
\newcommand{\figCap}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{#4}{}}%
{\figCapLab[#1]{#2}{#3}{#4}{}}%
}
%% Graphics figure with label
% [1:placement,] 2:relative width, 3:file name, 4:label
\newcommand{\figLab}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{}{#4}}%
{\figCapLab[#1]{#2}{#3}{}{#4}}%
}
\begin{document}
See \ref{foo}.
\figCapLab{0.9}{whatever.pdf}{Caption}{foo}
\end{document}
, ich erhalte keinen der von Ihnen beschriebenen Fehler, aber ich erhalte:
LaTeX Warning: Reference `foo' on page 1 undefined on input line 43.
! LaTeX Error: \fLab undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
! Illegal parameter number in definition of \fLab.
<to be read again>
5
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
! LaTeX Error: \fCap undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
! Illegal parameter number in definition of \fCap.
<to be read again>
4
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
LaTeX Warning: File `whatever.pdf' not found on input line 44.
! Package pdftex.def Error: File `whatever.pdf' not found: using draft setting.
See the pdftex.def package documentation for explanation.
Type H <return> for immediate help.
...
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
! Illegal parameter number in definition of \reserved@a.
<to be read again>
4
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
! Illegal parameter number in definition of \reserved@a.
<to be read again>
5
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
! You can't use `macro parameter character #' in restricted horizontal mode.
<argument> ...e : \ignorespaces \fLab {\small {}##
4}
l.44 \figCapLab{0.9}{whatever.pdf}{Caption}{foo}
?
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] (./test.aux)
LaTeX Warning: There were undefined references.
Wenn ich stattdessen Folgendes tue:
\documentclass[a4paper,twoside]{report}
\usepackage{german}
\usepackage[latin1]{inputenc}
\usepackage{a4}
\usepackage{amsmath}
\usepackage{url}
\usepackage{graphicx}
\usepackage{ifthen}
% As later \renwecommand is done on these macros,
% they should be defined: !!!!!!!!!!!!
\newcommand{\fLab}{}
\newcommand{\fCap}{}
%% Graphics figure with caption and label
% #1: optional: placement
% #2: non-optional: relative width
% #3: non-optional: file name
% #4: non-optional: in case not empty: caption
% #5: non-optional: in case not empty: label
\newcommand{\figCapLab}[5][htbp]{%
\ifthenelse{\equal{#5}{}}%
{\renewcommand{\fLab}{}}%
{\renewcommand{\fLab}{\label{#5}}}% !!!!Don't double the hash!!!!
\ifthenelse{\equal{#4}{}}%
{\renewcommand{\fCap}{\fLab}}%
{\renewcommand{\fCap}{\caption{\fLab{\small{}#4}}}}% !!!!Don't double the hash!!!!
\begin{figure}[#1]%
\centering
\begin{minipage}[t]{#2\textwidth}%
\includegraphics[width=\textwidth]{#3}% is width of surrounding minipage
\fCap
\end{minipage}%
\end{figure}%%%%%%%
}
%% Graphics figure with caption
% [1:placement,] 2:relative width, 3:file name, 4:caption
\newcommand{\figCap}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{#4}{}}%
{\figCapLab[#1]{#2}{#3}{#4}{}}%
}
%% Graphics figure with label
% [1:placement,] 2:relative width, 3:file name, 4:label
\newcommand{\figLab}[4]{%
\ifthenelse{\equal{#1}{}}%
{\figCapLab{#2}{#3}{}{#4}}%
{\figCapLab[#1]{#2}{#3}{}{#4}}%
}
\begin{document}
See \ref{foo}.
\figCapLab{0.9}{example-grid-100x100pt.pdf}{Caption}{foo}
\end{document}
, dann bekomme ich bei der zweiten Kompilierung keine Fehler oder Warnungen.
Übrigens 1:
Ich habe nichtwas auch immer.pdfin den Texmf-Bäumen meines Systems.
Wenn Sie Beispiele bereitstellen möchten, die Bilder verarbeiten, können Sie die gebrauchsfertigen Bilder verwenden, die Ihnen moderne LaTeX-Systeme zur Verfügung stellen:
So etwa die Dokumentation von Martin ScharrersMWE-Paketlistet alle Bilder auf, die durch dieses Paket verfügbar sind. Mit aktuellen TeX-Plattformen und aktuellen Versionen desMWE-Paket, die Bilder sind nutzbar ohne dass das Paket geladen werden muss, da sie in den Texmf-Baum und in die Dateinamen-Datenbank integriert sind.
Übrigens 2:
Unter normalen Umständen können Sie Zeilen des TeX-Quellcodes einrücken, um die Lesbarkeit zu verbessern. ;-) Das liegt daran, dass, wenn (La)TeX beginnt, eine Eingabezeile zu lesen, sich der Zustand des Lesegeräts im Zustand N (neue Zeile) befindet, während im Zustand N Zeichen des Kategoriecodes 10 (Leerzeichen) nicht als Leerzeichen-Token tokenisiert werden, sondern überhaupt keine Token erzeugen.
Übrigens 3:
Es empfiehlt sich, Beispiele bereitzustellen, die die Benutzer so kompilieren können, wie sie sind, um das fehlerhafte Verhalten exakt zu reproduzieren. Die Fähigkeit, fehlerhaftes Verhalten zu reproduzieren, ist wichtig, um den Code debuggen zu können, der dieses fehlerhafte Verhalten erzeugt.
Dr. Nicola TalbotsErstellen eines minimalen LaTeX-Beispielsbietet einige Richtlinien.
Es gibt auchWie man ein „Minimalbeispiel“ erstelltvon texfaq.org, das auch einige Links mit Ratschlägen zum Stellen von Fragen enthält.
InWas ist ein minimales funktionierendes Beispiel?Christian Faulhammer verwendet zwar nicht den Begriff „Minimalbeispiel“, aber er benutzt den Begriff „Minimal Working Example“, und zwar sogar für Beispiele, die nur in dem Sinne funktionieren, dass sie ausreichen, um ein fehlerhaftes Verhalten aufzuzeigen.
Vielleicht interessieren Sie sich auch für die Antworten auf die FrageIch wurde gerade gebeten, ein Minimalbeispiel zu schreiben. Was ist das?
Antwort2
Der OP hat mich um eine kleine Erklärung zu dieser Antwort gebeten, daher werde ich hier etwas Text hinzufügen. Der Standard-LaTeX-Mechanismus für optionale Argumente erlaubt ein optionales Argument, das vor obligatorischen Argumenten steht. Um also eine Syntax zu erstellen, die ein optionales Argument, 2 obligatorische Argumente und dann 2 optionale Argumente bereitstellt, müssen 3 Makros nacheinander aneinandergereiht werden, da 3 optionale Argumente angefordert werden.
Das erste Makro nimmt ein optionales und zwei obligatorische Argumente auf und muss dann ein zweites Makro aufrufen. Hier ist der Schlüssel:als seine letzte Aktion! Der Grund, warum der Aufruf des zweiten Makros die letzte Aktion des ersten Makros sein muss, besteht darin, dass das zweite Makro ein optionales Argument aufnehmen muss. Wenn das erste Makro Token enthält, die dem Aufruf des zweiten Makros in der Kette folgen, werden diese anderen Token des ersten Makros als Argument aufgenommen, anstatt wie beabsichtigt.
Ebenso muss das 2. Makro als letzte Aktion das 3. Makro aufrufen.
Einige skurrile Highlights:
wenn das Folgemakro innerhalb eines
\if
Blocks aufgerufen werden soll, muss\expandafter
vor dem Folgemakro eines stehen, damit das Folgemakro nicht versucht, das\else
oder zu absorbieren\fi
.In diesem speziellen Fall kann das letzte optionale Argument, das Label, nur aufgerufen werden, wenn eine Überschrift angegeben wurde. Daher ruft das zweite Makro in der Kette das dritte Makro nur auf, wenn eine Überschrift angegeben wurde. Andernfalls wird die Sequenz abgeschnitten.
Das MWE:
\documentclass{article}
\usepackage{graphicx}
\newcommand\addtofigtoks[1]{\expandafter\figtoks\expandafter
{\the\figtoks#1}}
\newtoks\figtoks
\newcommand\figCapLab[3][htbp]{%
\figtoks{\begin{figure}[#1]}
\addtofigtoks{\centering}
\addtofigtoks{\includegraphics[width=#2\textwidth]{#3}}
\optcap
}
\newcommand\optcap[1][\relax]{%
\ifx\relax#1\relax
\addtofigtoks{\end{figure}}
\the\figtoks
\else
\addtofigtoks{\caption{#1}}%
\expandafter\labelopt
\fi
}
\newcommand\labelopt[1][\relax]{%
\ifx\relax#1\relax\else\addtofigtoks{\label{#1}}\fi
\addtofigtoks{\end{figure}}
\the\figtoks
}
\begin{document}
\figCapLab{.2}{example-image-a}
\figCapLab{.2}{example-image-b}[My caption]
\figCapLab{.2}{example-image-c}[My caption][fg:label1]
\figCapLab[p]{.2}{example-image}[Other caption][fg:label2]
In figures \ref{fg:label1} and \ref{fg:label2}...
\end{document}
Ack-shu-ally, je mehr ich darüber nachdenke, desto mehr werden Tokens benötigt:
\documentclass{article}
\usepackage{graphicx}
\newcommand\figCapLab[3][htbp]{%
\begin{figure}[#1]
\centering
\includegraphics[width=#2\textwidth]{#3}
\optcap
}
\newcommand\optcap[1][\relax]{%
\ifx\relax#1\relax
\end{figure}
\else
\caption{#1}%
\expandafter\labelopt
\fi
}
\newcommand\labelopt[1][\relax]{%
\ifx\relax#1\relax\else\label{#1}\fi
\end{figure}
}
\begin{document}
\figCapLab{.2}{example-image-a}
\figCapLab{.2}{example-image-b}[My caption]
\figCapLab{.2}{example-image-c}[My caption][fg:label1]
\figCapLab[p]{.2}{example-image}[Other caption][fg:label2]
In figures \ref{fg:label1} and \ref{fg:label2}...
\end{document}
Antwort3
So erreichen Sie Ihr Ziel mitxparse
:
\documentclass{article}
\usepackage{graphicx,xparse}
% \figCapLab
% [<float spec>] #1
% {<width factor>} #2
% {<image>} #3
% [<caption>] #4
% [<label>] #5
\NewDocumentCommand{\figCapLab}{ O{htbp} m m o o }{%
\begin{figure}[#1]
\centering
\includegraphics[width=#2\linewidth]{#3}% Set image at width
\IfValueT{#4}
{\caption{#4}\IfValueT{#5}{\label{#5}}}% Set possible \caption and \label
\end{figure}
}
\begin{document}
\figCapLab{.2}{example-image-a}
\figCapLab{.2}{example-image-b}[My caption]
\figCapLab{.2}{example-image-c}[My caption][fg:label1]
\figCapLab[p]{.2}{example-image}[Other caption][fg:label2]
In figures \ref{fg:label1} and \ref{fg:label2}\ldots
\end{document}
Optionale Argumente mit einem Standardwert werden mit angegeben, O{<default>}
während optionale Argumente ohne Standardwert verwendet werden o
. Die Bedingung, ob ein Wert angegeben wird oder nicht, wird mit erfüllt \IfValueTF{<parameter>}{<true>}{<false>}
. Es gibt auch singuläre Konditionale \IfValueT
und \IfValueF
, wobei ersteres oben verwendet wurde.
Der obige Code geht davon aus, dass eine leere Überschrift (leeres viertes Argument) kein (fünftes) Argument benötigt \label
. Wenn dies erforderlich ist, verschieben Sie den \IfValueT{#5}{\label{#5}}
Zweig <true>
nach innen \IfValueT{#4}
:
\NewDocumentCommand{\figCapLab}{ O{htbp} m m o o }{%
\begin{figure}[#1]
\centering
\includegraphics[width=#2\textwidth]{#3}% Set image at width
\IfValueT{#4}{\caption{#4}}% Possible \caption
\IfValueT{#5}{\label{#5}}% Possible \label
\end{figure}
}