该pgfkeys
软件包具有 /.code
处理程序,允许定义用户设置键时要执行的代码,就像它执行了以 作为#1
值的宏一样。/.code args
处理程序允许以 -style 提供实际参数列表,\def
以便可以定义花哨的键,例如rectangle/.code args={#1 by #2}{...}
可以设置为rectangle=13 by 12
。
我的问题是:是否有一些包可以xparse
与之集成pgfkeys
以便使用xparse
类似语法(例如{m o m}
)来定义键的参数?
例子:
\pgfkeys{my key/.xparse code={o m}{\def\mykey{Required: #2, Optional: #1}}}
\pgfkeys{my key = [Hello]{John}} % prints 'Required: John, Optional: Hello'
答案1
除了定义自己的 DocumentCommand 并手动将所有内容从 PGFkeys 转发到那里之外,还可以说
\NewDocumentCommand\myKey{o m}{<stuff>}
\pgfkeys{my key/.code=\myKey#1}
我们可以使用执行相同操作的处理程序来完成此操作。
my key/.xparse code = {o m}{<stuff>}
可以与
my key = [opt]{mand}
并且它会正常工作:
\myKey[opt]{mand}
但是,当不带可选参数使用时,例如
my key = mand
% or
my key = {mand}
PGFkeys 将丢失一些括号,并且调用\myKey
将是
\myKey mand
它只会抓住m
并#2
离开and
。
我们需要my key = {{{{mand}}}}
。
PGFkeys 的工作方式与\newcommand
s 或\NewDocumentCommand
s 有很大不同:每个 key-macro 都是一个分隔宏,其参数和带有\pgfeov
。在内部,所有 key-macro 都会附加此参数。
不幸的是,xparse
不提供相同的接口,它只知道
t
→ 可选标记(将切换布尔值)和u
→ 强制性论点你直到遇到指定的标记。
我选择了后者。这意味着,每一个
key/.xparse code={<args>}{<code>}
实际上将用参数来定义<args> u\pgfeov
。
这使得 PGFkeys 的使用非常方便,xparse
但有一个注意事项:用户始终必须输入最后一个参数才不是指定。
这不是很好,但我还是要重申一下我的建议xparse
:保持简单(释义)。不要在最后添加任何花哨的论点。
在您的情况下,您只需使用o
,因为最后的强制性参数是强制性的。
\pgfkeys{my key/.xparse code={o}{Required: #2, Optional: #1}}
几点说明:
如果你需要
.append xparse code
并且类似的东西需要做更多的工作,不过我有一些想法。我在下面的代码中明确展示了几乎唯一的坏情况,不要灰心。
我正在使用,
\DeclareDocumentCommand
因为这只会覆盖宏(就像 PGFkeys 所做的那样.code
),即使xparse
手册建议不要这样做:应谨慎使用此方法。
代码
\documentclass{article}
\usepackage{pgfkeys,xparse,tabularx}
\pgfqkeys{/handlers}{
.xparse code/.code 2 args={%
\expandafter\DeclareDocumentCommand
\csname pgfk@\pgfkeyscurrentpath/.@cmd\endcsname
{#1u\pgfeov}{#2}%
% probably useless unless .xparse append code is needed
%\pgfkeyssetvalue{\pgfkeyscurrentpath/.@args}{#1u\pgfeov}%
%\pgfkeyssetvalue{\pgfkeyscurrentpath/.@body}{#2}%
},
.xparse style/.code 2 args=%
\pgfkeysalso{\pgfkeyscurrentpath/.xparse code={#1}{\pgfkeysalso{#2}}},
}
\newcommand*\doKey[2]{\texttt{\detokenize{#1}} & \pgfkeys{#1}
\ifx\\#2\\\else\par\def\tt##1 {\texttt{##1} }\sffamily$\to$ #2\fi\\}
\parindent=0pt
\begin{document}
\pgfkeys{my key1/.xparse code = { o }{Required1: #2, Optional1: #1}}
\pgfkeys{my key2/.xparse code = { o }{Required2: #2, Optional2: #1}}
\pgfkeys{my style/.xparse style = { o o }%
{my key1 = [1]{#1}, /utils/exec=\par, my key2 = {#2}}}
\begin{tabularx}{\linewidth}{l X}
\doKey{my key1 = [Hello]{John}}{}
\doKey{my key2 = John2 }{}
\doKey{my style = [Foo]Bar }{\tt Bar is lost (and no error message)}
\end{tabularx}
\vspace{1ex}% without the #4
\pgfkeys{omo/.xparse code={omo}{Opt1: #1, Req2: #2, Opt2: #3}}
\begin{tabularx}{\linewidth}{l X}
\doKey{omo = [opt1]{Foo}[opt3]}{}
\doKey{omo = [opt1]{FooBar} }{}
\doKey{omo = {FooBar} }{\tt ooBar is lost}
\doKey{omo = {Foo}Bar }{\tt Bar is lost}
\end{tabularx}
\vspace{1ex}% as above but with #4 after the #2
\pgfkeys{omo/.xparse code={O{--}mO{--}}{Opt1: #1, Req2: #2#4, Opt2: #3}}
\begin{tabularx}{\linewidth}{l X}
\doKey{omo = [opt1]{Foo}[opt3]}{}
\doKey{omo = [opt1]{FooBar} }{}
\doKey{omo = {FooBar} }{ooBar is lost}
\doKey{omo = {Foo}Bar }{Bar is caught}
\end{tabularx}
\end{document}