\makeatletter
\NewDocumentCommand\ztset{o}
{
\newtcbtheorem{zljtest}{name}
{
zljTheoStyle,
\setkeys{zt}{#1}
}
{zljtest}
}
\define@key{zt}{color}[red]{
colbacktitle=#1
}
\makeatother
\ztset[color=blue]
\ExplSyntaxOff
\begin{zljtest}{}{}
测试基
\end{zljtest}
我想要实现的功能是在newtcbtheorem新建定理时,可以指定颜色标题等一些列不同的值,而相同部分比如定理形状不必反复设置,看了keyval的文档,尝试按照那个唯一的例子写了上面的代码,但是编译通不过,是不是我对keyval的理解有问题,l3里面的prop的用法是不是基于keyval的?还是另起炉灶的?prop接口正在看,但是英文的看起来很费劲,请教一下高手
编译不成功的原因是
\newtcbtheorem
不会展开其参数;\setkeys
以及几乎所有的键设置命令(\keys_set:nn
、\pgfkeys
)都是不可扩展的。(也有一部分命令是可扩展的,如 \keyval_parse:nnn
、expkv
宏包的部分命令。)首先要说明的是,LaTeX3 不依赖任何其它宏包,甚至都不需要是 LaTeX。以及 l3keys
也不依赖 l3prop
,这二者是独立的。键值设置一般使用 l3keys
,l3prop
使用得较少。
要想成功编译,首先必须解析传入的键值,然后将其传给 \newtcbtheorem
。
可用的方法有很多,但是既然使用了 tcolorbox
,就使用 pgfkeys
来实现吧。
首先定义几个辅助命令与句柄(handler):
\makeatletter
\ExplSyntaxOn
\cs_new_nopar:Npn \zt@appto@clist #1#2 { \clist_put_right:Nn #2 {#1} }
\cs_new_nopar:Npn \zt@preto@clist #1#2 { \clist_put_left:Nn #2 {#1} }
\ExplSyntaxOff
\pgfkeys{
% {<prefix list>} {<clist>},把 <prefix list> 放到 <clist> 之前,<clist> 是一个 list 宏
/handlers/.prefix to clist/.code 2 args=%
\pgfkeysdef{\pgfkeyscurrentpath}{\zt@preto@clist{#1}{#2}},
% {<append list>} {<clist>}
/handlers/.append to clist/.code 2 args=%
\pgfkeysdef{\pgfkeyscurrentpath}{\zt@appto@clist{#1}{#2}},
}
\tcbset{
zljTheoStyle/.style={}, % 你自己的代码
}
% 这个命令类似于 \tikzset、\tcbset,它的形式是 \ztpgfset{<module>}{<key-val>}
\def\ztpgfset#1{\pgfqkeys{zt/#1}}
\NewDocumentCommand\ztset{O{}}
{
\def\zt@tmplist{}% 这个命令用于保存解析的键值
\ztpgfset{tcb}{#1} % 这个命令用于解析传入的键值参数,使用 tcb 模块
\def\zt@tmp{\newtcbtheorem{zljtest}{name}}
\expandafter\zt@tmp\expandafter{\zt@tmplist,zljTheoStyle,}{zljtest} % 必须展开解析得到的键值
}
现在就可以定义自己的键了,把它们放到 tcb 模块:
\ztpgfset{tcb}{
color/.append to clist={colbacktitle={#1}}{\zt@tmplist},% 把 "colbacktitle={#1}" 放到 \zt@tmplist 之后,效果和 "color/.code=\zt@appto@clist{#1}{\zt@tmplist}" 一样
color/.default=red,% 默认值为 red
cf/.append to clist={colframe=#1}{\zt@tmplist},% 把 "colframe=#1" 放到 \zt@tmplist 之后
cf/.default=yellow!80!black,
}
\makeatother
一个完整的例子:
\documentclass{ctexart}
\usepackage[most]{tcolorbox}
\makeatletter
\ExplSyntaxOn
\cs_new_nopar:Npn \zt@appto@clist #1#2 { \clist_put_right:Nn #2 {#1} }
\cs_new_nopar:Npn \zt@preto@clist #1#2 { \clist_put_left:Nn #2 {#1} }
\ExplSyntaxOff
\pgfkeys{
/handlers/.prefix to clist/.code 2 args=%
\pgfkeysdef{\pgfkeyscurrentpath}{\zt@preto@clist{#1}{#2}},
/handlers/.append to clist/.code 2 args=%
\pgfkeysdef{\pgfkeyscurrentpath}{\zt@appto@clist{#1}{#2}},
}
\tcbset{
zljTheoStyle/.style={}, % 你自己的代码
}
\def\ztpgfset#1{\pgfqkeys{zt/#1}}
\NewDocumentCommand\ztset{O{}}
{
\def\zt@tmplist{}% 这个命令用于保存解析的键值
\ztpgfset{tcb}{#1} % 这个命令用于解析传入的键值参数,使用 tcb 模块
\def\zt@tmp{\newtcbtheorem{zljtest}{name}}
\expandafter\zt@tmp\expandafter{\zt@tmplist,zljTheoStyle,}{zljtest}
}
\ztpgfset{tcb}{
color/.append to clist={colbacktitle={#1}}{\zt@tmplist},% 把 "colbacktitle={#1}" 放到 \zt@tmplist 之后
color/.default=red,% 默认值为 red
cf/.append to clist={colframe=#1}{\zt@tmplist},% 把 "colframe=#1" 放到 \zt@tmplist 之后
cf/.default=yellow!80!black,
}
\makeatother
\begin{document}
\ztset[color=blue,cf]
\begin{zljtest}{}{}
测试基
\end{zljtest}
\end{document}
非常感谢,pgfkeys我没学过,我慢慢消化