keyval使用的不太理解

发布于 2021-11-27 18:49:10
\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接口正在看,但是英文的看起来很费劲,请教一下高手

查看更多

关注者
0
被浏览
1.5k
雾月
雾月 2021-11-28
这家伙很懒,什么也没写!

编译不成功的原因是

  1. \newtcbtheorem 不会展开其参数;
  2. \setkeys 以及几乎所有的键设置命令(\keys_set:nn\pgfkeys)都是不可扩展的。(也有一部分命令是可扩展的,如 \keyval_parse:nnnexpkv 宏包的部分命令。)

首先要说明的是,LaTeX3 不依赖任何其它宏包,甚至都不需要是 LaTeX。以及 l3keys 也不依赖 l3prop,这二者是独立的。键值设置一般使用 l3keysl3prop 使用得较少。

要想成功编译,首先必须解析传入的键值,然后将其传给 \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}

image.png

1 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览