Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Make root (slash /) of a documented key configurable #259

Closed
muzimuzhi opened this issue Nov 15, 2023 · 4 comments
Closed

[FR] Make root (slash /) of a documented key configurable #259

muzimuzhi opened this issue Nov 15, 2023 · 4 comments
Assignees

Comments

@muzimuzhi
Copy link
Contributor

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.

  • Full path of a key defined by pgfkeys (\pgfkeys) indeed starts with /.
  • (Full) path of a key defined by expl3 l3keys module (\keys_define:nn and \keys_set:nn) doesn't start with /. It's path stored in l_keys_path_str is just <module>/<key>, after some sanitisation.
    This is the case for documentation of csvsimple-l3 package.
  • Keys defined by 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

  • defines a new option /tcb/doc path prefix with initial value /,
  • extends \tcbmakedocSubKey and \tcbmakedocSubKeys to accept an optional argument <tcb options>, and
  • in addition makes the value of /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

  • document l3keys-based keys with empty path root and
  • make documented keys based on different key-value mechanisms distinguishable in index by misusing /tcb/doclang/key and /tcb/doclang/Keys (not recommended, just for comparing results in a single document).
Full example

% !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}

image image
@T-F-S
Copy link
Owner

T-F-S commented Nov 17, 2023

I have to look into deeper with more time, but this proposal seems reasonable to me.

@muzimuzhi
Copy link
Contributor Author

muzimuzhi commented Nov 19, 2023

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.

Proposal version 2

\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}

@T-F-S T-F-S self-assigned this Dec 1, 2023
@muzimuzhi
Copy link
Contributor Author

Just for the record: implemented in 5e113b6 (more literal / were caught than in my proposal v2) and e8733ff.

@T-F-S
Copy link
Owner

T-F-S commented Jan 10, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants