我想创建一个新命令\add
接受 2 个参数的新命令,称为实体和标题。换句话说,命令应如下所示:\add{entity}{title}
。输出应具有以下形式:\textit{entity} '{title}'
。
例如,如果我输入\add{article}{LaTeX}
结果应该是文章'乳胶'。
我怎样才能做到这一点?
答案1
答案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