Closed muzimuzhi closed 6 months ago
I have to look into deeper with more time, but this proposal seems reasonable to me.
Here is my proposal v2.
To avoid misuse of /tcb/doclang
keys, it implements the "FIXME" comment in initial proposal,
% FIXME: though this change improves consistency, setting different % "/tcb/doclang/key" for different key groups is still like a misuse. % One idea is to provide \kvtcb@text@key and \kvtcb@text@keys wrappers % configurable by user through new keys. % Then "documentation" lib is even more complex. :)
That is, a pair of new keys /tcb/index key formatter
and /tcb/index keys formatter
(key names inspired by /tcb/description formatter=<macro>
).
It produces the same output as the initial proposal.
```tex \documentclass{article} \usepackage{tcolorbox} \tcbuselibrary{documentation} \hypersetup{colorlinks} \usepackage{regexpatch} \makeindex \makeatletter \tcbset{ doc key prefix/.store in=\kvtcb@doc@keyprefix, doc key prefix={/}, % new formatter keys index key formatter/.code={\let\kvtcb@doc@format@key=#1}, index keys formatter/.code={\let\kvtcb@doc@format@keys=#1}, index key formatter/.default=\@firstofone, index keys formatter/.default=\@firstofone, index key formatter, index keys formatter } \ExplSyntaxOn % replace literal "/" by intenal of "/tcb/doc key prefix" \xpatchcmd \__tcobox_print_key: { / } { \kvtcb@doc@keyprefix } { } {\PatchFailed} \xpatchcmd \__tcobox_index_key: { / } { \kvtcb@doc@keyprefix } { } {\PatchFailed} % apply "/tcb/index key formatter" and "/tcb/index keys formatter" internals \xpatchcmd \__tcobox_index_key: { \tcbIndexPrintKeyCA{\kvtcb@doc@index} } { \tcbIndexPrintKeyCA{\kvtcb@doc@index}{\kvtcb@doc@format@key\kvtcb@text@key} } { } {\PatchFailed} \xpatchcmd* \__tcobox_index_key: { \kvtcb@text@keys } % two occurences { \kvtcb@doc@format@keys\kvtcb@text@keys } { } {\PatchFailed} % redefine \tcbmakedocSubKey(s) to take an optional arg % does its new O-arg need to be long? \RenewDocumentCommand \tcbmakedocSubKey { +O{} m m } { \NewDocumentEnvironment{#2}{ O{} +O{} m m +m } { \__tcobox_doc_entry_begin:nnn { doc@sub@keypath=#3, doc~keypath=##1, doc~name={##3}, doc~parameter={##4}, doc~description={##5}, #1, ##2 } {}{key} } { \__tcobox_doc_entry_end:n { key } } \NewDocumentEnvironment{#2*}{} { \group_begin: \bool_set_false:N \l__tcobox_doc_toindex_bool \begin{#2} } { \end{#2} \group_end: } } \RenewDocumentCommand \tcbmakedocSubKeys { +O{} m m } { \NewDocumentEnvironment{#2}{ +O{} +m } { \__tcobox_doc_entry_begin:nnn { doc@sub@keypath=#3, doc~keypath=, #1, ##1 } {##2}{key} } { \__tcobox_doc_entry_end:n { key } } } %% before % \NewDocumentCommand{\tcbIndexPrintKeyCA}{m} % {\tcb@Index@Print@CA{#1}{\kvtcb@col@key}{\kvtcb@text@key}} %% after \RenewDocumentCommand{\tcbIndexPrintKeyCA}{m} {\tcb@Index@Print@CA{#1}{\kvtcb@col@key}} \ExplSyntaxOff \makeatother % apply new formatter keys \tcbset{ mydoc pgfkeys/.style={ index key formatter=\myFormatPgfkeysIndex, index keys formatter=\myFormatPgfkeysIndex }, mydoc l3keys/.style={ doc key prefix=, index key formatter=\myFormatExplkeysIndex, index keys formatter=\myFormatExplkeysIndex } } % the replacement text of index formatters must be \write-robust \newcommand{\myFormatPgfkeysIndex}[1]{#1 (\textsf{pgfkeys})} \newcommand{\myFormatExplkeysIndex}[1]{#1 (\textsf{l3keys})} \tcbmakedocSubKey[mydoc pgfkeys]{docTcbKey}{tcb} \tcbmakedocSubKey[mydoc l3keys]{docCsvsimKey}{csvsim} \begin{document} \subsection*{Keys based on \textsf{pgfkeys}} \begin{docKey}[tcb][mydoc pgfkeys]{doc keypath}{=\meta{key path}}{no default, initially empty} content \end{docKey} \begin{docTcbKey}{doc name}{=\meta{name}}{no default, initially empty} content \end{docTcbKey} \docAuxKey[tcb][mydoc pgfkeys]{doc parameter} \subsection*{Keys based on \textsf{l3keys}} \begin{docKey}[csvsim][mydoc l3keys]{after line}{=\meta{code}}{no default, initially empty} content \end{docKey} \begin{docCsvsimKey}{late after line}{=\meta{code}}{no default, initially empty} content \end{docCsvsimKey} \docAuxKey[csvsim][mydoc l3keys]{after first line} \printindex \end{document} ```
Just for the record: implemented in https://github.com/T-F-S/tcolorbox/commit/5e113b6745a7290f76b898b01496e27907eaf169 (more literal /
were caught than in my proposal v2) and https://github.com/T-F-S/tcolorbox/commit/e8733ff05eb3a91523db3f596ec39b321ec49f6b.
Currently the full path of a key documented using
docKey(s)
environments or\docAuxKey(*)
commands always starts with a slash/
, which is not always true.pgfkeys
(\pgfkeys
) indeed starts with/
.l3keys
module (\keys_define:nn
and\keys_set:nn
) doesn't start with/
. It's path stored inl_keys_path_str
is just<module>/<key>
, after some sanitisation. This is the case for documentation ofcsvsimple-l3
package.keyval
-based mechanisms (\define@key
and\setkeys
) even don't have the concept of "(full) path", but only "family" and "key". (The internal representation is\KV@<family>@<key>
).Therefore to make
documentation
library able to document keys defined by various key-value mechanisms, the path root of a key needs to be configurable.Below is an attempt which
/tcb/doc path prefix
with initial value/
,\tcbmakedocSubKey
and\tcbmakedocSubKeys
to accept an optional argument<tcb options>
, and/tcb/doclang/key
written to.idx
(instead of privately used in\tcbIndexPrintKeyCA
), just like that of/tcb/doclang/Keys
.It then shows now one can
l3keys
-based keys with empty path root and/tcb/doclang/key
and/tcb/doclang/Keys
(not recommended, just for comparing results in a single document).Full example
```tex % !TeX TS-program = pdflatex -interaction=nonstopmode %.tex | makeindex -o %.ind %.idx | pdflatex -interaction=nonstopmode %.tex \documentclass{article} \usepackage{tcolorbox} \tcbuselibrary{documentation} \hypersetup{colorlinks} \usepackage{xpatch} \makeindex \makeatletter \tcbset{ doc key prefix/.store in=\kvtcb@doc@keyprefix, doc key prefix={/} } \ExplSyntaxOn \xpatchcmd \__tcobox_print_key: { / } { \kvtcb@doc@keyprefix } { } {\PatchFailed} \xpatchcmd \__tcobox_index_key: { / } { \kvtcb@doc@keyprefix } { } {\PatchFailed} % redefined to take an optional arg (does this O-arg need to be long?) \RenewDocumentCommand \tcbmakedocSubKey { +O{} m m } { \NewDocumentEnvironment{#2}{ O{} +O{} m m +m } { \__tcobox_doc_entry_begin:nnn { doc@sub@keypath=#3, doc~keypath=##1, doc~name={##3}, doc~parameter={##4}, doc~description={##5}, #1, ##2 } {}{key} } { \__tcobox_doc_entry_end:n { key } } \NewDocumentEnvironment{#2*}{} { \group_begin: \bool_set_false:N \l__tcobox_doc_toindex_bool \begin{#2} } { \end{#2} \group_end: } } \RenewDocumentCommand \tcbmakedocSubKeys { +O{} m m } { \NewDocumentEnvironment{#2}{ +O{} +m } { \__tcobox_doc_entry_begin:nnn { doc@sub@keypath=#3, doc~keypath=, #1, ##1 } {##2}{key} } { \__tcobox_doc_entry_end:n { key } } } % bonus: pass \kvtcb@text@key to \tcbIndexPrintKeyCA, making the value of % "/tcb/doclang/key" written to .idx, hence possible to be variable per key. % The value of "/tcb/doclang/keys" is already written to .idx. % Currently the value of /tcb/doclang/key is only used in \printindex. % % FIXME: though this change improves consistency, setting different % "/tcb/doclang/key" for different key groups is still like a misuse. % One idea is to provide \kvtcb@text@key and \kvtcb@text@keys wrappers % configurable by user through new keys. % Then "documentation" lib is even more complex. :) \xpatchcmd \__tcobox_index_key: { \tcbIndexPrintKeyCA{\kvtcb@doc@index} } { \tcbIndexPrintKeyCA{\kvtcb@doc@index}{\kvtcb@text@key} } {} {\PatchFailed} % #1: \kvtcb@doc@index, #2: \kvtcb@text@key \RenewDocumentCommand{\tcbIndexPrintKeyCA}{m m} {\tcb@Index@Print@CA{#1}{\kvtcb@col@key}{#2}} \ExplSyntaxOff \makeatother % misuse of "/tcb/doclang/key" and "/tcb/doclang/Keys" \tcbset{ mydoc pgfkeys/.style={ doclang/key=key (\textsf{pgfkeys}), doclang/keys=Keys (\textsf{pgfkeys}) }, mydoc l3keys/.style={ doc key prefix=, doclang/key=key (\textsf{l3keys}), doclang/keys=Keys (\textsf{l3keys}) } } \tcbmakedocSubKey[mydoc pgfkeys]{docTcbKey}{tcb} \tcbmakedocSubKey[mydoc l3keys]{docCsvsimKey}{csvsim} \begin{document} \subsection*{Keys based on \textsf{pgfkeys}} \begin{docKey}[tcb][mydoc pgfkeys]{doc keypath}{=\meta{key path}}{no default, initially empty} content \end{docKey} \begin{docTcbKey}{doc name}{=\meta{name}}{no default, initially empty} content \end{docTcbKey} \docAuxKey[tcb][mydoc pgfkeys]{doc parameter} \subsection*{Keys based on \textsf{l3keys}} \begin{docKey}[csvsim][mydoc l3keys]{after line}{=\meta{code}}{no default, initially empty} content \end{docKey} \begin{docCsvsimKey}{late after line}{=\meta{code}}{no default, initially empty} content \end{docCsvsimKey} \docAuxKey[csvsim][mydoc l3keys]{after first line} \printindex \end{document} ```