情况是,我正在开发自己的命令和环境,这些命令和环境基于另一个包提供的命令和环境:为了方便讨论,我们称之为其他包裹这第一个模块。 这第一个模块为我提供了一个可以使用键值设置参数的环境:
\begin{<first-module-env>}[<key-values>]
.... various content .....
\end{<first-module-env>}
我希望在此环境的基础上进一步补充早期软件包允许的键值范围。
如果第一个模块为我提供了一个直接处理密钥的命令,那么事情就会相当简单。例如,如果我得到类似这样的命令,
\firstmodulekeysetter{<key-values>}
然后我可以构建类似的东西
\keys_define:nn { acellett/augmentation } { ..... }
\NewDocumentEnvironment{acellett}{ O{} }
{ \keys_set_known:nnN { acellett/augmentation } { #1 } \l_tmpa_clist
\exp_args:NV \firstmodulekeysetter \l_tmpa_clist
.... }
{ .... }
但第一个模块可能不太方便用户使用。它可能只允许我通过环境的可选参数来访问密钥。
下面是一个示例,显示了我如何处理增强允许的键值第一个模块。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
%----------------------------------------------------------------------
%% module "first_module"
\tl_new:N \l_first_module_a_tl
\tl_new:N \l_first_module_b_tl
\keys_define:nn { first/module/set }
{
a .code:n = { \tl_set:Nn \l_first_module_a_tl { #1 } },
b .code:n = { \tl_set:Nn \l_first_module_b_tl { #1 } },
}
\NewDocumentEnvironment{firstenv}{ O{} }
{
\par
\keys_set:nn { first/module/set } { #1 }
\begin{tabular}{rl}
a & \l_first_module_a_tl \\
b & \l_first_module_b_tl \\
}
{
\end{tabular}\par
}
%----------------------------------------------------------------------
%% module "augmented_module"
\tl_new:N \l_ae_augmented_module_x_tl
\tl_new:N \l_ae_augmented_module_y_tl
\keys_define:nn { ae/augmented/module/set }
{
x .code:n = { \tl_set:Nn \l_ae_augmented_module_x_tl { #1 } },
y .code:n = { \tl_set:Nn \l_ae_augmented_module_y_tl { #1 } },
}
\cs_new:Npn \__ae_augmented_calling_first:n #1
{
\begin{firstenv}[#1]
}
\NewDocumentEnvironment{augmentedenv}{ O{} }
{
\keys_set_known:nnN { ae/augmented/module/set }{ #1 } \l_tmpa_clist
\exp_args:NV \__ae_augmented_calling_first:n \l_tmpa_clist
x & \l_ae_augmented_module_x_tl \\
y & \l_ae_augmented_module_y_tl \\
}
{
\end{firstenv}
}
\ExplSyntaxOff
\pagestyle{empty}
\begin{document}
\textbf{First Environment}
\begin{firstenv}[a={A},b={is for Apple}]
\end{firstenv}
\textbf{Augmented Environment}
\begin{augmentedenv}[a={B},b={is for Banana},x={X},y={is for Xylophone }]
\end{augmentedenv}
\end{document}
之前提到过\exp_args
不鼓励使用。有没有更好的方法?我是否需要创建函数\__ae_augmented_calling_first
来允许我传递\l_tmpa_clist
?
答案1
我想说这是扩充选项集的正确方法,甚至可以改变已经存在的键的行为(不是在示例中,但我想你明白了)。
我对代码做了一些修改,使用了正确定义键的方式,这.code:n
应该是最后的手段。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
%----------------------------------------------------------------------
%% module "first_module"
\keys_define:nn { first/module/set }
{
a .tl_set:N = \l_first_module_a_tl,
b .tl_set:N = \l_first_module_b_tl,
}
\NewDocumentEnvironment{firstenv}{ O{} }
{
\par
\keys_set:nn { first/module/set } { #1 }
\begin{tabular}{rl}
a & \l_first_module_a_tl \\
b & \l_first_module_b_tl \\
}
{
\end{tabular}\par
}
%----------------------------------------------------------------------
%% module "augmented_module"
\clist_new:N \l_ae_augmented_options_clist
\keys_define:nn { ae/augmented/module/set }
{
x .tl_set:N = \l_ae_augmented_module_x_tl,
y .tl_set:N = \l_ae_augmented_module_y_tl,
}
\cs_new:Npn \__ae_augmented_calling_first:n #1
{
\firstenv[#1]
}
\cs_generate_variant:Nn \__ae_augmented_calling_first:n { V }
\NewDocumentEnvironment{augmentedenv}{ O{} }
{
\keys_set_known:nnN { ae/augmented/module/set }{ #1 } \l_ae_augmented_options_clist
\__ae_augmented_calling_first:V \l_ae_augmented_options_clist
x & \l_ae_augmented_module_x_tl \\
y & \l_ae_augmented_module_y_tl \\
}
{
\endfirstenv
}
\ExplSyntaxOff
\pagestyle{empty}
\begin{document}
\textbf{First Environment}
\begin{firstenv}[a={A},b={is for Apple}]
\end{firstenv}
\textbf{Augmented Environment}
\begin{augmentedenv}[a={B},b={is for Banana},x={X},y={is for Xylophone }]
\end{augmentedenv}
\end{document}
请注意,尽管结果完全相同,但\__ae_augmented_calling_first:V
最好使用变体定义:函数名称更清楚地表达了预期参数的性质。\exp_args:NV
使用\firstenv
并\endfirstenv
避免了新级别的分组(如果augmentedenv
没有正确关闭,则会有更好的错误消息。