如何创建具有多个参数的新命令?

如何创建具有多个参数的新命令?

我想创建一个新命令\add接受 2 个参数的新命令,称为实体标题。换句话说,命令应如下所示:\add{entity}{title}。输出应具有以下形式:\textit{entity} '{title}'

例如,如果我输入\add{article}{LaTeX}结果应该是文章'乳胶'。

我怎样才能做到这一点?

答案1

\newcommand{\add}[2]{\textit{#1} {`#2'}}

有关此内容的更多阅读材料,请参阅

答案2

我将建议一种非常不同的方法,这种方法在这种特定情况下可能看起来有点过头,但从长远来看是有益的。

我建议使用钥匙来完成你想要做的事情。

因此,我将按如下方式设置密钥:

\documentclass{article}
\usepackage{pgfkeys}
\makeatletter
\pgfkeys{/jeroen/entities/.cd,
  title/.initial=,
  entity/.initial=,
  }
\def\jeroen@set@keys#1{%%
  \pgfkeys{/jeroen/entities/.cd,#1}}
\def\jeroen@get#1{%%
  \pgfkeysvalueof{/jeroen/entities/#1}}

\newcommand\Add[1]{%%
  \bgroup
  \jeroen@set@keys{#1}%%
  \textit{\jeroen@get{entity}} `\jeroen@get{title}'%%
  \egroup}

\makeatother

\begin{document}

\Add{title=\LaTeX,entity=article}

\end{document}

从短期来看,这看似简单的命令需要大量的开销。但从长期来看,这会带来回报。

根据我的经验,我发现有些情况下我想使用基本相同的底层宏,但重写宏可能很麻烦。例如,我可能想使用宏而不调用它的一个参数;我可能想添加第三个参数甚至一个可选参数。使用键值,以后修改代码或改进实现会容易得多。

键值还解决了记住哪个参数对应哪个内容的问题。

通过使用\bgroup\egroup,您可以更轻松地定义未调用某个键时的默认行为。例如,

\documentclass{article}
\usepackage{pgfkeys}
\makeatletter
\pgfkeys{/jeroen/entities/.cd,
  title/.initial=,
  entity/.initial=article,
  }
\def\jeroen@set@keys#1{%%
  \pgfkeys{/jeroen/entities/.cd,#1}}
\def\jeroen@get#1{%%
  \pgfkeysvalueof{/jeroen/entities/#1}}
\newcommand\Add[1]{%%
  \bgroup
  \jeroen@set@keys{#1}%%
  \textit{\jeroen@get{entity}} `\jeroen@get{title}'%%
  \egroup}
\makeatother

\begin{document}

\Add{title=\LaTeX,entity=article}

\Add{title=long nosed creature,entity=elephant}

\Add{title=mathematics}

\end{document}

在此处输入图片描述

答案3

一个有趣的例子,说明如何用不同的语法定义命令,但以最少的努力做同样的事情。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

% Define the keys
\keys_define:nn { jeroen/add }
 {
  title  .tl_set:N  = \l_jeroen_add_title_tl,
  title  .initial:n = {},
  entity .tl_set:N  = \l_jeroen_add_entity_tl,
  entity .initial:n = article,
 }

% The key-value interface
\NewDocumentCommand{\Add} { m }
 {
  \group_begin:
  \keys_set:nn { jeroen/add } { #1 }
  \jeroen_add:VV \l_jeroen_add_entity_tl \l_jeroen_add_title_tl
  \group_end:
 }

% The two argument interface
\NewDocumentCommand{\add} { m m }
 {
  \jeroen_add:nn { #1 } { #2 }
 }

% The main command
\cs_new:Nn \jeroen_add:nn
 {
  \textit{#1}\nobreakspace`#2'
 }

% The variant needed for the key-value interface
\cs_generate_variant:Nn \jeroen_add:nn { VV }
\ExplSyntaxOff

\begin{document}

Key-value syntax:

\Add{title=\LaTeX,entity=article}

\Add{title=long nosed creature,entity=elephant}

\Add{title=mathematics}

\medskip

Two argument syntax:

\add{article}{\LaTeX}

\add{elephant}{long nosed creature}

\add{article}{mathematics}

\end{document}

在此处输入图片描述

\jeroen_add:nn和之间的区别\jeroen_add:VV在于,前者需要两个标准的带括号参数,而后者使用作为参数传递的两个变量的值(无括号)。在这种情况下,这并不是必需的,因为

\jeroen_add:nn { \l_jeroen_add_entity_tl } { \l_jeroen_add_title_tl }

效果是一样的。在其他情况下,创建变体可以解决许多微妙的问题。从概念上讲,它也更好。

答案4

xparse有时可以利用其功能挽救生命。以下是一个例子:

\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\Add}{mm}{\textit{#1}{} `#2'}
\begin{document}
 \Add{article}{\LaTeX}
\end{document}

在此处输入图片描述

欲了解详情texdoc xparse或访问texdoc.net

相关内容