diff options
Diffstat (limited to 'macros/latex/contrib/easyfloats/doc/preamble')
8 files changed, 2250 insertions, 0 deletions
diff --git a/macros/latex/contrib/easyfloats/doc/preamble/bibliography.tex b/macros/latex/contrib/easyfloats/doc/preamble/bibliography.tex new file mode 100644 index 0000000000..ad24a2b445 --- /dev/null +++ b/macros/latex/contrib/easyfloats/doc/preamble/bibliography.tex @@ -0,0 +1,35 @@ +% !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[% + sorting=none, % none=citation order +]{biblatex} + +\setcounter{biburllcpenalty}{8000} +\setcounter{biburlucpenalty}{8000} +\setcounter{biburlnumpenalty}{8000} + +\addbibresource{\jobname.bib} + +\SetCiteCommand\autocite + +\newcommand{\mycite}[2][]{% + \citetitle{#2}~\autocite[#1]{#2}% +} + +%https://tex.stackexchange.com/a/108349 +\DeclareCiteCommand{\citetitle} + {\boolfalse{citetracker}% + \boolfalse{pagetracker}% + \usebibmacro{prenote}} + {\ifciteindex + {\indexfield{indextitle}} + {}% + \printtext[bibhyperref]{\printfield[citetitle]{labeltitle}}} + {\multicitedelim} + {\usebibmacro{postnote}} diff --git a/macros/latex/contrib/easyfloats/doc/preamble/description-links.tex b/macros/latex/contrib/easyfloats/doc/preamble/description-links.tex new file mode 100644 index 0000000000..6eac79bc1c --- /dev/null +++ b/macros/latex/contrib/easyfloats/doc/preamble/description-links.tex @@ -0,0 +1,224 @@ +% !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/. + +% Links all \cmd, \env and \handler to the corresponding \Describe*. +% Links all \pkg to a reference defined with \newurllink (see link.tex) +% Defines \pkgoptndoc to document package otions and links all \pkgoptn to it. +% +% \pkgoptndoc{<packageoption>} +% \pkgoptndoc*{<packageoption>} +% The starred version is for default package options. +% The non-starred version is for options disabled by default. +% Empty lines before a \pkgoptndoc are relevant: +% Without an empty line they are considered to belong together. +% With an empty line they do not and \pkgoptndoc@afterpar is inserted as separator. +% A list of \pkgoptndoc must be closed with \endpkgoptndoc. +% +% Defines +% \NoDescribeMacro{<cs>} +% \NoDescribeEnv{<environment>} +% to declare undescribed control sequences or environments +% which shall not produce a warning when being referenced. +% +% Warning: \cmd and \DescribeMacro are not intended for use with control characters. +% +% depends on +% \NewKeyword[\unexpanded]{<keywordtype>}{<keyword>}{<formatmacro-bg>}{<formatmacro-fg>}{<text>} +% \NoKeyword{<keywordtype>}{<keyword>}{<formatmacro-bg>}{<formatmacro-fg>} +% \LinkKeyword{<keywordtype>}{<keyword>}<formatmacro-bg><formatmacro-fg>{<text>} +% from preamble/keydoc.tex + +\makeatletter + +% --------- \cmd & \(No)DescribeMacro ---------- + +\newcommand{\DlCmdLabelName}[1]{\detokenize{#1}} +\newcommand{\Cmd}[1]{\expandafter{\detokenize{#1}\unskip}} +\newcommand{\CmdBg}{\formatcode} +\let\DlOriginalDescribeMacro=\DescribeMacro +\renewcommand{\DescribeMacro}[1]{% + \begingroup + \def\cmd##1{\formatcodeinmarginpar{\Cmd{##1}}}% + \DlOriginalDescribeMacro{#1}% + \endgroup + \NewKeyword[\unexpanded]{cs}{\DlCmdLabelName{#1}}{\CmdBg}{\Cmd}{}% + \AbbrevKeyword[\unexpanded]{}{\DlCmdLabelName{#1}} {cs}{\DlCmdLabelName{#1}}% + \ignorespaces +} +\newcommand{\NoDescribeMacro}[1]{% + \NoKeyword[\unexpanded]{cs}{\DlCmdLabelName{#1}}{\CmdBg}{\Cmd}% + \AbbrevKeyword[\unexpanded]{}{\DlCmdLabelName{#1}} {cs}{\DlCmdLabelName{#1}}% + \ignorespaces +} +\renewrobustcmd{\cmd}[1]{% + \LinkKeyword{cs}{\detokenize{#1}}\CmdBg\Cmd{#1}% +} + + +% --------- \env & \(No)DescribeEnv ---------- + +\let\DlOriginalDescribeEnv=\DescribeEnv +\renewcommand{\DescribeEnv}[1]{% + \DlOriginalDescribeEnv{#1}% + \NewKeyword{env}{#1}{\DlEnvBg}{\DlOriginalEnv}{}% + \AbbrevKeyword{}{#1} {env}{#1}% + \ignorespaces +} +\newcommand{\NoDescribeEnv}[1]{% + \NoKeyword{env}{#1}{\DlEnvBg}{\DlOriginalEnv}% + \AbbrevKeyword{}{#1} {env}{#1}% + \ignorespaces +} +\let\DlOriginalEnv=\env +\renewcommand{\env}[1]{\LinkKeyword{env}{#1}\DlEnvBg\DlOriginalEnv{#1}} +\newcommand{\DlEnvBg}{\formatcode} + + +% --------- \handler & \DescribeHandler ---------- + +\let\DlOriginalDescribeHandler=\DescribeHandler +\renewcommand{\DescribeHandler}[1]{% + \DlOriginalDescribeHandler{#1}% + \NewKeyword{handler}{#1}{\DlHandlerBg}{\DlOriginalHandler}{}% + \AbbrevKeyword{}{#1} {handler}{#1}% + \ignorespaces +} +\let\DlOriginalHandler=\handler +\renewcommand{\handler}[1]{\LinkKeyword{handler}{#1}\DlHandlerBg\DlOriginalHandler{#1}} +\newcommand{\DlHandlerBg}{\formatcode} + +\newcommand{\NoDescribeHandler}[1]{% + \NoKeyword{handler}{#1}{\DlHandlerBg}{\DlOriginalHandler}% + \AbbrevKeyword{}{#1} {handler}{#1}% + \ignorespaces +} + + +% --------- \NoDescribeKey, \NoDescribeVal ---------- + +\newcommand{\NoDescribeKey}[1]{% + \NoKeyword{key}{#1}{\keydoc@key@bg}{\keydoc@original@key}% + \AbbrevKeyword{}{#1} {key}{#1}% + \ignorespaces +} +\newcommand{\NoDescribeVal}[1]{% + \NoKeyword{}{#1}{\formatcode}{\val}% + \ignorespaces +} + + +% --------- \DescribeMeta ---------- + +\newcommand{\DescribeMeta}[1]{% + \NewKeyword{meta}{#1}{\formatcode}{\val}{}% + \ignorespaces +} + +\let\meta@nolink=\meta +\renewcommand{\meta}[1]{% + \IfKeywordUndefined{meta}{#1}% + {\@firstofone}% + {\LinkUnformattedKeyword{meta}{#1}}% + {\meta@nolink{#1}}% +} + + +% --------- \pkgoptn & \pkgoptndoc ---------- + +\let\DlOriginalPkgoptn=\pkgoptn +\renewcommand{\pkgoptn}[1]{\LinkKeyword{pkgoptn}{#1}\DlPkgoptnBg\DlOriginalPkgoptn{#1}} +\newcommand{\DlPkgoptnBg}{\formatcode} + +\newcommand{\begin@pkgoptndoc}{\begin{itemize}} +\def \endpkgoptndoc {\end{itemize}} +\newcommand{\pkgoptndoc@beforepkg@normal}{\item[\radiooff]} +\newcommand{\pkgoptndoc@beforepkg@default}{\item[\radioon]} +% inserted before \pkgoptndoc if it was preceded by an empty line +\newcommand{\pkgoptndoc@afterpar}{\bigpar} + +\newif\if@inpkgoptndoc + +\newcommand{\pkgoptndoc}{% + \unless\if@inpkgoptndoc + \begin@pkgoptndoc + \@inpkgoptndoctrue + \else + \ifvmode + \pkgoptndoc@afterpar + \fi + \fi + \@ifstar + {\pkgoptndoc@beforepkg@default\@pkgoptndoc@do}% + {\pkgoptndoc@beforepkg@normal\@pkgoptndoc@do}% +} +\newcommand{\@pkgoptndoc@do}[1]{% + \NewKeyword{pkgoptn}{#1}{\DlPkgoptnBg}{\DlOriginalPkgoptn}{#1}% + \AbbrevKeyword{}{#1} {pkgoptn}{#1}% +} + +\newcommand{\NoDescribePkgoptn}[1]{% + \NoKeyword{pkgoptn}{#1}{\DlPkgoptnBg}{\DlOriginalPkgoptn}% + \AbbrevKeyword{}{#1} {pkgoptn}{#1}% + \ignorespaces +} + + +% --------- \pkg & \pkgdoc, \NoDescribePkg ---------- + +\let\DlOriginalPkg=\pkg +\newcommand{\DlPkgBg}[1]{#1} +\renewcommand{\pkg}[1]{\LinkKeyword{pkg}{#1}\DlPkgBg\DlOriginalPkg{#1}} +\newcommand{\pkgdoc}[1]{% + \unless\if@inpkgdoc + \begin@pkgdoc + \@inpkgdoctrue + \fi + \pkgdoc@beforepkg + \NewKeyword{pkg}{#1}{\DlPkgBg}{\DlOriginalPkg}{\link[#1]{#1}}% + %\AbbrevKeyword{}{#1} {pkg}{#1}% + \let\pkgdoc@beforepkg=\pkgdoc@beforepkg@bak + \pkgdoc@lookahead +} +\newcommand{\pkgdoc@lookahead}{% + \futurelet \pkgdoc@nexttoken \pkgdoc@lookahead@check +} +\newcommand{\pkgdoc@lookahead@check}{% + \ifcat \noexpand\pkgdoc@nexttoken \space + \let\pkgdoc@lookahead@do=\pkgdoc@lookahead + \let\pkgdoc@lookahead@gobble=\@firstofone + \else\ifx \pkgdoc@nexttoken /% + \pkgdoc@pkgsep + \let\pkgdoc@beforepkg=\relax + \let\pkgdoc@lookahead@do=\pkgdoc@lookahead + \let\pkgdoc@lookahead@gobble=\@gobble + \else\ifx \pkgdoc@nexttoken \pkgdoc + \let\pkgdoc@lookahead@do=\relax + \let\pkgdoc@lookahead@gobble=\@empty + \else + \pkgdoc@descriptionsep + \let\pkgdoc@lookahead@do=\relax + \let\pkgdoc@lookahead@gobble=\@empty + \fi \fi \fi + \expandafter \pkgdoc@lookahead@do \pkgdoc@lookahead@gobble +} + +\newcommand{\begin@pkgdoc}{\begin{itemize}} +\def \endpkgdoc {\end{itemize}} +\newif\if@inpkgdoc +\newcommand{\pkgdoc@beforepkg}{\item} +\newcommand{\pkgdoc@pkgsep}{/} +\newcommand{\pkgdoc@descriptionsep}{ } +\let\pkgdoc@beforepkg@bak=\pkgdoc@beforepkg + +\newcommand{\NoDescribePkg}[1]{% + \NoKeyword{pkg}{#1}{\DlPkgBg}{\DlOriginalPkg}% + %\AbbrevKeyword{}{#1} {pkg}{#1}% + \ignorespaces +} + +\makeatother diff --git a/macros/latex/contrib/easyfloats/doc/preamble/examplecode.tex b/macros/latex/contrib/easyfloats/doc/preamble/examplecode.tex new file mode 100644 index 0000000000..79d3c7f424 --- /dev/null +++ b/macros/latex/contrib/easyfloats/doc/preamble/examplecode.tex @@ -0,0 +1,778 @@ +% !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/. + +% Defines an environment to typeset LaTeX code: +% \begin{examplecode} +% \let\do=\@makeother +% \dospecials +% \end{examplecode} +% @ is treated as letter. +% +% A starred version takes one argument, TeX code to be executed inside of the group. +% It can be used to change catcodes or to define escape characters. +% \begin{examplecode*}{\ExamplecodeEscapeinside $ $} +% a long$\\$long line +% \end{examplecode*} +% +% \ExamplecodeEscapeinside takes two arguments +% characters between which the code is executed normally. +% +% \ExamplecodeNoBox +% disables the tcolorbox +% +% \ExamplecodeLinenumbers +% enables line numbers +% +% \\ is redefined to cause a linebreak marked with \ExamplecodePostBreakText. + + + +\makeatletter +% ---------- settings --------- + +\usepackage{xcolor} +\usepackage{tcolorbox} +\tcbuselibrary{breakable,skins} +\usepackage{latexsym} +\usepackage{textcomp} + + +% taken from /usr/lib/python3/dist-packages/pygments/styles/default.py +\definecolor{math}{RGB}{"BA,"21,"21} +\definecolor{aligntab}{RGB}{"00,"80,"00} +\definecolor{parameter}{RGB}{"19,"17,"7C} +\colorlet{superscript}{black} +\colorlet{subscript}{superscript} +\colorlet{brace}{aligntab} +\colorlet{controlsequence}{aligntab} +\definecolor{comment}{RGB}{"40,"80,"80} +\definecolor{codebackground}{rgb}{0.9,0.9,1} +\colorlet{codeborder}{codebackground!50!black} +\colorlet{codelinkcolor}{white} + +\newtcolorbox{examplecodebox}{breakable, skin=enhanced, + colback = codebackground, + colframe = codeborder, + size = fbox, % normal|title|small|fbox|tight|minimal + %left = 0pt, right = 0pt, + %top = 0pt, bottom = 0pt, + %boxrule = 1pt, + %arc = 3pt, +} +\newcommand{\ExamplecodeNoBox}{% + \let\examplecodebox=\par + \let\endexamplecodebox=\par +} + +\newcommand{\NewExamplecodeFormatMandatoryArgument}[2]{% #1: control sequence, #2: replacement text where ##1 is the unprocessed argument + \expandafter\newcommand\csname @examplecode@formatarg\detokenize{#1}\endcsname[1]{\ExamplecodeProcessBeginGroup{\{}#2\ExamplecodeProcessEndGroup{\}}\ExamplecodeAllowLinebreakBeforeNext\@examplecode@loop}% +} +\newcommand{\NewExamplecodeFormatOptionalArgument}[4]{% #1: control sequence, #2: bracket open, #3: bracket close, #4: replacement text where ##1 is the unprocessed argument + \expandafter\def\csname @examplecode@formatoptarg\detokenize{#1}#2\endcsname##1#3{\ExamplecodeProcessBracket{#2}#4\ExamplecodeProcessBracket{#3}\ExamplecodeAllowLinebreakBeforeNext\@examplecode@loop}% +} +\NewExamplecodeFormatMandatoryArgument\begin{\ExamplecodeProcessEnv{#1}\ExamplecodeSetCmd{#1}} +\NewExamplecodeFormatMandatoryArgument\end{\ExamplecodeProcessEnv{#1}\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument\usepackage{\ExamplecodeProcessPkg{#1}\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument{object}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument{tableobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument{figureobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument{subobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument\objectset{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatOptionalArgument\includegraphicobject[]{\ExamplecodeParseKeys{}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatOptionalArgument\includegraphicsubobject[]{\ExamplecodeParseKeys{}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument\NewObjectStyle{\ExamplecodeParse\relax\relax\ExamplecodeEndParseKeys#1\ExamplecodeEndParseKeys\ExamplecodeSetCmd{\NewObjectStyle2}} +\NewExamplecodeFormatMandatoryArgument{\NewObjectStyle2}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} + +% custom styles defined in example +\NewExamplecodeFormatMandatoryArgument{tikzobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} +\NewExamplecodeFormatMandatoryArgument{tikz3dobject}{\ExamplecodeParseKeys{/object}#1\ExamplecodeEndParseKeys\ExamplecodeNoCmd} + +\newcommand{\ExamplecodeFormatMeta}[1]{{\normalfont\meta{#1}}} + +\newcommand{\ExamplecodePrint}[1]{#1} + +\newcommand{\ExamplecodePostBreakSymbol}{\footnotesize$\hookrightarrow$\quad} +\newcommand{\ExamplecodeIndentation}{}% don't change this, it is overwritten later to always contain the indentation of the current line +\newcommand{\ExamplecodePostBreakText}{\hbox{\ExamplecodeIndentation\ExamplecodePostBreakSymbol}} +\newcommand{\ExamplecodeAllowLinebreak}{\discretionary{}{\ExamplecodePostBreakText}{}} +\newcommand{\ExamplecodeAllowLinebreakBeforeNext}{\@examplecode@allowlinebreakbeforenexttrue} +\newcommand{\ExamplecodeLinebreak}{\newline\ExamplecodePostBreakText} + +\newcommand{\ExamplecodeFormatCmd}[1]{{\leavevmode\color{controlsequence}\LinkUnformattedKeyword{cs}{\detokenize{#1}}{\string#1}}\ExamplecodeAllowLinebreakBeforeNext} % catcode 0/16 +\newcommand{\ExamplecodeFormatEnv}[1]{\LinkUnformattedKeyword{env}{#1}{#1}} +\newcommand{\ExamplecodeFormatPkg}[1]{\LinkUnformattedKeyword{pkg}{#1}{#1}} + +\newcommand{\ExamplecodeFormatBeginGroup}[1]{\textcolor{brace}{#1}} % catcode 1 +\newcommand{\ExamplecodeFormatEndGroup}[1]{\textcolor{brace}{#1}\ExamplecodeAllowLinebreakBeforeNext} % catcode 2 +\newcommand{\ExamplecodeFormatMathShift}[1]{\textup{#1}} % catcode 3, see \ExamplecodeFormatMath +\newcommand{\ExamplecodeFormatAlignmentTab}[1]{\textcolor{aligntab}{#1}} % catcode 4 +% catcode 5: \ExamplecodeEndOfLine +\newcommand{\ExamplecodeFormatParameter}[1]{\textcolor{parameter}{#1}} % catcode 6 +\newcommand{\ExamplecodeFormatSuperscript}[1]{\textcolor{superscript}{#1}} % catcode 7 +\newcommand{\ExamplecodeFormatSubscript}[1]{\textcolor{subscript}{#1}} % catcode 8 +% catcode 9: ignored +% catcode 10: \ExamplecodeSpace, \ExamplecodeTab +\newcommand{\ExamplecodeFormatText}[1]{% + \ifx`#1% + \textasciigrave + \else\ifx'#1% + \textquotesingle + \else + #1% + \fi\fi +} % catcode 11, 12 +\newcommand{\ExamplecodeFormatBracket}[1]{#1} % catcode 11 +% catcode 13: active (uses \ExamplecodeFormatCmd, too) + +% in contrast to the other format macros this does +% *not* take an argument. Instead it applies the +% format for the rest of the group. +\newcommand{\ExamplecodeFormatComment}{% + \leavevmode + \color{comment}% + \itshape + \let\color=\@gobble +} % catcode 14 +\newcommand{\ExamplecodeFormatMath}{% + \leavevmode + \color{math}% + \itshape + \let\color=\@gobble + \ExamplecodeForbidLinebreaks +} +\newcommand{\ExamplecodeForbidLinebreaks}{% + \let\discretionary=\@thirdofthree +} % catcode 3 + +% catcode 15: invalid + +\newcommand{\ExamplecodeSpaceSymbol}{\space} +\newcommand{\ExamplecodeTabSymbol}{\qquad} +\newcommand{\ExamplecodeIndentationSpace}{\EnsureHMode\nobreak\space} +\newcommand{\ExamplecodeIndentationTab}{\EnsureHMode\nobreak\qquad} +\newcommand{\ExamplecodeNormalSpace}{\discretionary{}{\ExamplecodePostBreakText}{\hbox{\ExamplecodeSpaceSymbol}}} +\newcommand{\ExamplecodeNormalTab}{\discretionary{}{\ExamplecodePostBreakText}{\hbox{\ExamplecodeTabSymbol}}} +\newcommand{\ExamplecodeEndOfLine}{\EnsureHMode\par} + + +\newcommand{\ExamplecodeTabsize}{4} + + +\newcommand{\ExamplecodeAllowLinebreakAfter}[1]{\expandafter\def\csname @examplecode@breakafter@#1\endcsname{\ExamplecodeAllowLinebreakBeforeNext}} +\ExamplecodeAllowLinebreakAfter] + + +% ---------- process --------- + +\newif\ifExamplecodeInAlign + +\newcommand{\ExamplecodeProcessCmd}[1]{\ExamplecodePrint{\ExamplecodeFormatCmd{#1}}} % catcode 0/16 +\newcommand{\ExamplecodeProcessEnv}[1]{\ExamplecodePrint{\ExamplecodeFormatEnv{#1}}} +\newcommand{\ExamplecodeProcessPkg}[1]{\ExamplecodePrint{\ExamplecodeFormatPkg{#1}}} +\newcommand{\ExamplecodeProcessBeginGroup}[1]{\ExamplecodePrint{\ExamplecodeFormatBeginGroup{#1}}} % catcode 1 +\newcommand{\ExamplecodeProcessEndGroup}[1]{\ExamplecodePrint{\ExamplecodeFormatEndGroup{#1}}} % catcode 2 +\newcommand{\ExamplecodeProcessMathShift}[1]{\ExamplecodePrint{\ExamplecodeFormatMathShift{#1}}} % catcode 3 +\newcommand{\ExamplecodeProcessBeginMath}{\ExamplecodePrint{\begingroup\ExamplecodeFormatMath}} % catcode 3 +\newcommand{\ExamplecodeProcessEndMath}{\ExamplecodePrint{\endgroup}} +\newcommand{\ExamplecodeProcessAlignmentTab}[1]{\ExamplecodePrint{% + \ifExamplecodeInAlign + \endgroup + \fi + \ExamplecodeAllowLinebreak + \begingroup + \ExamplecodeInAligntrue + \ExamplecodeForbidLinebreaks + \ExamplecodeFormatAlignmentTab{#1}% +}} % catcode 4 +\newcommand{\ExamplecodeProcessEndOfLine}{\ExamplecodePrint{% + \ifExamplecodeInAlign + \endgroup + \fi + \ExamplecodeEndOfLine +}} % catcode 5 +\newcommand{\ExamplecodeProcessParameter}[1]{\ExamplecodePrint{\ExamplecodeFormatParameter{#1}}} % catcode 6 +\newcommand{\ExamplecodeProcessSuperscript}[1]{\ExamplecodePrint{\ExamplecodeFormatSuperscript{#1}}} % catcode 7 +\newcommand{\ExamplecodeProcessSubscript}[1]{\ExamplecodePrint{\ExamplecodeFormatSubscript{#1}}} % catcode 8 +% catcode 9: ignored +\newcommand{\ExamplecodeProcessSpace}{\ExamplecodePrint{\ExamplecodeSpace}\ExamplecodeAppendIndentation{\ExamplecodeSpace}} % catcode 10 +\newcommand{\ExamplecodeProcessTab}{\ExamplecodePrint{\ExamplecodeTab}\ExamplecodeAppendIndentation{\ExamplecodeTab}} % catcode 10 +\newcommand{\ExamplecodeProcessText}[1]{\ExamplecodePrint{\ExamplecodeFormatText{#1}}} % catcode 11, 12 +\newcommand{\ExamplecodeProcessBracket}[1]{\ExamplecodePrint{\ExamplecodeFormatBracket{#1}}} % catcode 11 +% catcode 13: active (uses \ExamplecodeProcessCmd, too) +\newcommand{\ExamplecodeProcessBeginComment}{\ExamplecodePrint{\begingroup\ExamplecodeFormatComment}} % catcode 14 +\newcommand{\ExamplecodeProcessEndComment}{\ExamplecodePrint{\endgroup}} +% catcode 15: invalid + +\newcommand{\ExamplecodeProcessCleanup}{\ExamplecodePrint{% + \ifExamplecodeInAlign + \endgroup + \fi +}} + +\newcommand{\ExamplecodeProcessMeta}[1]{\ExamplecodePrint{\ExamplecodeFormatMeta{#1}}} + + +% ---------- key=value options --------- + +\newcommand{\ExamplecodeParseKeys}[1]{% #1: key path + \ExamplecodeParse + {\@examplecode@prepare@parsekeys{#1}}% + {\@examplecode@cleanup@parsekeys}% + \ExamplecodeEndParseKeys +} +\newcommand{\@examplecode@prepare@parsekeys}[1]{% #1: key path + \let\@examplecode@print@original=\ExamplecodePrint + \ExamplecodeNoCmd + \def\@examplecode@key@cmd{\key@withopt@unformatted}% + \def\@examplecode@keypath{#1}% + \let\@examplecode@pathsep=\@empty + \def\ExamplecodeProcessText##1{% ##1: current token + \ifx,##1% + \ifExamplecodeInAlign + \endgroup + \fi + \@examplecode@endkey + \let\@examplecode@beginkey=\@examplecode@beginkey@bak + \@examplecode@print@original{\ExamplecodeFormatText{##1}}% + \else\ifx=##1% + \@examplecode@endkey + \let\@examplecode@beginkey=\relax + \@examplecode@print@original{\ExamplecodeFormatText{##1}}% + \else\ifx/##1% + \@examplecode@beginkey + \@examplecode@appendpathsep{##1}% + \else\ifx.##1% + \unless \ifx \@examplecode@pathsep \@empty + \@examplecode@endkey + \expandafter\@examplecode@print@original\expandafter{\expandafter\ExamplecodeFormatText\expandafter{\@examplecode@pathsep}}% + \fi + \@examplecode@beginkey + \ifx \@examplecode@key \@empty + \def\@examplecode@key@cmd[####1]####2{\LinkUnformattedKeyword{handler}{####2}{####2}}% + \fi + \@examplecode@appendkey{##1}% + \else + \@examplecode@beginkey + \@examplecode@appendkey{##1}% + \fi \fi \fi \fi + }% + \def\@examplecode@appendkey##1{% + \ExamplecodePrint{\ExamplecodeFormatText{##1}}% + }% + \def\@examplecode@appendpathsep##1{% + \ExamplecodePrint{\ExamplecodeFormatText{##1}}% + }% + \def\ExamplecodeProcessBeginComment{% + \@examplecode@endkey + \begingroup + \let\@examplecode@beginkey=\relax + \let\@examplecode@beginkey@bak=\relax + \@examplecode@print@original{\begingroup\ExamplecodeFormatComment}% + \let\ExamplecodePrint=\@examplecode@print@original + }% + \def\ExamplecodeProcessEndComment{% + \@examplecode@print@original{\endgroup}% + \endgroup + }% + \def\ExamplecodeProcessBeginGroup##1{% + \begingroup + \let\@examplecode@beginkey=\relax + \let\@examplecode@beginkey@bak=\relax + \ExamplecodePrint{\ExamplecodeFormatBeginGroup{##1}}% + }% + \def\ExamplecodeProcessEndGroup##1{% + \ExamplecodePrint{\ExamplecodeFormatEndGroup{##1}}% + \endgroup + }% +} +\newcommand{\@examplecode@cleanup@parsekeys}{% + \@examplecode@endkey + \ExamplecodeProcessCleanup +} +\newcommand{\@examplecode@beginkey}{% + \begingroup + \def\@examplecode@key{}% + \let\@examplecode@keyspace=\@empty + \def\@examplecode@appendkey##1{% + \unless \ifx \@examplecode@keyspace \@empty + \appto\@examplecode@key{ }% + \let\@examplecode@keyspace=\@empty + \fi + \@examplecode@applypathsep + \appto\@examplecode@key{##1}% + }% + \def\@examplecode@appendpathsep##1{% + \unless \ifx \@examplecode@keyspace \@empty + \appto\@examplecode@key{ }% + \let\@examplecode@keyspace=\@empty + \fi + \appto\@examplecode@pathsep{##1}% + }% + \def\@examplecode@applypathsep{% + \unless \ifx \@examplecode@pathsep \@empty + \eappto\@examplecode@key{\@examplecode@pathsep}% + \let\@examplecode@pathsep=\@empty + \fi + }% + \def\ExamplecodePrint##1{% + \@examplecode@endkey + \@examplecode@print@original{##1}% + }% + \def\ExamplecodeProcessSpace{% + \@examplecode@applypathsep + \appto\@examplecode@keyspace{\ExamplecodeSpace}% + }% + \let\@examplecode@beginkey=\relax + \def\@examplecode@endkey{% + \edef\@examplecode@do{\noexpand\@examplecode@print@original{% + \expandafter\noexpand\@examplecode@key@cmd[\@examplecode@keypath]{\@examplecode@key}% + \expandonce{\@examplecode@pathsep}% + \expandonce{\@examplecode@keyspace}% + }}% + \@examplecode@do + \endgroup + }% +} +\let\@examplecode@beginkey@bak=\@examplecode@beginkey +\newcommand{\@examplecode@endkey}{} + +\newcommand{\ExamplecodeEndParseKeys}{\PackageError{examplecode}{This should never be expanded}{}} + + +% ---------- parsing command --------- + +\newcommand{\ExamplecodeParse}[3]{% #1: prepare, #2: cleanup, #3: end token + \begingroup + #1% + \let\@examplecode@endtoken=#3% + \def\@examplecode@checkend##1{#2\@examplecode@beforeline\endgroup}% + \@examplecode@loop +} + +% WARNING: reads end token before changing catcodes +% compares end token with \ifx in case it is a control sequence +% => does not find end token if it's catcode is changed +% => \xc`...` does not work directly but inside of macro +\newcommand{\@xc@prepare}{% + \def\ExamplecodeNormalSpace{\ExamplecodeSpaceSymbol}% + \def\ExamplecodeNormalTab{\ExamplecodeTabSymbol}% + \@examplecode@setcatcodes + \@examplecode@state@normal + \let\ExamplecodeAllowLinebreak=\relax + \gdef\@xc@code{}% + \def\ExamplecodePrint{\gappto\@xc@code}% +}% +\newcommand{\@xc@afterend}{% + \formatcode{\@xc@code}% +} +\newcommand{\xc}{% + \ExamplecodeParse{% + \@xc@prepare + }{% + \ExamplecodeProcessCleanup + \@xc@afterend + }% +} +\newcommand{\xckey}{% + \ExamplecodeParse{% + \@xc@prepare + \@examplecode@prepare@parsekeys{}% + }{% + \@examplecode@cleanup@parsekeys + \@xc@afterend + }% +} + + +% ---------- escape inside --------- + +\newcommand{\ExamplecodeEscapeinside}[2]{% #1: begin token, #2: end token + \def\@examplecode@escapeinside#1##1#2{##1\@examplecode@loop}% + \let\@examplecode@escapeinside@startchar=#1% +} + + +% ---------- line numbers --------- + +\newcounter{ExamplecodeLinecounter} +\newcommand{\ExamplecodeLinenumbers}{% + \setcounter{ExamplecodeLinecounter}{1}% + \let\@examplecode@beforeline@hook=\@examplecode@insertlinenumber +} +\newcommand\@examplecode@insertlinenumber{% + \makebox[0pt][r]{{\ExamplecodeFormatLinenumber{\theExamplecodeLinecounter}}\quad}% + \stepcounter{ExamplecodeLinecounter}% +} +\newcommand\ExamplecodeFormatLinenumber[1]{% + \normalfont + \footnotesize + #1% +} + + +% ---------- parsing environment --------- + +\newenvironment{examplecode}{% + \csname examplecode*\endcsname{}% +}{% + \csname endexamplecode*\endcsname{}% +} +\newenvironment{examplecode*}[1]{% + \let\@examplecode@envname=\@currenvir + \@examplecode@setcatcodes + \let\@examplecode@endtoken=\end + #1% + \begin{examplecodebox}% + \colorlet{linkcolor}{codelinkcolor}% + \raggedright + \ttfamily + \leavevmode + \parskip=0pt + \parindent=0pt\relax + \let\\=\ExamplecodeLinebreak + \@examplecode@state@firstindent + \@examplecode@gobblefirsteol +}{% + \end{examplecodebox}% +} + +\newenvironment{examplecodekey}{% + \csname examplecodekey*\endcsname{}% +}{% + \csname endexamplecodekey*\endcsname{}% +} +\newenvironment{examplecodekey*}[1]{% + \csname examplecode*\endcsname{% + \@examplecode@prepare@parsekeys{}% + #1% + }% +}{% + \@examplecode@cleanup@parsekeys + \csname endexamplecode*\endcsname +} + + +\newcommand{\@examplecode@setcatcodes}{% + \@makeother\^^M% end of line + \@makeother\^^I% tab + \@makeother\ % space + \@makeother\%% + \makeatletter + % changed + \@makeother*% + \@makeother`% +} +\begingroup +\@makeother\^^M % +\@makeother\^^I % +\@firstofone{% +\endgroup% +\let\EolOther=^^M% +\let\TabOther=^^I% +} +\begingroup\@makeother\%\@firstofone{\endgroup\let\PercentOther=%} + +\newcommand{\@examplecode@error@catcodes@indentation}{\PackageError{examplecode}{failed to change catcodes, indentation will be screwed up}{}} +\newcommand{\@examplecode@error@mixedtabsandspaces}{\PackageWarning{examplecode}{mixed use of tabs and spaces}} + +\newcount\@examplecode@count@outerindent +\newcount\@examplecode@count@gobbledindent +\newif\if@examplecode@allowlinebreakbeforenext + +\newcommand{\EnsureHMode}{\leavevmode\@examplecode@beforeline\let\EnsureHMode\relax}% +\let\@EnsureHMode@bak=\EnsureHMode + + +\newcommand{\@examplecode@beforeline}{% + \@examplecode@beforeline@hook + \let\@examplecode@beforeline=\relax +} +\let\@examplecode@beforeline@bak=\@examplecode@beforeline +\let\@examplecode@beforeline@hook=\relax + +\newcommand{\@examplecode@state@firstindent}{% + \@examplecode@beforeline + \let\@examplecode@check@spaces=\@examplecode@check@firstindent +} +\newcommand{\@examplecode@state@gobbleindent}{% + \let\@examplecode@beforeline=\@examplecode@beforeline@bak + \let\@examplecode@state@normal=\@examplecode@state@normal@bak + \ifnum \@examplecode@count@outerindent > 0 + \@examplecode@count@gobbledindent=0 + \let\@examplecode@check@spaces=\@examplecode@check@gobbleindent + \else + \@examplecode@state@indent + \fi + \let\EnsureHMode=\@EnsureHMode@bak +} +\newcommand{\@examplecode@state@indent}{% + \let\@examplecode@check@spaces=\@examplecode@check@normalspaces + \let\ExamplecodeSpace=\ExamplecodeIndentationSpace + \let\ExamplecodeTab=\ExamplecodeIndentationTab + \def\ExamplecodeAppendIndentation##1{\eappto\ExamplecodeIndentation{\expandonce{##1}}}% + \let\ExamplecodeIndentation=\@empty +} +\newcommand{\@examplecode@state@normal}{% + \@examplecode@beforeline + \let\@examplecode@check@spaces=\@examplecode@check@normalspaces + \let\ExamplecodeSpace=\ExamplecodeNormalSpace + \let\ExamplecodeTab=\ExamplecodeNormalTab + \let\@examplecode@state@normal=\relax + \let\ExamplecodeAppendIndentation=\@gobble +} +\let\@examplecode@state@normal@bak=\@examplecode@state@normal + + +\newcommand{\@examplecode@gobblefirsteol}[1]{% + \ifx \EolOther #1\relax + \else + \PackageError{examplecode}{unexpected code on same line after \string\begin{examplecode}}{}% + \detokenize{#1}% + \fi + \@examplecode@loop +} + +\newcommand{\@examplecode@loop}{% + \futurelet \@examplecode@nexttoken \@examplecode@check +} +\newcommand{\@examplecode@check}{% + \ifx \@examplecode@nexttoken \@examplecode@endtoken + \expandafter \@examplecode@checkend + \else + \if@examplecode@allowlinebreakbeforenext + \ExamplecodeAllowLinebreak + \@examplecode@allowlinebreakbeforenextfalse + \fi + \expandafter \@examplecode@check@ii + \fi +} + +\newcommand{\@examplecode@check@ii}{% + \ifcat \noexpand\@examplecode@nexttoken \relax + \def\@examplecode@do{\@examplecode@handle@cs}% + \else + \def\@examplecode@do{\@examplecode@check@spaces}% + \fi + \@examplecode@do +} +\newcommand{\@examplecode@handle@cs}[1]{% + \ExamplecodeSetCmd{#1}% + \@examplecode@state@normal + \ExamplecodeProcessCmd{#1}% + \@examplecode@loop +} +\newcommand{\ExamplecodeSetCmd}[1]{\edef\@examplecode@cs{\detokenize{#1}}} +\newcommand{\ExamplecodeNoCmd}{\def\@examplecode@cs{}} +\ExamplecodeNoCmd + +\newcommand{\@examplecode@check@normalspaces}{% + \ifcat \noexpand\@examplecode@nexttoken \space + \def\@examplecode@do##1{\ExamplecodeProcessSpace\@examplecode@loop##1}% + \else\if \noexpand\@examplecode@nexttoken \space + \def\@examplecode@do##1{\ExamplecodeProcessSpace\@examplecode@loop}% + \else\ifx \@examplecode@nexttoken \TabOther + \def\@examplecode@do##1{\ExamplecodeProcessTab\@examplecode@loop}% + \else + \def\@examplecode@do{\@examplecode@check@iv}% + \fi \fi \fi + \@examplecode@do +} +% count the indentation of the first line +\newcommand{\@examplecode@check@firstindent}{% + \ifcat \noexpand\@examplecode@nexttoken \space + \@examplecode@error@catcodes@indentation + \advance\@examplecode@count@outerindent by 1 + \def\@examplecode@do##1{\@examplecode@loop##1}% + \else\if \noexpand\@examplecode@nexttoken \space + \advance\@examplecode@count@outerindent by 1 + \def\@examplecode@do##1{\@examplecode@loop}% + \else\ifx \@examplecode@nexttoken \TabOther + \advance\@examplecode@count@outerindent by \ExamplecodeTabsize + \def\@examplecode@do##1{\@examplecode@loop}% + \else + \def\@examplecode@do{\@examplecode@check@iv}% + \fi \fi \fi + \@examplecode@do +} +% gobble indentation as far as the first line was indented +\newcommand{\@examplecode@check@gobbleindent}{% + \ifcat \noexpand\@examplecode@nexttoken \space + \@examplecode@error@catcodes@indentation + \@examplecode@gobbleindent{1}% + \def\@examplecode@do##1{\@examplecode@loop##1}% + \else\if \noexpand\@examplecode@nexttoken \space + \@examplecode@gobbleindent{1}% + \def\@examplecode@do##1{\@examplecode@loop}% + \else\ifx \@examplecode@nexttoken \TabOther + \@examplecode@gobbleindent{\ExamplecodeTabsize}% + \def\@examplecode@do##1{\@examplecode@loop}% + \else + \def\@examplecode@do{\@examplecode@check@iv}% + \fi \fi \fi + \@examplecode@do +} +\newcommand{\@examplecode@gobbleindent}[1]{% + \advance\@examplecode@count@gobbledindent by #1 + \ifnum \@examplecode@count@gobbledindent = \@examplecode@count@outerindent + \@examplecode@state@indent + \else\ifnum \@examplecode@count@gobbledindent > \@examplecode@count@outerindent + \@examplecode@error@mixedtabsandspaces + \@examplecode@state@indent + \fi \fi +} +\newcommand{\@examplecode@check@iv}{% + \def\@examplecode@do{\@examplecode@check@v}% + \unless\ifx \@examplecode@escapeinside@startchar \relax + \if \noexpand\@examplecode@nexttoken \noexpand\@examplecode@escapeinside@startchar + \def\@examplecode@do{\@examplecode@escapeinside}% + \fi + \fi + \@examplecode@do +} +\newcommand{\@examplecode@check@v}{% + \ifcat \noexpand\@examplecode@nexttoken \bgroup% catcode 1 + \def\@examplecode@do{\@examplecode@handlebgroup}% + \else\ifcat \noexpand\@examplecode@nexttoken \egroup% catcode 2 + \def\@examplecode@do{\expandafter\@examplecode@handlespecialtoken\expandafter\ExamplecodeProcessEndGroup\string}% + \else\ifcat \noexpand\@examplecode@nexttoken $% catcode 3 + \def\@examplecode@do{\@examplecode@handlemathshift}% + \else\ifcat \noexpand\@examplecode@nexttoken &% catcode 4 + \def\@examplecode@do{\@examplecode@handlespecialtoken\ExamplecodeProcessAlignmentTab}% + \else\ifx \@examplecode@nexttoken \EolOther% catcode 5 + \@examplecode@endcomment + \def\@examplecode@do##1{% + \ExamplecodeProcessEndOfLine + \@examplecode@state@gobbleindent + \@examplecode@loop + }% + \else\ifcat \noexpand\@examplecode@nexttoken ##% catcode 6 + \def\@examplecode@do{\@examplecode@handleparameter}% + \else\ifcat \noexpand\@examplecode@nexttoken ^% catcode 7 + \def\@examplecode@do{\@examplecode@handlespecialtoken\ExamplecodeProcessSuperscript}% + \else\ifcat \noexpand\@examplecode@nexttoken _% catcode 8 + \def\@examplecode@do{\@examplecode@handlespecialtoken\ExamplecodeProcessSubscript}% + % catcode 9: ignored characters + % catcode 10: space, handled in \@examplecode@check@spaces + % catcode 11: letter, handled in \else + % catcode 12: other, handled in \else + \else\ifx \@examplecode@nexttoken <% + \def\@examplecode@do{\@examplecode@handlepossiblemeta}% + % catcode 13: active, handled in \@examplecode@check@ii (after \futurelet it's indistinguishable from a control sequence) + \else\ifx \@examplecode@nexttoken \PercentOther% catcode 14 + \@examplecode@state@normal + \ExamplecodeProcessBeginComment + \def\@examplecode@endcomment{\ExamplecodeProcessEndComment}% + \def\@examplecode@do{\@examplecode@handlenormaltoken}% + % catcode 15: invalid characters + \else% catcode 11, 12 + \def\@examplecode@do{\@examplecode@handlenormaltoken}% + \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi + \@examplecode@do +} +\newcommand{\@examplecode@endcomment}{} +\newcommand{\@examplecode@handlebgroup}{% + \ifcsundef{@examplecode@formatarg\@examplecode@cs}{% + \expandafter\@examplecode@handlespecialtoken\expandafter\ExamplecodeProcessBeginGroup\string + }{% + \csname @examplecode@formatarg\@examplecode@cs\endcsname + }% +} +\newcommand{\@examplecode@handlenormaltoken}[1]{% + \@examplecode@state@normal + \ifcsundef{@examplecode@formatoptarg\@examplecode@cs#1}{% + \csname @examplecode@breakafter@#1\endcsname + \ExamplecodeProcessText{#1}% + \@examplecode@loop + }{% + \csname @examplecode@formatoptarg\@examplecode@cs#1\endcsname + }% +} +\newcommand{\@examplecode@handlespecialtoken}[2]{% + \@examplecode@state@normal + #1{\string#2}% + \@examplecode@loop +} + +\newcommand{\@examplecode@handlemathshift}[1]{% + \@examplecode@math@begin + \ExamplecodeProcessMathShift{\string#1}% + \@examplecode@math@end + \@examplecode@loop +} +\newcommand{\@examplecode@math@begin}{% + \@examplecode@state@normal + \begingroup + \let\@examplecode@handlemeta=\@examplecode@handlenormaltoken + \ExamplecodeProcessBeginMath + \let\@examplecode@math@begin=\relax + \def\@examplecode@math@end{\def\@examplecode@math@end{\ExamplecodeProcessEndMath\endgroup}}% +} + +\newcommand{\@examplecode@handleparameter}[1]{% + \edef\@examplecode@parameter{\string#1}% + \@examplecode@parameterloop +} +\newcommand{\@examplecode@parameterloop}{% + \futurelet \@examplecode@nexttoken \@examplecode@parametercheck +} +\newcommand{\@examplecode@parametercheck}{% + \ifcat \noexpand\@examplecode@nexttoken ##% + \def\@examplecode@do##1{% + \edef\@examplecode@parameter{\@examplecode@parameter\string##1}% + \@examplecode@parameterloop + }% + \else\ifcat \noexpand\@examplecode@nexttoken 1% + \def\@examplecode@do##1{% + \edef\@examplecode@parameter{\@examplecode@parameter##1}% + \expandafter\ExamplecodeProcessParameter\expandafter{\@examplecode@parameter}% + \@examplecode@loop + }% + \else + \def\@examplecode@do{% + \expandafter\ExamplecodeProcessParameter\expandafter{\@examplecode@parameter}% + \@examplecode@check + }% + \fi \fi + \@examplecode@do +} + +\newcommand{\@examplecode@handlepossiblemeta}[1]{% + \def\@examplecode@tmp{#1}% + \futurelet \@examplecode@nexttoken \@examplecode@checkmeta +} +\newcommand{\@examplecode@checkmeta}{% + \ifcat \@examplecode@nexttoken a% + \def\@examplecode@do{\@examplecode@handlemeta}% + \else + \def\@examplecode@do{\@examplecode@handlenormaltoken}% + \fi + \expandafter\@examplecode@do\@examplecode@tmp +} +\def\@examplecode@handlemeta<#1>{% + \ExamplecodeProcessMeta{#1}% + \@examplecode@loop +} + +\newcommand{\@examplecode@checkend}[2]{% + \def\@examplecode@arg{#2}% + \ifx \@examplecode@arg \@examplecode@envname + \expandafter \@firstoftwo + \else + \expandafter \@secondoftwo + \fi{% + \end{#2}% + }{% + \@examplecode@state@normal + \ExamplecodeProcessCmd{#1}% + \ExamplecodeProcessBeginGroup{\{}% + \ExamplecodeProcessEnv{#2}% + \ExamplecodeProcessEndGroup{\}}% + \@examplecode@loop + }% +}% +\makeatother 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 diff --git a/macros/latex/contrib/easyfloats/doc/preamble/link.tex b/macros/latex/contrib/easyfloats/doc/preamble/link.tex new file mode 100644 index 0000000000..bd6daf7d42 --- /dev/null +++ b/macros/latex/contrib/easyfloats/doc/preamble/link.tex @@ -0,0 +1,53 @@ +% !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/. + +% Adds an abstraction layer above hyperref's \href and \hyperref commands. +% Links are defined with: +% \newurllink{<name>}{<url>} +% \newlabellink{<name>}{<label>} +% A text is turned into a link with +% \link[<name>]{<text>} +% Like in markdown the name of the link is optional. +% If it is omitted <text> is used instead. +% This has the advantage that all links can be declared in one place +% and URLs don't need to be repeated. +% Changing an external link to an internal link is easy. + +\makeatletter +\newcommand{\link@csname}[1]{link@cs@#1} + +\newcommand\newurllink{% + \begingroup + \let\do=\@makeother + \dospecials + \catcode`{=1 + \catcode`}=2 + \newurllink@do +} +\newcommand\newurllink@do[2]{% #1: name, #2: url + \endgroup + \expandafter \newcommand \csname\link@csname{#1}\endcsname{\href{#2}}% +} + +\newcommand\newlabellink[2]{% #1: name, #2: label + \expandafter \newcommand \csname\link@csname{#1}\endcsname{\hyperref[#2]}% +} + +\newcommand\link{% [#1: name], #2: displayed text + \@ifnextchar [ + {\link@do} + {\@dblarg\link@do}% +} +\def\link@do[#1]#2{% + \ifcsname\link@csname{#1}\endcsname + \csname\link@csname{#1}\endcsname{#2}% + \else + \PackageError{link}{link name `#1' undefined}{}% + \fi +} +\makeatother diff --git a/macros/latex/contrib/easyfloats/doc/preamble/macros.tex b/macros/latex/contrib/easyfloats/doc/preamble/macros.tex new file mode 100644 index 0000000000..2be2bc74cb --- /dev/null +++ b/macros/latex/contrib/easyfloats/doc/preamble/macros.tex @@ -0,0 +1,218 @@ +% !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/. + +% Defines additional macros which are not provided +% by the document class or other packages. +% +% \TikZ +% Typesets the name of the TikZ package. +% dtxdescribe defines the \tikz macro for that +% but it's wrong, the Z is not capitalized. +% +% \eTeX +% Typesets the name of eTeX. +% In standard LaTeX there are \TeX, \LaTeX and \LaTeXe. +% metalogo and dtxdescribe define more logos. +% But I have failed to find a package which provides +% the eTeX logo. +% In contrast to the other logo macros \eTeX includes a +% link to the eTeX manual on CTAN. +% +% \radioon +% draws an activated radio button +% \radiooff +% draws a deactivated radio button +% +% \DescribeHandler[<class>]{<name>} +% Typesets the handler name as a \marginpar. +% The same like all other \Describe* macros defined by dtxdescribe +% just for handlers. +% +% \handler{<name>} +% To reference a handler described with \DescribeHandler. +% +% \filename{<filename>} +% Typesets a file name in the pdf. +% +% \pkgoptn{<option>} +% Typesets a package option in the pdf. +% \key{<option>} +% Typesets a macro/environment option in the pdf. +% Usually \optn is used for both macro options and package options. +% However, I am using pgfkeys for macro options and standard LaTeX +% for package options making the two types of options quite different. +% Unlike some other packages the easyfloats package does not allow to +% pass macro options as package options. +% Therefore I like to have a better distinction between them even +% if they are formatted in the same way. +% Also, dtxdescribe defines two different macros for the description: +% \DescribeOption for package/class options and +% \DescribeKey for macro/environment options. +% So it is only consistent to have two different macros for typesetting +% macro/environment and package/class options. +% I have redefined \optn to print an error in order to avoid ambiguity. +% \val{<value>} +% typesets the value of a key. Package options don't have values. +% +% \errormessage{<message>} +% Typesets an error message in the pdf. Changes category codes so that +% control sequences and active characters do *not* need to be prefixed +% by \string. +% +% \sectionname{<title>} +% Format the name of a section of a different document which I am referring to. +% For sections of this document use \cref or \Cref instead. +% +% \newlicense{<name>}{<display text>}{<url>} +% \license{<name>} +% Define a license in the preamble with displayed name and URL with \newlicense +% and use it in the document with \license. +% Changes catcodes for the <url> only so that special characters +% can be used there without worrying (except for curly braces). +% +% \formatcode{<texcode>} +% Formats inline code. +% It does not change catcodes or performs any other kind of magic. +% <texcode> is executed as TeX code. + +\usepackage{relsize} + + +\makeatletter +\newcommand{\version}{\newcommand\theversion} +\newcommand{\package}{\newcommand\thepackage} +\newcommand{\thedate}{\@date} +\AtBeginDocument{% + \let\thedate=\@date + \ifundef{\theversion}{}{\appto\@date{\strut\\\strut\thepackage~\theversion}}% +} +\makeatother + +\makeatletter +\newcommand\parskipintoc[1]{% + \def\@starttoc##1{% + \begingroup + \makeatletter + \parskip=#1\relax + \@input{\jobname.##1}% + \if@filesw + \expandafter\newwrite\csname tf@##1\endcsname + \immediate\openout\csname tf@##1\endcsname \jobname.##1\relax + \fi + \@nobreakfalse + \endgroup + } +} +\makeatother +\parskipintoc{0pt plus .6em minus 1pt} + +\newcommand{\bigpar}{\par{\centering*~*~*\pagebreak[3]\par}} +\newcommand{\bigparinlist}{\par\medskip\pagebreak[3]\par} +\let\OriginalItemize=\itemize +\def\itemize{\OriginalItemize\let\bigpar\bigparinlist} + +\newcommand{\eTeX}{\texorpdfstring{\href{https://ctan.org/pkg/etex}{\ensuremath{\varepsilon}-\TeX}}{eTeX}} +\newcommand{\TikZ}{Ti\emph{k}Z} + +\newcommand{\radioon}{\radio{\fill circle (.45);}} +\newcommand{\radiooff}{\radio\relax} +\newcommand{\radio}[1]{\tikz[x=1ex,y=1ex,baseline=-.6ex,very thin]{\draw circle (.75);#1}} + + +\newcommand{\filename}{\emph} + +\newcommand{\pkgoptn}{\optn} +\newcommand{\key}{\optn} +\let\pkgoptn=\optn +\let\key=\optn +\let\handler=\optn +% Do *not* add the optional argument, otherwise \renewcommand would not only redefine \optn +% but also two internal macros which \pkgoptn and \key depend on. +\renewcommand{\optn}[1]{\PackageError{macros}{\string\optn\space is ambiguous}{Please use \string\key\space for macro/environment options and \string\pkgoptn\space for package/class options.}} + +\newcommand{\val}[1]{#1} + +\makeatletter +\newcommand*{\DescribeHandler}[2][]{\DTXD@margintagindex{#1}{#2}{Handler}{handler}{usage}} + +\newcommand{\errormessage}{% + \begingroup + \let\do=\@makeother + \dospecials + \@makeother` + \catcode`{=1 + \catcode`}=2 + \catcode` =10 + \do@errormessage +} +\newcommand{\do@errormessage}[1]{% + \endgroup + \enquote{\texttt{#1}}% +} +\makeatother + + +\newrobustcmd{\sectionname}[1]{{\let\formatcode\formatcodeinsection\emph{#1}}} + + +\makeatletter +\newcommand{\license@csname}[1]{license@cs@#1} +\newcommand{\FormatLicense}{\emph} + +\newcommand{\newlicense}[2]{% + \begingroup + \let\do=\@makeother + \dospecials + \catcode`{=1 + \catcode`}=2 + \newlicense@do{#1}{#2}% +} +\newcommand{\newlicense@do}[3]{% #1: name, #2: display text, #3: url + \endgroup + \expandafter \newcommand \csname\license@csname{#1}\endcsname{\href{#3}{\FormatLicense{#2}}}% +} + +\newcommand{\license}[1]{% #1: name + \ifcsname\license@csname{#1}\endcsname + \csname\license@csname{#1}\endcsname + \else + \PackageError{macros}{license name `#1' undefined}{}% + \fi +} + + +% ---------- \formatcode --------- + +\newcommand{\formatcode}[1]{{\ttfamily\smaller[.5]\fboxsep=.5pt\colorbox{codebackground!50}{\vphantom\}\colorlet{linkcolor}{codelinkcolor}#1}}} +\newcommand{\formatcodeinsection}[1]{{\ttfamily#1}} +\newcommand{\formatcodeinmarginpar}[1]{\formatcodeinsection{\small#1}} + +% patch section commands and toc to use \formatcodeinsection instead of \formatcode +\newcommand{\patchsection}[3]{% #1: command to be patched, #2: code to be inserted before, #3 code to be appended + \expandafter\let\csname @@originalsec@\string#1\endcsname #1% + \expandafter\def\csname @@sec@\string#1\endcsname##1##2{#2\csname @@originalsec@\string#1\endcsname##1{##2}#3}% + \def#1##1##{\csname @@sec@\string#1\endcsname{##1}}% +} +\@tfor \@sec@cmd :=\section\subsection\subsubsection \do{% + \expandafter\expandafter\expandafter\patchsection\expandafter\@sec@cmd\expandafter{% + \csname My\expandafter\string\@sec@cmd Hook\endcsname + \let\@original@formatcode=\formatcode + \let\formatcode=\formatcodeinsection + }{% + \let\formatcode=\@original@formatcode + }% +} +\let\@@original@toc=\tableofcontents +\def\tableofcontents{{\let\formatcode\formatcodeinsection\DisableLinks\@@original@toc}} + +% patch \marginpar to use \formatcodeinmarginpar instead of \formatcode +\let\@@original@marginpar=\marginpar +\renewcommand\marginpar[1]{\@@original@marginpar{\let\formatcode=\formatcodeinmarginpar#1}} + + +\makeatother diff --git a/macros/latex/contrib/easyfloats/doc/preamble/markdown.tex b/macros/latex/contrib/easyfloats/doc/preamble/markdown.tex new file mode 100644 index 0000000000..44662c79aa --- /dev/null +++ b/macros/latex/contrib/easyfloats/doc/preamble/markdown.tex @@ -0,0 +1,153 @@ +% !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/. + +% Allows markdown like syntax: +% *emph* +% `code` +% +% If `<code>` is used in an argument <code> cannot contain: +% - comment characters (percent sign) +% - unbalanced curly braces +% +% If `<code>` is used in a context where fragile commands break +% (e.g. an entry of the table of contents or list of figures): +% - control sequences and active characters *after* the first token +% must be preceded by \string or \protect +% +% If `<code>` is used in a pdf string (e.g. in \section): +% - control sequences *after* the first token must be preceded by \cmd +% - active characters *after* the first token must be preceded by \string +% - curly braces *after* the first token must be escaped or preceded by \string +% +% If you add prefixes like `\string` or `\cmd` in a normal execution context +% they will (of course) be treated as code to be displayed. +% Therefore it may be necessary to pass different code for these three cases: +% \section[\texorpdfstring +% {`\emph{page\string~42}`} +% {`\emph\{page\string~42\}`}] +% {`\emph{page~42}`} +% +% Warning: \section uses \write without \immediate. +% If the definition of ` is different where it is written +% e.g. if the next page break is inside of a minted environment +% you will get into trouble. +% +% Warning: With * being an active character you cannot just +% use starred versions of environments. +% \starred expands to a * with catcode other: +% \begin{examplecode\starred} +% <code> +% \end{examplecode\starred} +% I am redefining \@ifstar to recognize active * as well. +% So starred commands can be used usual. +% +% Warning: This should be loaded last so that the +% category changing code is appended to the hook last. +% Otherwise there is trouble with minted. +% +% depends on +% \LinkKeyword{<keywordtype>}{<keyword>}<formatmacro>{<text>} +% from preamble/keydoc.tex + +\usepackage{etoolbox} + +\newcommand{\starred}{*} + +\providecommand{\mintinline}[1]{\verb}%} + +\makeatletter +% An alternative version of \@ifstar which also recognizes an active star. +% I am not changing \@ifstar here because the active * is defined in \AtBeginDocument. +% So in the preamble \newcommand would check if the next token is an undefined control sequence token. +% If it was it would be discarded and it would try to define the next token. +\let\@markdown@original@ifstar=\@ifstar +\catcode`*=\active +\def\@markdown@ifstar#1#2{% + \@markdown@original@ifstar + {#1}% + {% + \@ifnextchar*% + {\@firstoftwo{#1}}% + {#2}% + }% +} +\@makeother* + +\protected\def\IfProtectedContextGobble#1{\ifx\@thirdofthree#1\relax\else#1\fi} +\newcommand\IfUnprotectedContext{% + \IfProtectedContextGobble\@thirdofthree + \@firstoftwo +} + +\catcode``=\active +\newcommand\MarkdownVerb{% + \begingroup + \@examplecode@setcatcodes + \catcode\string``=\active + \futurelet \@MarkdownVerb@nexttoken \@MarkdownVerb@do +} +\long\def\@MarkdownVerb@do#1`{% + \IfKeywordUndefined{}{\detokenize{#1}}{% + \ifcat \noexpand\@MarkdownVerb@nexttoken a% + \xckey`#1`% + \else + \xc`#1`% + \fi + }{% + \catcode\string` =10 + \catcode\string`\^^M=9 + \def\do{\LinkKeyword{}{\detokenize{#1}}\@firstofone\@firstofone}% + \scantokens{\appto\do{{#1}}}% + \do + }% + \endgroup +} +\def\StringifyMarkdownVerb#1`{\string#1\noexpand`} +\def\PdfStringifyMarkdownVerb#1#2`{% + \ifcat\relax\noexpand#1\relax + \cmd#1% + \else + \string#1% + \fi + \detokenize{#2}% +} +\@makeother` + +\write\@auxout{\string\catcode\string\string``=\active} + +% \AfterEndPreamble is important when used with minted +\AfterEndPreamble{% + \catcode`*=\active + \appto\dospecials{\do\*}% + \scantokens{\def\ActiveAsterisc{*}}% + \edef\do{\def\expandonce\ActiveAsterisc##1\expandonce\ActiveAsterisc{\noexpand\emph{##1}}}% + \do + \let\@ifstar=\@markdown@ifstar + % + \catcode``=\active + %% If I add ` to \dospecials \mintinline will change it to catcode other + %% therefore not finding the active ` which marks the end resulting in + %% ! Paragraph ended before \minted@inline@ii was complete. + %% I could change the definition of \mintinline to expect an other ` + %% but that would fail when using `...` inside of an argument. + %% Whether ` is contained in \dospecials or not does not seem to bother \verb. + %\appto\dospecials{\do\`}% + \scantokens{% + \def`{% + \texorpdfstring{% + \IfUnprotectedContext% + {\MarkdownVerb} + {\noexpand`\StringifyMarkdownVerb}% + }{% + \PdfStringifyMarkdownVerb + }% + }% + }% +} + +\makeatother diff --git a/macros/latex/contrib/easyfloats/doc/preamble/pdfstring.tex b/macros/latex/contrib/easyfloats/doc/preamble/pdfstring.tex new file mode 100644 index 0000000000..0a94b3d720 --- /dev/null +++ b/macros/latex/contrib/easyfloats/doc/preamble/pdfstring.tex @@ -0,0 +1,35 @@ +% !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/. + +% Redefines \cmd so that it can be used in a pdf string, +% e.g. in \section{...}. +% Please note that additionally to the restrictions +% named in the ltxdoc documentation you cannot use \cmd{\ }. +% That is a bug in ltxdoc and unrelated to pdf strings. +% +% This must be loaded last, after all other modifications +% to the \cmd macro. + +\let\PdfstringOriginalCmd=\cmd +\renewcommand{\cmd}[1]{% + \texorpdfstring + {\PdfstringOriginalCmd{#1}} + {\expandafter\PdfstringCmd\string#1\relax}% +} + +\def\PdfstringCmd#1#2#3\relax{% + \textbackslash + \ifnum\noexpand`\\=\noexpand`#2 + \textbackslash + \else\ifnum\noexpand`\%=\noexpand`#2 + \%% + \else + #2% + \fi\fi + #3% +} |