我想定義一個有兩個參數的宏,其中一個參數是可選的。如果沒有給出,則應採用另一個作為預設值。
很遺憾,
\newcommand{\mycommand}[2][#1]{ ... }
不起作用,也不起作用
\newcommand{\mycommand}[2][#2]{ ... }
有人知道怎麼做這個嗎?
答案1
好消息:您可以透過以下方式輕鬆完成xparse
:
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\foo}{O{#2}m}{%
Optional=``#1'', mandatory=``#2''\par
}
\NewDocumentCommand{\oof}{mO{#1}}{%
Mandatory=``#1'', optional=``#2''\par
}
\begin{document}
\foo{x}
\foo[y]{x}
\oof{x}
\oof{x}[y]
\end{document}
O{...}
當參數本身在呼叫時未出現時,參數說明符將替換預設值作為參數。這很可能是引用另一個參數的參數標記。
答案2
您可以使用xparse
輕鬆判斷可選參數是否存在,並向另一個(輔助)函數提供適當的組合。這是一個例子:
\documentclass{article}
\usepackage{xparse}
\newcommand{\printthis}[2]{%
Optional: #1; Mandatory: #2%
}
\NewDocumentCommand{\mycommand}{o m}{%
\IfValueTF{#1}
{\printthis{#1}{#2}}% \mycommand[..]{...}
{\printthis{#2}{#2}}% \mycommand{...}
}
\begin{document}
\mycommand{first}
\mycommand[first]{second}
\end{document}
一個稍微不同的版本源自於使用\caption
,您可以在其中為LoT/LoF 提供可選參數,但如果不這樣做,則會發送強制參數(對於帶有可選參數的、用於ToC 的分段單元也類似) )。這使用了核心的\@dblarg
:
\documentclass{article}
\newcommand{\printthis}[2][]{%
Optional: #1; Mandatory: #2%
}
\makeatletter
\newcommand{\mycommand}{%
\@dblarg\printthis
}
\makeatother
\begin{document}
\mycommand{first}
\mycommand[first]{second}
\end{document}
答案3
這是與處理可選參數的其他巨集一樣添加保護的嘗試:
%%\errorcontextlines=1000
\documentclass[a4paper]{article}
\makeatletter
\newcommand\makefirstmandatorytheoptional[1]{%
\expandafter\innermakefirstmandatorytheoptional
\expandafter{\csname\string#1\endcsname}{#1}%
}%
\newcommand\innermakefirstmandatorytheoptional[2]{%
\def#2{%
\ifx\protect\@typeset@protect
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\kernel@ifnextchar[{#1}{\@dblarg{#1}}}%
{\protect#2}%
}%
}%
\newcommand\mycommand[2][dummyoptional]{%
This is taken for the optional argument: #1.\\
This is taken for the mandatory argument: #2.
}%
\makefirstmandatorytheoptional{\mycommand}%
\makeatother
\parindent=0ex
\parskip=\medskipamount
\begin{document}
No optional argument given---\verb|\mycommand{A}|:
\mycommand{A}
Optional argument "B" given---\verb|\mycommand[B]{A}|:
\mycommand[B]{A}
\end{document}