如何定義具有多個可選參數的巨集?

如何定義具有多個可選參數的巨集?

在我有了一個可以工作的巨集之後,我嘗試透過將一些參數設為可選來改進它。不幸的是,該巨集不再起作用。相反,我收到了我不理解的錯誤,例如:

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-trees 中。

如果您希望提供處理影像的範例,您可以使用現代 LaTeX 系統為您提供的即用型影像:

例如,Martin Scharrer 的文檔MWE包列出由於該包而可用的所有圖像。使用當前的 TeX 平台和當前版本的MWE 包,圖像無需加載包即可使用,因為它們已整合到 texmf 樹和文件名資料庫中。

順便說一下2:

通常情況下,您可以縮排 TeX 原始程式碼行以提高可讀性。 ;-) 這是因為當(La)TeX開始讀取一行輸入時,讀取設備的狀態處於狀態N(換行),而在狀態N個類別代碼10(空格)的字元將不會被標記化為空間代幣,但根本不會產生任何代幣。

順便說一下3:

提供範例是一種很好的做法,人們可以根據這些範例來準確地重現錯誤行為。能夠重現錯誤行為對於能夠調試產生錯誤行為的程式碼非常重要。


尼古拉·塔爾伯特博士的建立一個 LaTeX 最小範例提供了一些指導方針。

還有如何製作“最小範例”來自 texfaq.org,其中還包含一些提問建議的連結。

什麼是最小工作範例?Christian Faulhammer 沒有使用術語“最小示例”,但他使用術語“最小工作示例”,即使對於僅在足以表現出錯誤行為的意義上起作用的示例也是如此。

您可能也對問題的答案感興趣我剛剛被要求寫一個最小的例子,那是什麼?

答案2

OP要求我對此答案進行一些解釋,所以我將在這裡添加一些文字。標準的 LaTeX 可選參數機制允許一個可選參數出現在強制參數之前。因此,要建立提供一個可選參數、2 個強制參數、然後 2 個可選參數的語法,需要將 3 個巨集連續串在一起,因為需要 3 個可選參數。

第一個宏吸收一個可選參數加上 2 個強制參數,然後它必須呼叫第二個宏,這是關鍵,作為其最後的行動! 第二個巨集呼叫必須是第一個巨集的最終操作的原因是第二個巨集必須吸收可選參數。如果第一個宏中有任何標記跟隨鏈中第二個宏的調用,那麼第一個宏中的其他標記將被吸收為參數,而不是預期的參數。

同樣,第二個巨集必須呼叫第三個巨集作為其最終操作。

某些古怪的亮點:

  1. 如果要在區塊內部調用連續宏\if,則必須\expandafter在連續宏之前調用,以便連續宏不會嘗試吸收\else\fi

  2. 在這種特殊情況下,最後一個可選參數(標籤)只有在指定了標題時才可呼叫。因此,如果指定了標題,則鏈中的第二個巨集將只呼叫第三個巨集。否則,它將截斷序列。

氣象局:

\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,我越想越覺得,甚至不需要令牌:

\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>}。還有單數條件句\IfValueTand \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}
}

相關內容