
После того, как у меня появился работающий макрос, я попытался улучшить его, сделав некоторые параметры необязательными. К сожалению, макрос больше не работает. Вместо этого я получаю непонятные мне ошибки, например:
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.
...и так далее. Последний код, который я попробовал, выглядел так:
%% 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}}%
}
Кто может объяснить, что пошло не так?
Те, кто любит полные примеры, могут добавить этот пролог:
\documentclass[a4paper,twoside]{report}
\usepackage{german}
\usepackage[latin1]{inputenc}
\usepackage{a4}
\usepackage{amsmath}
\usepackage{url}
\usepackage{graphicx}
\usepackage{ifthen}
...и этот эпилог:
\begin{document}
See \ref{foo}.
\figCapLab{0.9}{whatever.pdf}{Caption}{foo}
\end{document}
решение1
Когда я следую вашим расплывчатым инструкциям по созданию компилируемого примера самостоятельно, который демонстрирует ошибочное поведение
\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}
, у меня нет ни одной из описанных вами ошибок, но я получаю:
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.
Когда вместо этого я делаю:
\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}
, то при второй компиляции я не получаю никаких ошибок или предупреждений.
Кстати 1:
У меня нетчто угодно.pdfв texmf-деревьях моей системы.
Если вы хотите предоставить примеры обработки изображений, вы можете использовать готовые изображения, которые вам предлагают современные системы LaTeX:
Например, документация Мартина ШаррераПакет МВЭперечисляет все изображения, доступные благодаря этому пакету. С текущими TeX-платформами и текущими выпускамиMWE-пакетизображения можно использовать без необходимости загрузки пакета, поскольку они интегрированы в texmf-tree и в базу данных имен файлов.
Кстати 2:
В обычных обстоятельствах вы можете делать отступы в строках исходного кода TeX для улучшения читабельности. ;-) Это происходит потому, что когда (La)TeX начинает считывать строку ввода, состояние считывающего устройства находится в состоянии N (новая строка), в то время как в состоянии N символы с кодом категории 10 (пробел) не будут токенизированы как пробельные токены, но и не дадут никаких токенов вообще.
Кстати 3:
Хорошей практикой является предоставление примеров, которые люди могут скомпилировать такими, какие они есть, для точного воспроизведения ошибочного поведения. Возможность воспроизвести ошибочное поведение важна для возможности отладки кода, который производит это ошибочное поведение.
Доктор Никола ТэлботСоздание минимального примера LaTeXдает некоторые рекомендации.
Также естьКак сделать «минимальный пример»с сайта texfaq.org, где также содержатся ссылки на советы по заданию вопросов.
ВКаков минимальный рабочий пример?Кристиан Фолхаммер не использует термин «минимальный пример», но он использует термин «минимальный рабочий пример» даже для примеров, которые работают только в том смысле, что они достаточны для демонстрации ошибочного поведения.
Вас также могут заинтересовать ответы на вопросМеня только что попросили написать минимальный пример. Что это?
решение2
Автор OP попросил меня дать небольшое пояснение к этому ответу, поэтому я добавлю немного текста здесь. Стандартный механизм LaTeX для необязательных аргументов допускает один необязательный аргумент, который предшествует обязательным аргументам. Таким образом, для создания синтаксиса, который предоставляет необязательный аргумент, 2 обязательных аргумента, а затем 2 необязательных аргумента, требуется последовательно связать 3 макроса, поскольку запрошено 3 необязательных аргумента.
Первый макрос принимает необязательный и 2 обязательных аргумента, а затем он должен вызвать второй макрос, и вот ключ,как его последнее действие! Причина, по которой вызов 2-го макроса должен быть последним действием первого макроса, заключается в том, что 2-й макрос должен поглотить необязательный аргумент. Если в первом макросе есть какие-либо токены, которые следуют за вызовом 2-го макроса в цепочке, то эти другие токены в 1-м макросе будут поглощены как аргумент, а не то, что предполагалось.
Аналогично, 2-й макрос должен вызвать 3-й макрос в качестве своего конечного действия.
Некоторые необычные моменты:
если последующий макрос должен быть вызван внутри блока
\if
, он должен быть\expandafter
вызван до последующего макроса, чтобы последующий макрос не пытался поглотить\else
или\fi
.В этом конкретном случае последний необязательный аргумент, метка, может быть вызван только в том случае, если указан заголовок. Таким образом, 2-й макрос в цепочке вызовет 3-й макрос только в том случае, если указан заголовок. В противном случае он обрежет последовательность.
МВЭ:
\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}
А-шу-элли, чем больше я об этом думаю, тем больше понимаю, что токены даже не нужны:
\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}
решение3
Вот как вы можете достичь своей цели, используяxparse
:
\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}
Необязательные аргументы со значением по умолчанию указываются с помощью , O{<default>}
а необязательные аргументы без значения по умолчанию используют o
. Условие того, предоставлено ли значение, выполняется с помощью \IfValueTF{<parameter>}{<true>}{<false>}
. Существуют также единичные условные операторы \IfValueT
и \IfValueF
, первый из которых использовался выше.
Приведенный выше код предполагает, что пустой заголовок (пустой четвертый аргумент) не нуждается в \label
(пятом) аргументе. Если это необходимо, переместите \IfValueT{#5}{\label{#5}}
из <true>
ветки внутрь \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}
}