summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/easyfloats/doc/preamble/keydoc.tex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/easyfloats/doc/preamble/keydoc.tex')
-rw-r--r--macros/latex/contrib/easyfloats/doc/preamble/keydoc.tex754
1 files changed, 754 insertions, 0 deletions
diff --git a/macros/latex/contrib/easyfloats/doc/preamble/keydoc.tex b/macros/latex/contrib/easyfloats/doc/preamble/keydoc.tex
new file mode 100644
index 0000000000..3116266bef
--- /dev/null
+++ b/macros/latex/contrib/easyfloats/doc/preamble/keydoc.tex
@@ -0,0 +1,754 @@
+% !TeX root = ../easyfloats.tex
+
+% Copyright © 2020 E. Zöllner
+% Alternatively to the terms of the LPPL, at your choice,
+% you can redistribute and/or modify this file under the
+% terms of the Do What The Fuck You Want To Public License, Version 2,
+% as published by Sam Hocevar. See http://www.wtfpl.net/about/.
+
+\usepackage{etoolbox}
+\usepackage{pgfkeys}
+
+% Defines a macro to document a macro or environment key:
+% \keydoc{<keyname> = <allowedvalues>}{<keytype>}
+% \keydoc[<options>]{<keyname> = <allowedvalues>}{<keytype>}
+% Following text is assumed to be a description of the key.
+% If it is instead followed by another \keydoc it is assumed
+% that this key has no description.
+% If a description applies to two keys separate the \keydocs
+% by a slash.
+% Do *not* put an empty line between a \keydoc and it's description.
+% Spaces after (the second argument of) \keydoc are ignored.
+% <options> is a comma separated list of the following possible key=value pairs:
+% - target = the full key to another key.
+% The name of this key is made into a link to target.
+% This is used by \forwardingkeydoc.
+% - initial value
+% - default value
+% Values are separated by pipes.
+% Wildcards are put in angular brackets.
+%
+% The description of a \keydoc is assumed to reach up to the
+% next \keydoc, \section, \subsection or \subsubsection.
+% If that is not the case you must explicitly end it with
+% \endkeydoc
+% If the description of a \keydoc is ended by a \*section macro
+% there must be a \par (aka an empty line) before that \*section.
+% Otherwise \keydoc@descriptionsep will be inserted.
+%
+% There is a special macro for forwarding keys:
+% \forwardingkeydoc[<options>]{<keyname>}
+% In contrast to \keydoc, the target option can be a path, name or full key.
+% If target is not given it is tried to generate it by expanding
+% \TargetKey{<keypath>}{<keyname>}
+% This macro is given the path (without trailing slash) and name
+% of the key to be described and is expected to expand to a full key.
+% You must define it yourself if you want to leave out the optional argument.
+%
+% \forwardingkeydoc uses internally a more generalized macro:
+% \correspondingkeydoc[<options>]{<keyname>}{<keytype>}
+% target is as flexible as for \forwardingkeydoc
+% but it also takes a <keytype> like \keydoc.
+%
+% Examples for a key pattern can be specified with
+% \keylinktarget{<keyexample>}
+% It must be specified directly following the \keydoc it refers to.
+%
+% \key is redefined to link to \keydoc.
+% However, different environments can have different keys
+% with the same name. In that case a path must be set to
+% distinguish these keys:
+% \keydocpath{<path>}
+% Sets the path for all following \keydoc in the same group.
+% Unambiguous keys can be referenced without a path:
+% \key{sub}
+% For ambiguous keys the path must given as an optional argument:
+% \key[/object]{label}
+% Paths may *not* include a trailing slash.
+%
+% Internals:
+% \begin@keydoc is put before the first \keydoc.
+% \endkeydoc is put after the last description of a \keydoc.
+% \keydoc@beforekey is put before each \keydoc but only once
+% for \keydocs which belong together.
+% \keydoc@keysep is put between \keydocs which belong together.
+% \keydoc@descriptionsep is put between a \keydoc and it's description.
+% If a \keydoc is followed by a \par neither \keydoc@keysep
+% nor \keydoc@descriptionsep is inserted.
+
+
+\makeatletter
+
+% ---------- \keydoc settings ---------
+
+\newcommand{\begin@keydoc}{\begin{itemize}}
+\def \endkeydoc {\end{itemize}}
+
+\newcommand{\keydoc@beforekey}{\item}
+\newcommand{\keydoc@keysep}{~/ }
+\newcommand{\keydoc@descriptionsep}{\nopagebreak\par}
+
+\newcommand{\keydoc@mandatoryvalueformat}[1]{#1}
+\newcommand{\keydoc@optionalvalueformat}{\textcolor{gray}}
+
+\newcommand{\keydoc@keytype}[1]{\,\ensuremath{^{\pgfmanualcslinkpreskip=.33em\pgfmanualcslinkpostskip=\pgfmanualcslinkpreskip\LinkUnformattedKeyword{keytype}{#1}{\keytypesymbol{#1}}}}}
+\newcommand{\keytypedoc@keytype}[1]{\raisebox{.2ex}{\bfseries\keytypesymbol{#1}}}
+
+% ---------- key type symbols ---------
+
+\newcommand{\keytypesymbolformat}[1]{\hbox{\scriptsize(#1)}}
+\newcommand{\newkeytypesymbol}[2]{% #1: key type, #2: symbol
+ \expandafter\newcommand\csname keytypesymbol@#1\endcsname{#2}%
+}
+\newcommand{\keytypesymbol}[1]{% #1: key type
+ \@ifundefined{keytypesymbol@#1}%
+ {\PackageError{keydoc}{undefined keytype `#1'}{}}%
+ {\keytypesymbolformat{\csname keytypesymbol@#1\endcsname}}%
+}
+
+\newkeytypesymbol{storing key}{sto}
+\newkeytypesymbol{executed key}{exe}
+\newkeytypesymbol{boolean key}{bool}
+\newkeytypesymbol{forwarding key}{fwd}
+\newkeytypesymbol{handler}{hdl}
+\newkeytypesymbol{unknown key handler}{unk}
+
+
+% ---------- optional dependencies ---------
+
+\providecommand{\key}[2][]{% #1: key path/group, #2: key name
+ \texttt{#2}%
+}
+
+
+% ---------- auxiliary macros ---------
+
+% \ifendsonspace{<text>}{<then>}{<else>}
+% Checks if the last token of <text> is a space.
+% If it is it expands to <then>{<text-without-last-space>}.
+% If it is not it expands to <else>{<text>}.
+% <text> may not contain \relax.
+\newcommand\ifendsonspace{\ifendson{ }}
+\newcommand\ifendson[2]{%
+ \def\endson@check##1#1\relax.##2\relax\relax##3##4{%
+ \if \relax\detokenize{##2}\relax
+ \def\endson@do{##4}%
+ \endson@stripandappto##1%
+ \else
+ \def\endson@do{##3{##1}}%
+ \fi
+ \endson@do
+ }%
+ \def\endson@stripandappto##1\relax.{\appto\endson@do{{##1}}}%
+ \endson@check#2\relax.#1\relax.\relax\relax
+}
+
+% \newstripoptend{<cs>}{<suffix>}
+% Defines a new control sequence <cs> which checks if it's argument ends on <suffix>.
+% If the argument of <cs> ends on <suffix> it is stripped.
+% If the argument of <cs> does not end on <suffix> <cs> expands to the argument.
+% <cs> is expandable.
+% The number of required expansion steps depends on whether the argument ends on <suffix> or not.
+\newcommand\newstripoptend[2]{% #1: cs, #2: end
+ \expandafter\def\csname\string#1@do\endcsname##1#2\relax.##2\relax\relax{%
+ \if \relax\detokenize{##2}\relax
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+ {\csname\string#1@strip\endcsname##1}%
+ {##1}%
+ }%
+ \expandafter\def\csname\string#1@strip\endcsname##1\relax.{##1}%
+ \newcommand#1[1]{\csname\string#1@do\endcsname##1\relax.#2\relax.\relax\relax}%
+}
+\newstripoptend\stripoptplus{ (+)}
+
+
+% ---------- \FormatKey ---------
+
+\newcommand{\FormatKey}[1]{%
+ \def\FormatKeyText{}%
+ \FormatKey@lookahead#1\pgfeov
+ \let\FormatKey@original=\FormatKey
+ \let\FormatKey=\@firstofone
+ \KeyFormat@original@key{\FormatKeyText}%
+ \let\FormatKey=\FormatKey@original
+}
+\newcommand{\FormatKey@lookahead}{%
+ \futurelet \FormatKey@nexttoken \FormatKey@check
+}
+\newcommand{\FormatKey@check}{%
+ \ifx \FormatKey@nexttoken (%
+ \def\FormatKey@do{\FormatKey@optional}%
+ \else\ifx \FormatKey@nexttoken <%
+ \def\FormatKey@do{\FormatKey@var}%
+ \else\ifcat \noexpand\FormatKey@nexttoken \space
+ \def\FormatKey@do{\FormatKey@space}%
+ \else\ifx \FormatKey@nexttoken \pgfeov
+ \def\FormatKey@do{\FormatKey@endofloop}%
+ \else\ifx \FormatKey@nexttoken \bgroup
+ \def\FormatKey@do{\FormatKey@arg}%
+ \else
+ \def\FormatKey@do{\FormatKey@normaltoken}%
+ \fi \fi \fi \fi \fi
+ \FormatKey@do
+}
+\def\FormatKey@normaltoken#1{%
+ \appto\FormatKeyText{#1}%
+ \FormatKey@lookahead
+}
+\def\FormatKey@arg#1{%
+ \let\FormatKey@text@backup=\FormatKeyText
+ \def\FormatKeyText{}%
+ \FormatKey@lookahead#1\pgfeov
+ \eappto\FormatKey@text@backup{{\expandonce{\FormatKeyText}}}%
+ \let\FormatKeyText=\FormatKey@text@backup
+ \FormatKey@lookahead
+}
+\def\FormatKey@optional(#1){%
+ \appto\FormatKeyText{{\normalfont\color{gray}(}}%
+ \FormatKey@lookahead#1\pgfeov
+ \appto\FormatKeyText{{\normalfont\color{gray})}}%
+ \FormatKey@lookahead
+}
+\providecommand{\meta@nolink}{\meta}
+\def\FormatKey@var<#1>{%
+ \appto\FormatKeyText{{\normalfont\meta@nolink{#1}}}%
+ \FormatKey@lookahead
+}
+\@firstofone{\def\FormatKey@space} {%
+ \appto\FormatKeyText{ }%
+ \FormatKey@lookahead
+}
+\def\FormatKey@endofloop\pgfeov{%
+}
+
+\providecommand{\pgfeov}{\textcolor{red}{\textbf{eov, this should never be expanded}}}
+
+\let\KeyFormat@original@key=\key
+\renewcommand{\key}{\FormatKey}
+
+
+% ---------- format allowed values ---------
+
+\def\FormatVal@var#1{{\normalfont\meta{#1}}}
+\def\FormatVal@or{\unskip\,\ensuremath{|}\,\ignorespaces}
+
+\newcommand{\FormatValue}[1]{%
+ \def\FormatValue@val{}%
+ \expandafter\FormatValue@loop#1\pgfeov
+ \FormatValue@val
+}
+\newcommand{\FormatValue@loop}{%
+ \futurelet \FormatValue@nexttoken \FormatValue@check
+}
+\newcommand{\FormatValue@check}{%
+ \ifx \FormatValue@nexttoken \pgfeov
+ \def\FormatValue@do##1{}%
+ \else\ifcat \noexpand\FormatValue@nexttoken \space
+ \appto\FormatValue@val{ }%
+ \def\FormatValue@do##1{\FormatValue@loop##1}%
+ \else
+ \def\FormatValue@do{\FormatValue@check@ii}%
+ \fi \fi
+ \FormatValue@do
+}
+\newcommand{\FormatValue@check@ii}[1]{%
+ \if|\noexpand#1%
+ \appto\FormatValue@val{\FormatVal@or}%
+ \def\FormatValue@do{\FormatValue@loop}%
+ \else\if<\noexpand#1%
+ \def\FormatValue@do##1>{\appto\FormatValue@val{\FormatVal@var{##1}}\FormatValue@loop}%
+ \else
+ \appto\FormatValue@val{#1}%
+ \def\FormatValue@do{\FormatValue@loop}%
+ \fi \fi
+ \FormatValue@do
+}
+
+
+% ---------- keyword ---------
+% This is a generalized api to link certain keywords.
+% Use the following macro in a description:
+% \NewKeyword[\unexpanded]{<keywordtype>}{<keyword>}{<formatmacro-bg>}{<formatmacro-fg>}{<text>}
+% Use the following macro in references:
+% \LinkKeyword{<keywordtype>}{<keyword>}<formatmacro-bg><formatmacro-fg>{<text>}
+% <keywordtype> and <keyword> are used to generate/
+% link to a hyper link target. They are not visible
+% in the resulting document.
+% <formatmacro-bg/fg>: TeX code which takes one mandatory argument
+% and formats it as desired. Usually those passed to \NewKeyword are used
+% for both the description and the link.
+% Those passed to \LinkKeyword are used only if the link is undefined.
+% <formatmacro-bg> is applied before \FormatLink.
+% <formatmacro-fg> is applied inside of \FormatLink.
+% Setting a background color must happen in <formatmacro-bg>
+% otherwise it will cover the underline produced by \FormatLink.
+% Using \detokenize must happen in <formatmacro-fg>
+% otherwise \FormatLink will not be executed but printed to the pdf.
+% Changing the font can happen in either one.
+% <text>: TeX code to produce the displayed text.
+% The optional argument of \NewKeyword is a macro which
+% takes the <keyword> as argument and can protect it
+% from expansion when writing it to an auxiliary file.
+% If you try to link an undefined keyword you will
+% get a warning.
+%
+% You can define abbreviations so you do not always
+% need to type out the full name:
+% \AbbrevKeyword[\unexpanded]{<abbrevtype>}{<abbrevname>}{<fulltype>}{<fullname>}
+% If two abbreviations are ambiguous they will not
+% cause an error where they are defined but where
+% they are referenced so you can create abbreviations
+% automatically without trouble.
+%
+% In order to avoid warnings for undescribed keywords
+% \NoKeyword[\unexpanded]{<keywordtype>}{<keyword>}{<formatmacro-bg>}{<formatmacro-fg>}
+% can be used. It is used similar to \NewKeyword but
+% does not display any text and \LinkKeyword to this keyword
+% will not result in a link and will not give a warning.
+% The separation in <formatmacro-bg> and <formatmacro-fg>
+% is only for compatability with \NewKeyword.
+%
+% Links are defined in a temporary file which is loaded in the
+% preamble so that \LinkKeyword can be used before \NewKeyword.
+% I am not using the aux file for that because
+% (a) the aux file is loaded twice (once in \begin{document}
+% and once in \end{document}) and
+% (b) the aux file is loaded in a group so all definitions need
+% to be global but \newcommand can't do that and \gdef does not
+% check if a macro is already defined.
+
+
+% https://github.com/pgf-tikz/pgf/blob/master/tex/latex/pgf/doc/pgfmanual-en-macros.tex
+\colorlet{linkcolor}{black!8}
+\newdimen\pgfmanualcslinkpreskip
+\newdimen\pgfmanualcslinkpostskip
+\ifunderlinelinks
+\newcommand{\FormatLink}[1]{%
+ \begingroup
+ \setbox0=\hbox{#1}%
+ \rlap{{%
+ \keyword@original@color{linkcolor}%
+ \dimen0\wd0
+ \advance\dimen0by-\pgfmanualcslinkpreskip
+ \advance\dimen0by-\pgfmanualcslinkpostskip
+ \hskip\pgfmanualcslinkpreskip
+ \vrule width\dimen0 height-1pt depth1.6pt
+ }}%
+ \box0%
+ \endgroup
+}
+\else
+\newcommand{\FormatLink}[1]{#1}
+\fi
+
+
+% is used in the first run when the keyword is not yet defined
+% or if an abbreviation is ambiguous
+\newcommand{\keyword@placeholder}[1]{%
+ {\keyword@original@color{yellow}%
+ #1%
+ }%
+}
+\let\keyword@original@color=\color
+
+\newcommand{\keyword@targetname}[2]{% #1: keyword type, #2: name
+ keyword:#1:#2%
+}
+\newcommand{\keyword@csname}[2]{% #1: keyword type, #2: name
+ keyword@#1@#2%
+}
+\newcommand{\keyword@link}[3]{% #1: keyword type, #2: name, #3: text
+ \hyperlink{\keyword@targetname{#1}{#2}}{#3}%
+}
+\newcommand{\DisableLinks}{%
+ \let\keyword@link=\@thirdofthree
+ \let\FormatLink=\@firstofone
+}
+\let\keyword@formatenable=\@firstofone
+\newrobustcmd{\keyword@new}[4]{% #1: keyword type, #2: name, #3: format macro bg, #4: format macro fg
+ \expandafter\newcommand\csname\keyword@csname{#1}{#2}\endcsname[1]{\keyword@link{#1}{#2}{\keyword@formatenable{#3}{\FormatLink{\keyword@formatenable{#4}{##1}}}}}%
+}
+\newrobustcmd{\keyword@no}[4]{% #1: keyword type, #2: name, #3: format macro bg, #4: format macro fg
+ \expandafter\newcommand\csname\keyword@csname{#1}{#2}\endcsname[1]{\keyword@formatenable{#3}{\keyword@formatenable{#4}{##1}}}%
+}
+\newrobustcmd{\keyword@abbrev}[4]{% #1: abbrev keyword type, #2: abbrev name, #3: full keyword type, #4: full name
+ \IfKeywordUndefined{#3}{#4}{%
+ \PackageError{keyword}{#3 `#4' (for which you wanted to add the abbreviation `#1@#2') is undefined}{}%
+ }{\IfKeywordUndefined{#1}{#2}{%
+ \expandafter\let \csname\keyword@csname{#1}{#2}\expandafter\endcsname \csname\keyword@csname{#3}{#4}\endcsname
+ }{%
+ \expandafter\def \csname\keyword@csname{#1}{#2}\endcsname ##1{\PackageWarning{keyword}{The abbreviation #1 `#2' is ambiguous. Please specify the full name for ##1}{}\keyword@placeholder{##1}}%
+ }}%
+}
+\newcommand{\IfKeywordIsAbbrev}[4]{% key to be tested, reference key
+ \expandafter\ifx \csname\keyword@csname{#1}{#2}\expandafter\endcsname \csname\keyword@csname{#3}{#4}\endcsname
+ \expandafter \@firstoftwo
+ \else
+ \expandafter \@secondoftwo
+ \fi
+}
+
+\newcommand{\LinkKeyword}[5]{% #1: keyword type, #2: name, #3: formatmacro bg, #4: formatmacro fg, #5: displayed text
+ \IfKeywordUndefined{#1}{#2}{%
+ \edef\do{\noexpand\PackageWarning{keydoc}{Either #1 `#2' is undefined or you need to rerun LaTeX}}%
+ \do
+ \keyword@placeholder{#3{#4{#5}}}%
+ }{%
+ \csname \keyword@csname{#1}{#2}\endcsname{#5}%
+ }%
+}
+\newcommand{\LinkUnformattedKeyword}[3]{% #1: keyword type, #2: name, #3 displayed text
+ \begingroup
+ \let\keyword@formatenable=\@gobble
+ \LinkKeyword{#1}{#2}\@firstofone\@firstofone{#3}%
+ \endgroup
+}
+\newcommand{\IfKeywordUndefined}[2]{% #1: keyword type, #2: name, #3: then, #4: else
+ \expandafter \ifx \csname\keyword@csname{#1}{#2}\endcsname \relax
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+
+
+\newcommand\keyword@filename{\jobname.kw}
+
+\AtBeginDocument{%
+ \IfFileExists{\keyword@filename}{%
+ \makeatletter
+ \input{\keyword@filename}%
+ \makeatother
+ }{}
+ \newwrite\keyword@file
+ \immediate\openout\keyword@file=\keyword@filename\relax
+}
+
+\newcommand{\NewKeyword}[6][\@firstofone]{% [#1: name protection], #2: type, #3: name, #4: format macro bg, #5: format macro fg, #6: text
+ %https://tex.stackexchange.com/a/17138
+ \Hy@raisedlink{\hypertarget{\keyword@targetname{#2}{#3}}{}}%
+ \if\relax\detokenize{#6}\relax
+ \else
+ #4{#5{#6}}%
+ \fi
+ \immediate\write\keyword@file{\keyword@new{#2}{#1{#3}}{\unexpanded{#4}}{\unexpanded{#5}}}%
+}
+\newcommand{\AbbrevKeyword}[5][\@firstofone]{% abbrev = full
+ \immediate\write\keyword@file{\keyword@abbrev{#2}{#1{#3}} {#1{#4}}{#1{#5}}}%
+}
+\newrobustcmd{\NoKeyword}[5][\@firstofone]{% #2: keyword type, #3: name, #4: format macro bg, #5: format macro fg
+ \immediate\write\keyword@file{\keyword@no{#2}{#1{#3}}{\unexpanded{#4}}{\unexpanded{#5}}}%
+}
+
+
+% ---------- \keydoc ---------
+
+\newif\if@inkeydoc
+\newif\ifkeydoc@isrelated
+
+\newcommand\keydoc@keypath{}
+\newcommand{\keydocpath}[1]{\def\keydoc@keypath{#1}}
+
+\pgfqkeys{/keydoc}{%
+ target/.initial,
+ target/.value required,
+ %
+ initial value/.initial,
+ initial value/.value required,
+ %
+ default value/.initial,
+ default value/.value required,
+}
+
+\newcommand{\keydoc@printvalues}{%
+ \pgfkeysgetvalue{/keydoc/initial value}{\keydoc@initialvalue}%
+ \pgfkeysgetvalue{/keydoc/default value}{\keydoc@defaultvalue}%
+ \let\keydoc@initdefault=\@empty
+ %
+ \unless\ifx \keydoc@defaultvalue \pgfkeysnovalue@text
+ \appto\keydoc@initdefault{\hyperref[initial-vs-default-values]{Default value}: \keydoc@defaultvalue.}%
+ \fi
+ \unless\ifx \keydoc@initialvalue \pgfkeysnovalue@text
+ \unless\ifx \keydoc@initdefault \@empty
+ \appto\keydoc@initdefault{ }%
+ \fi
+ \appto\keydoc@initdefault{\hyperref[initial-vs-default-values]{Initial value}: \keydoc@initialvalue.}%
+ \fi
+ \unless\ifx \keydoc@initdefault \@empty
+ \\%
+ {\MaxFontSize\footnotesize\keydoc@initdefault}%
+ \fi
+ \pgfkeyssetvalue{/keydoc/initial value}{\pgfkeysnovalue}%
+ \pgfkeyssetvalue{/keydoc/default value}{\pgfkeysnovalue}%
+}
+\newcommand{\MaxFontSize}[1]{%
+ #1%
+ \def\MaxFontSize@do##1#1##2\relax{%
+ \@tfor\MaxFontSize@fontsize:=##1\do{%
+ \expandafter\let\MaxFontSize@fontsize=\relax
+ }%
+ }%
+ \MaxFontSize@do\Huge\huge\LARGE\Large\large\normalsize\small\footnotesize\scriptsize\tiny\relax
+}
+
+\newcommand{\keydoc}[3][]{% [#1: options], #2: key name, #3: key type
+ \unless \if@inkeydoc
+ \begin@keydoc
+ \keydoc@registerend
+ \@inkeydoctrue
+ \fi
+ \pgfkeyssetvalue{/keydoc/target}{\pgfkeysnovalue}%
+ \pgfqkeys{/keydoc}{#1}%
+ \keydoc@parsekey#2=\relax%
+ \def\keydoc@abbrev{%
+ \AbbrevKeyword{key}{\keydoc@keypattern} {key}{\keydoc@keypath/\keydoc@keypattern}%
+ \AbbrevKeyword{}{\keydoc@keypattern} {key}{\keydoc@keypath/\keydoc@keypattern}%
+ }%
+ \pgfkeysgetvalue{/keydoc/target}{\keydoc@targetkey}%
+ \ifx \keydoc@targetkey \pgfkeysnovalue@text
+ \let\keydoc@link=\@firstofone
+ \else
+ \def\keydoc@link{\LinkKeyword{key}{\keydoc@targetkey}\keydoc@key@bg\keydoc@original@key}%
+ \IfKeywordUndefined{}{\keydoc@keypattern}{%
+ % keep \keydoc@abbrev
+ }{\IfKeywordIsAbbrev{}{\keydoc@keypattern} {key}{\keydoc@keypath/\keydoc@keypattern}{%
+ % keep \keydoc@abbrev
+ }{%
+ \let\keydoc@abbrev=\relax
+ }}%
+ \fi
+ \ifkeydoc@isrelated
+ \keydoc@keysep
+ \else
+ \keydoc@beforekey
+ \fi
+ \edef\keydoc@do{%
+ \noexpand\NewKeyword{key}{\keydoc@keypath/\keydoc@keypattern}{\noexpand\keydoc@key@bg}{\noexpand\keydoc@original@key}{\noexpand\keydoc@link{\keydoc@keypattern}%
+ \noexpand\keydoc@valueformat{\keydoc@keyvalsep\noexpand\FormatValue\noexpand\keydoc@keyval}}%
+ }%
+ \keydoc@do
+ \keydoc@abbrev
+ \keydoc@keytype{#3}%
+ \keydoc@isrelatedfalse
+ \keydoc@lookahead
+}
+\def\keydoc@parsekey#1=#2\relax{%
+ \if \relax\detokenize{#2}\relax
+ \def\keydoc@keypattern{#1}%
+ \def\keydoc@keyval{}%
+ \def\keydoc@keyvalsep{}%
+ \let\keydoc@valueformat=\@firstofone
+ \else
+ \expandafter\def\expandafter\keydoc@keyval\expandafter{\keydoc@stripeq#2\relax}%
+ \expandafter\keydoc@checkifvalueisoptional\keydoc@keyval\relax
+ \ifendsonspace{#1}{%
+ \def\keydoc@keyvalsep{\ =}%
+ \def\keydoc@keypattern%{#1 without space}
+ }{%
+ \def\keydoc@keyvalsep{=}%
+ \def\keydoc@keypattern%{#1}
+ }%
+ \fi
+}
+\def\keydoc@stripeq#1=\relax{#1}
+\def\keydoc@checkifvalueisoptional#1#2\relax{%
+ \pgfkeysgetvalue{/keydoc/default value}{\keydoc@defaultvalue}%
+ \ifx?#1%
+ \ifx \keydoc@defaultvalue \pgfkeysnovalue@text
+ \ifx \keydoc@link \@firstofone
+ \PackageWarning{keydoc}{keydoc with optional value but default value is not given}{}%
+ \fi
+ \fi
+ \def\keydoc@keyval{#2}%
+ \let\keydoc@valueformat=\keydoc@optionalvalueformat
+ \else
+ \unless\ifx \keydoc@defaultvalue \pgfkeysnovalue@text
+ \PackageWarning{keydoc}{keydoc with default value but value is not optional}{}%
+ \fi
+ \let\keydoc@valueformat=\keydoc@mandatoryvalueformat
+ \fi
+}
+
+
+
+\newcommand{\keydoc@lookahead}{%
+ \futurelet \keydoc@nexttoken \keydoc@lookahead@check
+}
+\newcommand{\keydoc@lookahead@check}{%
+ \ifcat \noexpand\keydoc@nexttoken \space
+ \let\keydoc@lookahead@do=\keydoc@lookahead
+ \let\keydoc@lookahead@gobble=\@firstofone
+ \else\ifx \keydoc@nexttoken \par
+ \let\keydoc@lookahead@do=\keydoc@afterlookahead
+ \let\keydoc@lookahead@gobble=\@empty
+ \else\ifx \keydoc@nexttoken /%
+ \keydoc@isrelatedtrue
+ \let\keydoc@lookahead@do=\keydoc@lookahead
+ \let\keydoc@lookahead@gobble=\@gobble
+ \else\ifx \keydoc@nexttoken \keydoc
+ \let\keydoc@lookahead@do=\keydoc@afterlookahead
+ \let\keydoc@lookahead@gobble=\@empty
+ \else\ifx \keydoc@nexttoken \forwardingkeydoc
+ \let\keydoc@lookahead@do=\keydoc@afterlookahead
+ \let\keydoc@lookahead@gobble=\@empty
+ \else\ifx \keydoc@nexttoken \correspondingkeydoc
+ \let\keydoc@lookahead@do=\keydoc@afterlookahead
+ \let\keydoc@lookahead@gobble=\@empty
+ \else\ifx \keydoc@nexttoken \endkeydoc
+ \let\keydoc@lookahead@do=\keydoc@afterlookahead
+ \let\keydoc@lookahead@gobble=\@empty
+ \else
+ \ifkeydoc@isrelated
+ \PackageError{keydoc}{expexcted another keydoc command after /}{}%
+ \fi
+ \keydoc@printvalues
+ \keydoc@descriptionsep
+ \let\keydoc@lookahead@do=\relax
+ \let\keydoc@lookahead@gobble=\@empty
+ \fi \fi \fi \fi \fi \fi \fi
+ \expandafter \keydoc@lookahead@do \keydoc@lookahead@gobble
+}
+\newcommand{\keydoc@afterlookahead}{%
+ \unless\ifkeydoc@isrelated
+ \keydoc@printvalues
+ \fi
+}
+\newcommand{\RegisterEnd}[1]{%
+ \@tfor \@sec@cmd :=\section\subsection\subsubsection \do{%
+ \expandafter\appto\csname My\expandafter\string\@sec@cmd Hook\endcsname{#1}%
+ }%
+}
+\newcommand{\keydoc@registerend}{\RegisterEnd\endkeydoc}
+
+\newcommand{\keylinktarget}[1]{%
+ \AbbrevKeyword{key}{\keydoc@keypath/#1} {key}{\keydoc@keypath/\keydoc@keypattern}%
+ \AbbrevKeyword{key}{#1} {key}{\keydoc@keypath/\keydoc@keypattern}%
+ \AbbrevKeyword{}{#1} {key}{\keydoc@keypath/\keydoc@keypattern}%
+ \ignorespaces
+}
+
+\let\keydoc@original@key=\key
+\newcommand{\keydoc@key@bg}{\formatcode}
+% I cannot say \renewcommand{\key}[1][] because that would break \keydoc@original@key
+\renewcommand{\key}{%
+ \@ifnextchar [
+ \key@withopt
+ \key@withoutopt
+}
+\newcommand{\key@withopt}{}
+\def\key@withopt[#1]#2{%
+ \ifx\relax#1\relax
+ \LinkKeyword{key}{#2}\keydoc@key@bg\keydoc@original@key{#2}%
+ \else
+ \LinkKeyword{key}{#1/#2}\keydoc@key@bg\keydoc@original@key{#2}%
+ \fi
+}
+\newcommand{\key@withoutopt}[1]{%
+ \LinkKeyword{key}{#1}\keydoc@key@bg\keydoc@original@key{#1}%
+}
+
+\def\key@withopt@unformatted[#1]#2{%
+ \ifx\relax#1\relax
+ \LinkUnformattedKeyword{key}{#2}{#2}%
+ \else
+ \LinkUnformattedKeyword{key}{#1/#2}{#2}%
+ \fi
+}
+
+
+% ---------- \forwardingkeydoc ---------
+
+\newcommand{\forwardingkeydoc}[2][]{% [#1: name, path or full key of target], #2: name
+ \correspondingkeydoc[#1]{#2}{forwarding key}%
+}
+\newcommand{\correspondingkeydoc}[3][]{% [#1: options], #2: name, #3: key type
+ \keydoc[#1, /utils/exec=\forwardingkeydoc@parsetarget{#2}]{#2}{#3}%
+}
+\newcommand{\forwardingkeydoc@parsetarget}[1]{% #1: this key name
+ % parse target which may be a name, path or full key of corresponding key
+ \pgfkeysgetvalue{/keydoc/target}{\forwardingkeydoc@targetkey}%
+ \ifx\forwardingkeydoc@targetkey\pgfkeysnovalue@text
+ \ifundef\TargetKey{%
+ \PackageError{keydoc}
+ {\string\TargetKey{<keypath>}{<keyname>} must be defined if the the optional argument of \forwardingkeydoc\space is not passed}
+ {\string\TargetKey\space shall expand to path/name of the linked key given the path (without trailing slash) and name of the forwarding key.}%
+ }{%
+ \def\forwardingkeydoc@targetkey{\TargetKey{\keydoc@keypath}}%
+ \edef\forwardingkeydoc@targetkey{\expandafter\forwardingkeydoc@targetkey\expandafter{\forwardingkeydoc@stripval#1=\relax}}%
+ \expandafter\ifendsonspace\expandafter{\forwardingkeydoc@targetkey}%
+ {\def\forwardingkeydoc@targetkey}%
+ {\def\forwardingkeydoc@targetkey}%
+ \pgfkeyslet{/keydoc/target}{\forwardingkeydoc@targetkey}%
+ }%
+ \else
+ \forwardingkeydoc@parse{\forwardingkeydoc@targetkey}{\keydoc@keypath}{#1}%
+ \pgfkeyslet{/keydoc/target}{\forwardingkeydoc@targetkey}%
+ \fi
+}
+\newcommand\forwardingkeydoc@parse[3]{% #1: key name, key path or full key of target, #2: path of source, #3: name of source
+ \IfStartsWithSlash{#1}{%
+ \edef\forwardingkeydoc@targetkey@original{#1}%
+ \edef\forwardingkeydoc@targetkey{#1/\forwardingkeydoc@stripval#3=\relax}%
+ \expandafter\ifendsonspace\expandafter{\forwardingkeydoc@targetkey}%
+ {\def\forwardingkeydoc@targetkey}%
+ {\def\forwardingkeydoc@targetkey}%
+ \IfKeywordUndefined{key}{\forwardingkeydoc@targetkey}{%
+ \let\forwardingkeydoc@targetkey=\forwardingkeydoc@targetkey@original
+ }{}%
+ }{%
+ \def\forwardingkeydoc@targetkey{#2/#1}%
+ }%
+}
+\def\forwardingkeydoc@stripval#1=#2\relax{#1}
+
+\newcommand{\IfStartsWithSlash}[1]{%
+ \expandafter\IfStartsWithSlash@do#1\relax
+}
+\def\IfStartsWithSlash@do#1#2\relax{%
+ \ifx/#1%
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+
+
+% ---------- \keytypedoc ---------
+
+\newcommand{\begin@keytypedoc}{\begin{itemize}}
+\def \endkeytypedoc {\end{itemize}}
+
+\newcommand{\keytypedoc@beforekeytype}{\item}
+\newcommand{\keytypedoc@format}[1]{\emph{#1}}
+\newcommand{\keytypedoc@descriptionsep}{:}
+
+\newif\if@inkeytypedoc
+
+\newcommand{\keytypeRAW}[1]{#1}
+\newcommand{\keytype@bg}[1]{#1}
+\newcommand{\keytype}{% [#1: type name], #2: displayed text (usually the type name, but can be another grammatic form)
+ \@ifnextchar [
+ {\@keytype@do}
+ {\@dblarg\@keytype@do}%
+}
+\def\@keytype@do[#1]#2{%
+ \LinkKeyword{keytype}{#1}\keytype@bg\keytypeRAW{#2}%
+}
+
+\newcommand{\keytypedoc}[1]{% #1 key type name
+ \unless \if@inkeytypedoc
+ \begin@keytypedoc
+ \keytypedoc@registerend
+ \@inkeytypedoctrue
+ \fi
+ \keytypedoc@beforekeytype[\keytypedoc@keytype{#1}]
+ \NewKeyword{keytype}{#1}{\keytype@bg}{\keytypeRAW}{\keytypedoc@format{#1}}%
+ \keytypedoc@descriptionsep
+}
+
+\newcommand{\keytypedoc@registerend}{\RegisterEnd\endkeytypedoc}
+
+\makeatother