Documentação tcolorbox: documentando caminhos-chave dinâmicos
Estou documentando um pacote que possui certos caminhos-chave que são criados dinamicamente (por algum comando ou em tempo real por meio do .unknownmanipulador pgfkeys ).
Quero documentar essas chaves com o docKeyambiente de tcolorbox, mas os primeiros argumentos (tanto os opcionais quanto os obrigatórios) não funcionam com macros como \meta{}.
Existe uma maneira adequada de fazer isso?
MWE:
\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}
Respostas
tcolorboxassume que o valor do primeiro argumento opcional do docKeyambiente (também o valor da chave /tcb/doc keypath) é totalmente expansível e o usa na impressão, nome do rótulo e nome do índice. Como \meta{...}não é totalmente expansível, são gerados erros.
No exemplo a seguir, divido a função de doc keypathem quatro:
- nome da chave impressa
- nome do rótulo, pode ser definido por
doc keypath label - nome do índice impresso, pode ser definido por
doc keypath index - nome do índice classificado, pode ser definido por
doc keypath sort index.
Modificado doc keypathirá definir todos os quatro, e uma nova chave doc formatted keypathdefine o primeiro e o terceiro.
Uso:
\begin{docKey}
[keypath][doc formatted keypath=\meta{keypath}]
{my key}
{=value}
{}
\end{docKey}
See \refKey{/keypath/my key}.
Exemplo completo:
\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}
Obrigado pelas respostas detalhadas, @Marijn & @mushimushiZ! Estou estudando-os por ideias e técnicas.
Quanto a este problema específico, verifica-se que é possível fazer com as opções fornecidas pelo próprio tcolorbox, por meio da doc labelchave, se as macros forem mantidas na própria chave (e não no argumento caminho opcional):
\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}
O problema é que tanto o argumento opcional quanto o obrigatório são usados para criar um rótulo para referência \refKey, ou seja \refKey{/mypackage/keypath/my key},. No valor de um rótulo, comandos como \metanão são permitidos.
Você pode modificar a definição de docKeyligeiramente para contornar o problema, definindo o rótulo para ser apenas o nome sem o prefixo opcional. Uma maneira de fazer isso é copiar a definição da tcolorboxfonte e usar \RenewDocumentEnvironmentpara fazer as alterações.
MWE:
\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}
Resultado:
Observação: talvez \textit{<keypath>}seja melhor do que \meta{keypath}: