我正在记录一个具有某些动态创建的关键路径的包(通过某些命令或通过 pgfkeys 处理程序动态创建.unknown
)。
我想用docKey
tcolorbox 的环境记录这些键,但第一个参数(可选和强制)不适用于诸如 之类的宏\meta{}
。
有没有正确的方法可以做到这一点?
梅威瑟:
\documentclass{article}
\usepackage{tcolorbox}
\tcbuselibrary{documentation}
\begin{document}
\begin{docKey}
[mypackage/keypath]
{my key}
{=value}
{}
The \texttt{keypath} part of the key path is dynamic. Using \meta{keypath} breaks.
Putting both in the mandatory argument as \verb|{\meta{keypath}/my key}| also breaks.
What is the best alternative?
\end{docKey}
\end{document}
答案1
tcolorbox
假设环境的第一个可选参数的值docKey
(也是 key 的值/tcb/doc keypath
)是完全可扩展的,并在打印、标签名称和索引名称中使用它。由于\meta{...}
不完全可扩展,因此会引发错误。
在下面的例子中,我将角色拆分doc keypath
成四个:
- 打印按键名称
- 标签名称,可以通过
doc keypath label
- 打印索引名称,可以通过设置
doc keypath index
- 排序的索引名称,可以通过 设置
doc keypath sort index
。
修改doc keypath
后将设置所有这四个,而新键doc formatted keypath
将设置第一个和第三个。
用法:
\begin{docKey}
[keypath][doc formatted keypath=\meta{keypath}]
{my key}
{=value}
{}
\end{docKey}
See \refKey{/keypath/my key}.
完整示例:
\documentclass{article}
\usepackage{tcolorbox}
\tcbuselibrary{documentation}
\makeindex
\makeatletter
\newif\iftcb@doc@formatted@keypath
\tcbset{
doc keypath/.style={%
doc@keypath={#1},
doc keypath label={#1},
doc keypath index={#1},doc keypath sort index={#1},
},
doc@keypath/.store in=\kvtcb@doc@keypath,
doc formatted keypath/.code=%
\tcb@doc@formatted@keypathtrue
\pgfkeysalso{doc@keypath=#1,doc keypath index=#1},
% doc keypath name/.store in=\kvtcb@doc@keypath,
doc keypath label/.store in=\kvtcb@doc@keypath@label,
doc keypath index/.store in=\kvtcb@doc@keypath@index,
doc keypath sort index/.store in=\kvtcb@doc@keypath@sortindex,
}
\ExplSyntaxOn
\cs_set_nopar:Npn \__tcobox_print_key:
{
\textcolor{\kvtcb@col@key}{\tcb@doc@bfseries\ttfamily
\tl_if_empty:NF \kvtcb@doc@keypath
{
\iftcb@doc@formatted@keypath
/\kvtcb@doc@keypath/
\else
/\__tcobox_sanitize_tl:V\kvtcb@doc@keypath/
\fi
}
\__tcobox_sanitize_tl:V\kvtcb@doc@name}
}
\cs_set_nopar:Npn \__tcobox_index_key:
{
\iftcb@doc@toindex
\kvtcb@index@command{\kvtcb@doc@sortindex\idx@actual\tcbIndexPrintKeyCA{\kvtcb@doc@index}}
\tl_if_empty:NTF \kvtcb@doc@keypath@index
{
\kvtcb@index@command{\kvtcb@text@keys\idx@level\kvtcb@doc@sortindex\idx@actual\tcbIndexPrintKeyC{\kvtcb@doc@index}}
}
{
\kvtcb@index@command{\kvtcb@text@keys\idx@level\kvtcb@doc@keypath@sortindex\idx@actual\tcbIndexPrintKeyC{/\kvtcb@doc@keypath@index/}
\idx@level\kvtcb@doc@sortindex\idx@actual\tcbIndexPrintKeyC{\kvtcb@doc@index}}
}
\fi
}
\cs_set:Npn \__tcobox_doc_head_key:
{
\__tcobox_print_key:
\__tcobox_index_key:
\tl_if_empty:NTF \kvtcb@doc@keypath@label
{
\seq_if_in:NVF \g__tcobox_label_seq \kvtcb@doc@label
{
\protected@edef\@currentlabel{\kvtcb@doc@name}
\label{key:\kvtcb@doc@label}
\seq_gput_left:NV \g__tcobox_label_seq \kvtcb@doc@label
}
}
{
\tl_set:Nx \l_tmpa_tl {/\kvtcb@doc@keypath@label/\kvtcb@doc@label}
\seq_if_in:NVF \g__tcobox_label_seq \l_tmpa_tl
{
\protected@edef\@currentlabel{/\kvtcb@doc@keypath/\kvtcb@doc@name}
\label{key:/\kvtcb@doc@keypath@label/\kvtcb@doc@label}
\seq_gput_left:NV \g__tcobox_label_seq \l_tmpa_tl
}
}
{\ttfamily\kvtcb@doc@parameter}
\tcb@doc@do@description
}
\ExplSyntaxOff
\makeatother
\begin{document}
\begin{docKey}
[keypath][doc formatted keypath=\meta{keypath}]
{my key}
{=value}
{}
The \texttt{keypath} part of the key path is dynamic. Using \meta{keypath} breaks.
Putting both in the mandatory argument as \verb|{\meta{keypath}/my key}| also breaks.
What is the best alternative?
\end{docKey}
See \refKey{/keypath/my key}.
\printindex
\end{document}
答案2
感谢@Marijn 和@mushimushiZ 的详细回答!我正在研究它们,以寻找思路和技巧。
至于这个特定问题,事实证明,可以使用 tcolorbox 本身提供的选项来解决,通过doc label
键,如果宏保留在键本身中(而不是在可选路径参数中):
\documentclass{article}
\usepackage{tcolorbox}
\tcbuselibrary{documentation}
\makeindex
\begin{document}
\begin{docKey}
[mypackage]
[doc label=keypath/mykey]
{\meta{keypath}/my key}
{=value}
{}
The \texttt{keypath} part of the key path is dynamic and corresponds to ...
\end{docKey}
Can be referenced: \refKey{/mypackage/keypath/mykey}
\printindex
\end{document}
答案3
问题在于,可选参数和强制参数都用于创建用于引用的标签\refKey
,即\refKey{/mypackage/keypath/my key}
。标签值中\meta
不允许使用诸如这样的命令。
您可以稍微修改 的定义docKey
以规避此问题,方法是将标签定义为名称,不带可选前缀。一种方法是从源复制定义tcolorbox
并使用\RenewDocumentEnvironment
它进行更改。
梅威瑟:
\documentclass{article}
\usepackage{tcolorbox}
\tcbuselibrary{documentation}
\makeatletter
\RenewDocumentEnvironment{docKey}{ O{} +O{} m m +m }{\tcbset{#2,doc description={#5}}%
\begin{tcb@manual@entry}%
\begin{tcb@doc@head}{doc@head@key}%
\ifblank{#1}{%
\tcb@Print@Key{#3}\tcb@index@Key{#3}\protected@edef\@currentlabel{#3}\label{key:#3}{\ttfamily #4}%
}{%
\tcb@Print@Key{/#1/#3}%
% CHANGE OF LABEL IN FOLLOWING LINE %
\tcb@index@KeyPath{#1}{#3}\protected@edef\@currentlabel{/#1/#3}\label{key:#3}{\ttfamily #4}%
}%
\tcb@doc@do@description%
\end{tcb@doc@head}\nobreak\tcbset{before upper=}\kvtcb@doc@body@key@before\ignorespaces}%
{\ifvmode\else\unskip\fi\kvtcb@doc@body@key@after\end{tcb@manual@entry}}
\makeatother
\begin{document}
\begin{docKey}
[mypackage/\meta{keypath}]
{my key}
{=value}
{}
The \texttt{keypath} part of the key path is dynamic. Using \meta{keypath} breaks.
Putting both in the mandatory argument as \verb|{\meta{keypath}/my key}| also breaks.
What is the best alternative?
\end{docKey}
See \refKey{my key}.
\end{document}
结果:
备注:可能\textit{<keypath>}
比以下更好\meta{keypath}
: