summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/commutative-diagrams
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-06-06 21:11:51 +0000
committerKarl Berry <karl@freefriends.org>2020-06-06 21:11:51 +0000
commit204a15684f2ee547b4b0816480b87b3c30d3ef6f (patch)
tree34c8f919e87413a026b3718c985735de7368f19c /Master/texmf-dist/tex/generic/commutative-diagrams
parent632dd1c4a26f2687cefe49e59c2071c4f7b2c5ee (diff)
commutative-diagrams (6jun20)
git-svn-id: svn://tug.org/texlive/trunk@55438 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/commutative-diagrams')
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.bapto.code.tex56
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.code.tex47
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.diorthono.code.tex78
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ektropi.code.tex66
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.katharizo.code.tex136
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.koinos.code.tex168
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mandyas.code.tex319
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mitra.code.tex207
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ozos.code.tex58
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ramma.code.tex158
-rw-r--r--Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.velos.code.tex280
11 files changed, 1573 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.bapto.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.bapto.code.tex
new file mode 100644
index 00000000000..e417dc7f08e
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.bapto.code.tex
@@ -0,0 +1,56 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% βάπτω • (báptō)
+% 1. I dip, submerge
+% 2. I dye, colour
+% 3. I baptise
+
+% Bapto is a node labeling mechanism.
+% It allows non-invasive relabeling and preprocessing.
+
+% ,-- input input hook
+% `-> controller --. the controller conditionally
+% ,---[overwrite]--' (depending upon the given overwriting behaviour)
+% `-> trigger -----. calls the trigger
+% ,--- ??? <-------' either short the keys or do preprocessing here
+% `-> dispatcher --. the dispatcher conditionally
+% ,---[overwrite]--| (depending upon the given overwriting behaviour)
+% `-> (name|alias) | assigns the label
+% output <-----' output hook
+
+%==[ input ]====================================================================
+
+\pgfqkeys{/bapto/input}{
+ .forward to=/bapto/controller
+}
+
+%==[ controller/dispatcher ]====================================================
+
+\pgfqkeys{/bapto/overwrite}{.is choice,
+ false/.style={/bapto/controller/.code={\def\kDTmp{##1}\ifx\kDTmp\empty\else
+ \tikz@fig@name\ifx\tikz@fig@name\empty
+ \pgfqkeys{/bapto}{trigger={##1}}\fi\fi},
+ /bapto/dispatcher/.code={\pgfqkeys{/tikz}{name=##1}%
+ \pgfqkeys{/bapto}{output=##1}}},
+ alias/.style={/bapto/controller/.code={\def\kDTmp{##1}\ifx\kDTmp\empty\else
+ \pgfqkeys{/bapto}{trigger={##1}}\fi},
+ /bapto/dispatcher/.code={\pgfqkeys{/tikz}{alias=##1}%
+ \pgfqkeys{/bapto}{output=##1}}},
+ true/.style= {/bapto/controller/.code={\def\kDTmp{##1}\ifx\kDTmp\empty\else
+ \pgfqkeys{/bapto}{trigger={##1}}\fi},
+ /bapto/dispatcher/.code={\pgfqkeys{/tikz}{name=##1}%
+ \pgfqkeys{/bapto}{output=##1}}},
+ false, % default is no name overwriting and no aliasing
+}
+
+%==[ output ]===================================================================
+
+\pgfqkeys{/bapto/output}{
+ .code={}
+}
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.code.tex
new file mode 100644
index 00000000000..eabf14dd069
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.code.tex
@@ -0,0 +1,47 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+%==[ dependencies graph ]=======================================================
+
+% NOTE: arrow notation means targets require sources.
+% TODO: does mandyas depend upon ramma?
+
+%====[ TikZ/pgf standard libraries ]===============%
+% %
+% calc ------------------------------------. %
+% matrix -------------------------------. | %
+% | | %
+%====[ Volatile layer: TikZ bugfixes ]=======|==|==%
+% | | %
+% commutative-diagrams.diorthono | | %
+% | | %
+%====[ Inner layer: base infrastructure ]====|==|==%
+% | | %
+% ,-> commutative-diagrams.ektropi ------. | | %
+% | commutative-diagrams.bapto --------| | | %
+% | commutative-diagrams.katharizo ----| | | %
+% `-- commutative-diagrams.koinos ----. | | | %
+% ,---' | | | | %
+%==|=[ Middle layer: custom parsers ]==|==|==|==|==%
+% | | | | | %
+% |-- commutative-diagrams.mitra <----+--|--' | %
+% |-- commutative-diagrams.ozos <-----| | | %
+% |-- commutative-diagrams.velos <----' | | %
+% | | | %
+%==|=[ Outer layer: user interface ]======|=====|==%
+% | | | %
+% `-> commutative-diagrams.ramma <-------' | %
+% commutative-diagrams.mandyas <-----------' %
+% %
+%==================================================%
+
+% Given the graph above, these suffice to encompass the whole library:
+
+\usetikzlibrary[commutative-diagrams.diorthono]
+\usetikzlibrary[commutative-diagrams.ramma]
+\usetikzlibrary[commutative-diagrams.mandyas]
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.diorthono.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.diorthono.code.tex
new file mode 100644
index 00000000000..4a79abdbccb
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.diorthono.code.tex
@@ -0,0 +1,78 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% διορθώνω • (diorthóno)
+% 1. I correct
+% 2. I mend
+% 3. I repair
+
+% Diorthono is a collection of bugfixes.
+
+% Save catcode of @ to restore it at EOF.
+\edef\kDAct{\catcode`@=\the\catcode`@\relax}
+\catcode`@=11\relax
+
+% The following code patches \pgfpathcurvebetweentime.
+% See http://tex.stackexchange.com/a/271024/82186 for reference.
+% Original fix by Mark Wibrow.
+\def\pgf@@pathcurvebetweentime#1#2#3#4#5#6{%
+ \pgfmathparse{#1}%
+ \let\pgf@time@s=\pgfmathresult%
+ \pgfmathparse{#2}%
+ \let\pgf@time@t=\pgfmathresult%
+ \ifdim\pgf@time@s pt>\pgf@time@t pt\relax%
+ \pgfmathsetmacro\pgf@time@s{1-#1}%
+ \pgfmathsetmacro\pgf@time@t{1-#2}%
+ \pgf@@@pathcurvebetweentime{#6}{#5}{#4}{#3}%
+ \else%
+ \pgf@@@pathcurvebetweentime{#3}{#4}{#5}{#6}%
+ \fi%
+}
+\def\pgf@@@pathcurvebetweentime#1#2#3#4{%
+\begingroup%
+ % Get the curve Q from curve P for time 0 to t
+ \pgfextract@process\Pa{#1}%
+ \pgfextract@process\Pb{#2}%
+ \pgfextract@process\Pc{#3}%
+ \pgfextract@process\Pd{#4}%
+ % Qa = Pa
+ \pgfextract@process\Qa{\Pa}%
+ % Qb = Pa + t*(Pb-Pa).
+ \pgfextract@process\Qb{%
+ \pgfpointadd{\Pa}{\pgfpointscale{\pgf@time@t}{\pgfpointdiff{\Pa}{\Pb}}}%
+ }%
+ % Qc = Qb + t*((Pb + t*(Pc-Pb)) - Qb)
+ \pgfextract@process\Qc{%
+ \pgfpointadd{\Qb}{\pgfpointscale{\pgf@time@t}{\pgfpointdiff{\Qb}{\pgfpointadd{\Pb}{\pgfpointscale{\pgf@time@t}{\pgfpointdiff{\Pb}{\Pc}}}}}}%
+ }%
+ % Qd = (1-t)^3*Pa + 3*t(1-t)^2*Pb + 3*t^2(1-t)*Pc + t^3*Pd.
+ \pgfextract@process\Qd{\pgfpointcurveattime{\pgf@time@t}{\Pa}{\Pb}{\Pc}{\Pd}}%
+ %
+ % Now get the curve R from the reversed curve Q for time 0 to 1-s/t
+ \pgfmathdivide@{\pgf@time@s}{\pgf@time@t}%
+ \pgfmathadd@{-\pgfmathresult}{1.0}%
+ \let\pgf@time@s=\pgfmathresult%
+ % Rd = Qd
+ \pgfextract@process\Rd{\Qd}%
+ % Rc = Qd + s*(Qc-Qd).
+ \pgfextract@process\Rc{%
+ \pgfpointadd{\Qd}{\pgfpointscale{\pgf@time@s}{\pgfpointdiff{\Qd}{\Qc}}}%
+ }%
+ % Rb = Rc + s*((Qc + s*(Qb-Qc)) - Rc)
+ \pgfextract@process\Rb{%
+ \pgfpointadd{\Rc}{\pgfpointscale{\pgf@time@s}{\pgfpointdiff{\Rc}{\pgfpointadd{\Qc}{\pgfpointscale{\pgf@time@s}{\pgfpointdiff{\Qc}{\Qb}}}}}}%
+ }%
+ % Ra = (1-s)^3*Qd + 3*s(1-s)^2*Qc + 3*s^2(1-s)*Qb + s^3*Qa.
+ \pgfextract@process\Ra{\pgfpointcurveattime{\pgf@time@s}{\Qd}{\Qc}{\Qb}{\Qa}}%
+ \ifpgf@ignoremoveto\else\pgfpathmoveto{\Ra}\fi%
+ \pgfpathcurveto{\Rb}{\Rc}{\Rd}%
+\endgroup%
+}
+
+% Restore catcode of @.
+\kDAct
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ektropi.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ektropi.code.tex
new file mode 100644
index 00000000000..3a698436c41
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ektropi.code.tex
@@ -0,0 +1,66 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% εκτροπή • (ektropí)
+% 1. diversion
+% 2. deflection
+% 3. aberration
+
+% Ektropi is a mechanism to hijack the /tikz/.unknown handler.
+% It allows the addition of maximum priority paths in the key finding algorithm.
+% The diversions are globally scoped, cumulative and removable.
+
+\usetikzlibrary{commutative-diagrams.koinos}
+
+\kDStoreCatcodeOf @
+\catcode`@=11
+
+%==[ handler restoring procedure ]==============================================
+
+% The default handler's code is backed up as a token list at load time.
+% NOTE: this has strong implications on loading order!
+
+\newtoks\kDEktropiDefaultToksBackup
+
+\expandafter\expandafter
+\expandafter\kDEktropiDefaultToksBackup
+\expandafter\expandafter
+\expandafter{\csname pgfk@/tikz/.unknown/.@body\endcsname}
+
+\def\kDEktropiRestore{
+ % Restore handler body.
+ \def\kDAct{\pgfkeyssetvalue{/tikz/.unknown/.@body}}
+ \expandafter\kDAct\expandafter{\the\kDEktropiDefaultToksBackup}
+ % Restore handler macro.
+ % NOTE: #s are doubled since we're inside \kDAct helper.
+ \def\kDAct{\long\def\kDAct####1\pgfeov}
+ \expandafter\kDAct\expandafter{\the\kDEktropiDefaultToksBackup}
+ \pgfkeyslet{/tikz/.unknown/.@cmd}\kDAct
+}
+
+% This key is the user interface. Self explanatory.
+\pgfkeys{/ektropi/restore/.code={\kDEktropiRestore}}
+
+%==[ handler hacking procedure ]================================================
+
+% This key is the user interface. It wraps the /tikz/.unknown handler code
+% with a conditional that executes it only if the unknown key retrieval
+% fails inside the path passed to /ektropi/add.
+\pgfkeys{/ektropi/add/.style={
+ /tikz/.unknown/.add code=
+ {
+ \let\tikz@key\pgfkeyscurrentname
+ \pgfkeys{#1/\tikz@key/.try={##1}}
+ \ifpgfkeyssuccess\else
+ }{
+ \fi
+ }
+ }
+}
+
+\kDRestoreCatcodeOf @
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.katharizo.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.katharizo.code.tex
new file mode 100644
index 00000000000..ef3c4ea0fcc
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.katharizo.code.tex
@@ -0,0 +1,136 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% καθαρίζω • (katharízo)
+% 1. clean, wash
+% 2. peel, descale
+% 3. (slang) kill
+
+% Katharizo is a detokenization/sanitation mechanism.
+% It produces "safe" strings from tokens.
+
+% ,-- input input hook
+% `-> expander ---. performs expansion according to
+% ,---[expand]----' macro expansion configuration
+% `-> expanded ---. pre-sanitation hook
+% ,-- sanitizer <-' performs detokenization and sanitation according to
+% `---[replace]---. character replacement configuration
+% ,-- sanitized <-' pre-output hook
+% `-> output output hook
+
+%==[ input stage ]==============================================================
+
+\pgfqkeys{/katharizo/input}{
+ .forward to=/katharizo/expander
+}
+
+%==[ expansion stage ]==========================================================
+
+\pgfqkeys{/katharizo/expand}{.is choice,
+ once/.style={/katharizo/expander/.style={/katharizo/expanded/.expand once={##1}}},
+ full/.style={/katharizo/expander/.style={/katharizo/expanded/.expanded={##1}}},
+ none/.style={/katharizo/expander/.style={/katharizo/expanded={##1}}},
+ none % default is no expansion
+}
+
+\pgfqkeys{/katharizo/expanded}{
+ .forward to=/katharizo/sanitizer
+}
+
+%==[ sanitation stage ]=========================================================
+
+\pgfqkeys{/katharizo}{
+ replace charcode/.code args={#1 with #2}{%
+ % TODO: would a \string be of any use? or at least a stringification?
+ \pgfkeys{/katharizo/replacements/characters/#1/.initial={#2}}%
+ },
+ remove charcode/.style={/katharizo/replace charcode={{#1} with {}}},
+ remove charcodes/.style args={#1}{%
+ /katharizo/remove charcodes loop={#1 \kD},
+ },
+ remove charcodes loop/.code args={#1 #2\kD}{%
+ % \message{|||#1|#2|||}
+ \ifx\relax#1\else\pgfkeys{/katharizo/remove charcode={#1}}\fi
+ \ifx\relax#2\else\pgfkeys{/katharizo/remove charcodes loop={#2\kD}}\fi
+ },
+ replace character/.code args={#1 with #2}{%
+ \edef\kDFoo{\number`#1}% TODO: can I inline this?
+ % TODO: would a \string be of any use? or at least a stringification?
+ \pgfkeys{/katharizo/replacements/characters/\kDFoo/.initial={#2}}%
+ },
+ remove character/.style={/katharizo/replace character={{#1} with {}}},
+ remove characters/.code args={#1#2}{%
+ \ifx\relax#1\else\pgfkeys{/katharizo/remove character={#1}}\fi
+ \ifx\relax#2\else\pgfkeys{/katharizo/remove characters={#2}}\fi
+ },
+ remove characters={(),.:},
+ remove charcode=92,% \ backslash
+}
+
+\pgfqkeys{/katharizo}{
+ sanitizer/.code={
+ % TODO: token replacement routine? Would that be useful?
+ \kDKatharizoStringify#1\kD
+ \expandafter\kDKatharizoSanitize\the\kDKatharizoStringified\kD
+ \pgfkeysalso{/katharizo/sanitized/.expanded=\the\kDKatharizoSanitized}
+ % \message{^^J:::\the\kDKatharizoSanitized:::^^J}
+ }
+}
+
+\pgfqkeys{/katharizo/sanitized}{
+ .forward to=/katharizo/output
+}
+
+%==[ output stage ]=============================================================
+
+% NOTE: this must be defined/hooked before calling input
+\pgfqkeys{/katharizo/output}{
+ .code={}
+}
+
+\newtoks\kDKatharizoStringified
+
+\def\kDKatharizoStringify#1\kD{
+ \def\kDFoo{#1}
+ \edef\kDFoo{\meaning\kDFoo}
+ \def\kDAct##1:->##2\kD{##2}
+ \edef\kDFoo{\expandafter\kDAct\kDFoo\kD}
+ \kDKatharizoStringified\expandafter{\kDFoo}
+}
+
+\newtoks\kDKatharizoSanitized
+
+\def\kDKatharizoSanitize#1\kD{
+ \pgfkeysifdefined{/katharizo/replacements/characters/32}%
+ {\edef\kDKatharizoSSpace{\pgfkeysvalueof{/katharizo/replacements/characters/32}}}%
+ {\edef\kDKatharizoSSpace{\space}}%
+ \def\kDKatharizoSAppendSpace
+ {\edef\kDAct{\noexpand\kDKatharizoSanitized={\the\kDKatharizoSanitized\kDKatharizoSSpace}}\kDAct}
+ \kDKatharizoSanitized={}
+ \kDKatharizoSString#1 \kD}% NOTE: the whitespace is a mandatory string terminator
+
+\def\kDKatharizoSString#1 #2\kD{%
+ \ifx\relax#1\else % if string head word is not empty
+ \kDKatharizoSWord#1\kD % parse string head word
+ \if#2\space\else % if string tail is not the space terminator
+ \ifx\relax#2\else % if string tail is not empty
+ \kDKatharizoSAppendSpace\fi\fi\fi % append space substitute to output
+ \ifx\relax#2\else % if string tail is not empty
+ \kDKatharizoSString#2\kD\fi} % recurse on string tail
+
+\def\kDKatharizoSWord#1#2\kD{%
+ \kDKatharizoSCharacter#1\kD % parse word head character
+ \ifx\relax#2\else % if word tail is not empty
+ \kDKatharizoSWord#2\kD\fi} % recurse on word tail
+
+\def\kDKatharizoSCharacter#1\kD{%
+ \pgfkeysifdefined{/katharizo/replacements/characters/\number`#1}%
+ {\edef\kDFoo{\pgfkeysvalueof{/katharizo/replacements/characters/\number`#1}}}%
+ {\edef\kDFoo{#1}}%
+ \edef\kDAct{\noexpand\kDKatharizoSanitized={\the\kDKatharizoSanitized\kDFoo}}%
+ \kDAct}
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.koinos.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.koinos.code.tex
new file mode 100644
index 00000000000..c2b378f38a2
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.koinos.code.tex
@@ -0,0 +1,168 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% κοινός • (koinós)
+% 1. shared
+% 2. common
+% 3. public
+
+% Koinos implements or aliases commonplace macros.
+
+%==[ catcode manipulation ]=====================================================
+
+\newcount\kDEscapecharCounter
+
+\def\kDEscapecharDisable{\kDEscapecharCounter\escapechar \escapechar=-1}
+\def\kDEscapecharEnable{\escapechar\kDEscapecharCounter}
+
+\def\kDStoreCatcodeOf#1%
+ {\kDEscapecharDisable
+ \expandafter\edef\csname kDRestoreCatcodeOf\string#1\endcsname{\catcode`\string#1=\the\catcode\expandafter`\string#1}%
+ % NOTE: setting a default catcode is disabled; might come in handy someday, though.
+ % \catcode\expandafter`\string#1=12\relax
+ \kDEscapecharEnable}
+
+\def\kDRestoreCatcodeOf#1%
+ {\kDEscapecharDisable
+ \csname kDRestoreCatcodeOf\string#1\endcsname
+ \kDEscapecharEnable}
+
+%==[ forward checks and gobbling ]==============================================
+
+% This macro is the blank space token.
+\bgroup
+\def\:{\global\let\kDBlankSpace= }\:
+\egroup
+
+% Save catcode of @ to restore it later.
+\kDStoreCatcodeOf @
+\catcode`@=11\relax
+
+% The next two macros both implement token gobbling.
+
+% This "hard" version gobbles any token, ignoring whitespace.
+\let\kDGobbleHardTok\pgfutil@gobble
+
+% This "soft" version gobbles only whitespace.
+% NOTE: this is just the identity macro. Fun fact.
+\def\kDGobbleSoftTok#1{#1}
+
+% The next two macros both implement the following logical condition:
+% if next token is #1 then #2 else #3
+
+% This "hard" version ignores whitespace.
+\let\kDIfNextHardCh\pgfutil@ifnextchar
+
+% This "soft" version does not ignore whitespace.
+\long\def\kDIfNextSoftCh#1#2#3{%
+ \let\kDINCToken= #1% <- MEMO: this space is crucial
+ \def\kDINCTrue{#2}\def\kDINCFalse{#3}%
+ \futurelet\kDINCTok\kDINC}
+
+\def\kDINC{\ifx\kDINCTok\kDINCToken\let\kDINCFalse\kDINCTrue\fi\kDINCFalse}
+
+% Restore catcode of @.
+\kDRestoreCatcodeOf @
+
+%==[ token lists parsing and manipulation ]=====================================
+
+% This macro appends token list #1 to token list #2.
+\def\kDAppend#1#2{\edef\kDAct{\noexpand#2={\the#2\the#1}}\kDAct}
+
+% This macro tokenizes the stream into \kDOptTok
+% until a group preceeding a ';' character is found;
+% then it puts the group into \kDGrpTok and gobbles the ';'.
+\def\kDFetchOptAndGrpThen#1%
+ {\kDOptTok={}\kDGrpTok={}\kDFetchTilGrpThen{#1}}
+
+\newtoks\kDOptTok
+\newtoks\kDGrpTok
+
+\def\kDFetchGrpThen#1#2{%
+ \def\kDExit{#1}%
+ \def\kDLoop{\kDFetchTilGrpThen{#1}}%
+ \kDTmpTok={{#2}}%
+ \kDIfNextHardCh;
+ {\kDGrpTok\the\kDTmpTok\expandafter\kDExit\kDGobbleHardTok}
+ {\kDAppend\kDTmpTok\kDOptTok\kDLoop}}
+
+\newtoks\kDTmpTok
+
+\def\kDFetchTilGrpThen#1#2#{%
+ \kDTmpTok={#2}%
+ \kDAppend\kDTmpTok\kDOptTok
+ \kDFetchGrpThen{#1}}
+
+% This macro removes trailing whitespace from token list #1.
+\def\kDTrimTrailingSpace#1{%
+ \kDDetectTrailingSpace#1
+ \ifkDDTSHasTrail
+ \def\kDRTS##1 \kD{#1={##1}}%
+ \edef\kDRTSAct{\noexpand\kDRTS\the#1\noexpand\kD}
+ \kDRTSAct
+ \fi}
+
+\def\kDDetectTrailingSpace#1{%
+ \kDDTSPrevSpacefalse
+ \edef\kDAct{\noexpand\kDDTSGob\the#1\noexpand\kD}%
+ \kDAct}
+
+\newif\ifkDDTSHasTrail
+
+\def\kDDTSGob%
+ {\kDIfNextSoftCh\kD
+ {\message{A}\ifkDDTSPrevSpace\kDDTSHasTrailtrue\else\kDDTSHasTrailfalse\fi\kDGobbleHardTok}
+ {\message{B}\kDIfNextSoftCh\kDBlankSpace
+ {\message{Y}\kDDTSPrevSpacetrue\expandafter\kDDTSGob\kDGobbleSoftTok}
+ {\message{N}\kDDTSPrevSpacefalse\expandafter\kDDTSGob\kDGobbleHardTok}}}
+
+\newif\ifkDDTSPrevSpace
+
+% This macro removes leading whitespace from token list #1.
+\def\kDTrimLeadingSpace#1{%
+ \def\kDAct##1\kD{#1={##1}}%
+ \expandafter\kDGobbleSpaceThen
+ \expandafter\kDAct\the#1\kD}
+
+\def\kDGobbleSpaceThen#1%
+ {\kDIfNextHardCh\bgroup
+ {\kDGSGroupThen#1}
+ {\kDGSOtherThen#1}}
+
+\def\kDGSGroupThen#1#2{#1{#2}}
+
+\def\kDGSOtherThen#1#2{#1#2}
+
+%==[ environment checks ]=======================================================
+
+\newif\ifConTeXt
+% Trick stolen from iftex. The second line is expanded inside the group so
+% the global scope isn't polluted by \csname defining the token.
+\begingroup\expandafter\expandafter\expandafter\endgroup\expandafter
+ \ifx\csname starttext\endcsname\relax\ConTeXtfalse\else\ConTeXttrue\fi
+
+%==[ dumping, debugging and testing ]===========================================
+
+% macros for dumping, debugging and testing
+% TODO: not sure I want to depend on these being in the sourcecode instead of
+% some external package integrated with a TeX unit testing suite.
+% I'll work in that direction.
+
+\newif\ifkDDumping
+\kDDumpingfalse
+
+\newwrite\kDDumpFile
+
+\def\kDDumpOpen%
+{\ifkDDumping\immediate\openout\kDDumpFile=\jobname.yml\fi}
+
+\def\kDDump#1%
+{\ifkDDumping\immediate\write\kDDumpFile{#1}\fi}
+
+\def\kDDumpClose%
+{\ifkDDumping\closeout\kDDumpFile\fi}
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mandyas.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mandyas.code.tex
new file mode 100644
index 00000000000..2d43ef5d556
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mandyas.code.tex
@@ -0,0 +1,319 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% μανδύας • (mandýas)
+% 1. cloak
+% 2. mantle
+% 3. dolman
+
+% Mandias defines the aesthetics aspect of the user level functionality,
+% together with some baseline configuration.
+
+\usetikzlibrary[calc]
+
+% \usetikzlibrary[decorations.pathreplacing]
+% \usetikzlibrary{decorations.pathmorphing}
+% \usetikzlibrary[decorations.markings]
+% \usetikzlibrary[arrows.meta]
+
+\pgfqkeys{/codi}{
+%==[ universal styles ]=========================================================
+ every diagram/.append style={},
+ every layout/.append style={
+ /codi/every object/.append style={shape=codi baseline centered rectangle},
+ square,
+ },
+ every object/.append style={},
+ every arrow/.append style={
+ >=stealth,
+ },
+ every label/.append style={
+ auto,
+ inner sep=0.5ex,
+ font=\everymath\expandafter{\the\everymath\scriptstyle}
+ },
+%==[ arrow styles ]=============================================================
+ /codi/arrows/.cd,
+ crossing over/clearance/.initial=0.5ex,
+ crossing over/color/.initial=white,
+ crossing over/.style={
+ /tikz/preaction={
+ -,
+ draw=\pgfkeysvalueof{/codi/arrows/crossing over/color},
+ line width=\pgfkeysvalueof{/codi/arrows/crossing over/clearance},
+ },
+ },
+ shove/.style={
+ /tikz/transform canvas={
+ /tikz/shift={($(\tikztostart)!#1!-90:(\tikztotarget)-(\tikztostart)$)}
+ }
+ },
+ slide/.style={
+ /tikz/transform canvas={
+ /tikz/shift={($(\tikztostart)!#1!0:(\tikztotarget)-(\tikztostart)$)}
+ }
+ },
+%==[ label styles ]=============================================================
+ /codi/labels/.cd,
+ mid/.style={
+ /tikz/fill=white,
+ /tikz/shape=circle,
+ /tikz/anchor=center,
+ /tikz/inner sep=.25ex
+ },
+%=[ objects styles ]============================================================
+ /codi/objects/.cd,
+ % TODO: reflect on these styles
+ % tetragonal/.style 2 args={
+ % /tikz/node distance=#2 and #1
+ % },
+ % square/.style={
+ % /codi/objects/rectangular={#1}{#1}
+ % },
+ % golden/.style={
+ % /codi/objects/rectangular={#1}{0.618*#1}
+ % },
+ % % comb/.style={
+ % % /codi/objects/rectangular={#1}{sqrt(3/4)*#1},
+ % % },
+ % % comb/.default=4em,
+ % square/.default=4em,
+ % golden/.default=4em,
+%=[ lattice styles ]============================================================
+ /codi/layouts/.cd,
+ hexagonal/.code args={#1side #2 angle #3}{
+ \pgfkeys{/codi/layouts/#1hexagonal=side {#2} angle {#3}},
+ },
+ horizontal hexagonal/.style args={side #1 angle #2}{
+ /codi/layouts/tetragonal=base {#1} height {tan(#2)*#1*0.5},
+ /tikz/every odd row/.append style={/tikz/xshift=(#1)*0.5},
+ },
+ vertical hexagonal/.style args={side #1 angle #2}{
+ /codi/layouts/tetragonal=base {tan(#2)*#1*0.5} height {#1},
+ /tikz/every odd column/.append style={/tikz/yshift=-1*(#1)*0.5},
+ },
+ hexagonal/.default=horizontal side 4.5em angle 60,
+ %
+ tetragonal/.style args={base #1 height #2}{
+ /tikz/column sep={{#1},between origins},
+ /tikz/row sep={{#2},between origins},
+ },
+ tetragonal/.default=base 4.5em height 2.8em,
+ %
+ square/.style={
+ /codi/layouts/tetragonal=base {#1} height {#1},
+ },
+ golden/.style={
+ /codi/layouts/tetragonal=base {#1} height {0.618*#1},
+ },
+ square/.default=4.5em,
+ golden/.default=4.5em,
+%=[ diagram styles ]============================================================
+ /codi/diagrams/.cd,
+ grid/.style 2 args={
+ /tikz/x={#1},
+ /tikz/y={#2},
+ /tikz/on grid,
+ },
+ metric/.style 2 args={
+ % NOTE: {1 and 1}{1} is infty-norm, unit circle is unit square
+ % NOTE: {2}{0.5} is 1-norm, circle of radius 2 is rhombus circumscribing base hexagon
+ /tikz/node distance={#1},
+ % TODO: implement control to allow for explicit units on single factor specs
+ /tikz/above left/.code={\tikz@lib@place@handle@{##1}{south east}{-1}{1}{north west}{#2}},
+ /tikz/above right/.code={\tikz@lib@place@handle@{##1}{south west}{1}{1}{north east}{#2}},
+ /tikz/below left/.code={\tikz@lib@place@handle@{##1}{north east}{-1}{-1}{south west}{#2}},
+ /tikz/below right/.code={\tikz@lib@place@handle@{##1}{north west}{1}{-1}{south east}{#2}},
+ },
+ %
+ hexagonal/.code args={#1side #2 angle #3}{
+ \pgfkeys{/codi/diagrams/#1hexagonal=side #2 angle #3}
+ },
+ horizontal hexagonal/.style args={side #1 angle #2}{
+ /codi/every layout/.append style={/codi/layouts/hexagonal=horizontal side {#1} angle {#2}},
+ /codi/diagrams/grid={#1*0.5}{#1*tan(#2)*0.5},
+ /codi/diagrams/metric={2}{0.5},
+ },
+ vertical hexagonal/.style args={side #1 angle #2}{
+ /codi/every layout/.append style={/codi/layouts/hexagonal=vertical side {#1} angle {#2}},
+ /codi/diagrams/grid={#1*tan(#2)*0.5}{#1*0.5},
+ /codi/diagrams/metric={2}{0.5},
+ },
+ hexagonal/.default=horizontal side 4.5em angle 60,
+ %
+ tetragonal/.style args={base #1 height #2}{
+ /codi/every layout/.append style={/codi/layouts/tetragonal=base {#1} height {#2}},
+ /codi/diagrams/grid={#1}{#2},
+ /codi/diagrams/metric={1 and 1}{1},
+ },
+ tetragonal/.default=base 4.5em height 2.8em,
+ %
+ square/.style={
+ /codi/every layout/.append style={/codi/layouts/square=#1},
+ /codi/diagrams/tetragonal=base {#1} height {#1},
+ },
+ golden/.style={
+ /codi/every layout/.append style={/codi/layouts/golden=#1},
+ /codi/diagrams/tetragonal=base {#1} height {0.618*#1},
+ },
+ square/.default=4.5em,
+ golden/.default=4.5em,
+}
+
+%==[ baseline centered rectangle shape ]========================================
+
+% The math formula axis height is recovered and stored as a pgf function.
+
+% NOTE: the LuaTeX version is needed just by ConTeXt
+\pgfutil@ifluatex
+ \directlua{tex.enableprimitives('kD', {'Umathaxis'})}
+ \pgfmathdeclarefunction{kD_math_formula_axis_height}{0}{%
+ \begingroup%
+ $\relax$% update fontdimens
+ % See TeX by Topic §23.5 for details.
+ \pgfmathreturn\the\kDUmathaxis\textstyle%
+ \endgroup}
+\else% if using (pdf)tex
+ \pgfmathdeclarefunction{kD_math_formula_axis_height}{0}{%
+ \begingroup%
+ $\relax$% update fontdimens
+ % See TeX by Topic §23.5 for details.
+ \pgfmathreturn\the\fontdimen22\textfont2%
+ \endgroup}
+\fi
+
+\pgfqkeys{/codi/baseline centered rectangle}{
+ center raise/.initial=kD_math_formula_axis_height
+}
+
+% Then the shape is defined by inheritance.
+
+\pgfdeclareshape{codi baseline centered rectangle} {
+ % Inherit the rectangle shape.
+ \inheritsavedanchors[from={rectangle}]
+ \inheritanchor[from={rectangle}]{base}
+ \inheritanchor[from={rectangle}]{north}
+ \inheritanchor[from={rectangle}]{south}
+ \inheritanchor[from={rectangle}]{base west}
+ \inheritanchor[from={rectangle}]{north west}
+ \inheritanchor[from={rectangle}]{south west}
+ \inheritanchor[from={rectangle}]{base east}
+ \inheritanchor[from={rectangle}]{north east}
+ \inheritanchor[from={rectangle}]{south east}
+ \inheritanchor[from={rectangle}]{mid}
+ \inheritanchor[from={rectangle}]{mid west}
+ \inheritanchor[from={rectangle}]{mid east}
+ \inheritbackgroundpath[from={rectangle}]
+ % Redefine west, center and east anchors
+ % setting their y coordinates to center raise.
+ \anchor{center}{\pgf@anchor@rectangle@center\pgfmathsetlength\pgf@y%
+ {\pgfkeysvalueof{/codi/baseline centered rectangle/center raise}}}
+ \anchor{west}{\pgf@anchor@rectangle@west\pgfmathsetlength\pgf@y%
+ {\pgfkeysvalueof{/codi/baseline centered rectangle/center raise}}}
+ \anchor{east}{\pgf@anchor@rectangle@east\pgfmathsetlength\pgf@y%
+ {\pgfkeysvalueof{/codi/baseline centered rectangle/center raise}}}
+ % Save the original anchors as alternate "real" versions.
+ \anchor{real center}{\pgf@anchor@rectangle@center}
+ \anchor{real west}{\pgf@anchor@rectangle@west}
+ \anchor{real east}{\pgf@anchor@rectangle@east}
+ % Redefine the border anchor calculation.
+ \anchorborder{%
+ % (x,y) = target
+ % let tempdima = center raise
+ \pgfmathsetlength\pgfutil@tempdima%
+ {\pgfkeysvalueof{/codi/baseline centered rectangle/center raise}}%
+ % let b = (x,y) = target
+ \pgf@xb=\pgf@x%
+ \pgf@yb=\pgf@y%
+ % let (x,y) = south west
+ \southwest%
+ % let a = (x,y) = south west
+ \pgf@xa=\pgf@x%
+ \pgf@ya=\pgf@y%
+ % let (x,y) = north east
+ \northeast%
+ % let (x,y) = (x,y) - a = north east - south west = (width, height)
+ \advance\pgf@x by-\pgf@xa%
+ \advance\pgf@y by-\pgf@ya%
+ % let c = (x,y)/2 = (width, height)/2 = (width/2, height/2)
+ \pgf@xc=.5\pgf@x%
+ \pgf@yc=.5\pgf@y%
+ % let a = a + c = south west + (width/2, height/2) = center
+ \advance\pgf@xa by\pgf@xc%
+ \advance\pgf@ya by\pgf@yc%
+ % if by = target y > 0
+ \ifdim\pgf@yb>0pt%
+ % let (x,y) = north east
+ \northeast%
+ % let cy = y = north east y
+ \pgf@yc=\pgf@y%
+ % let cy = cy - center raise = north east y - center raise
+ \advance\pgf@yc by-\pgfutil@tempdima%
+ \else%
+ % let (x,y) = south west
+ \southwest%
+ % let cy = y = - south west y
+ \pgf@yc=-\pgf@y%
+ % let cy = cy + center raise = - south west y + center raise
+ \advance\pgf@yc by\pgfutil@tempdima%
+ \fi
+ \edef\pgf@marshal{%
+ % calculate the intersection of the half line from the origin
+ \noexpand\pgfpointborderrectangle
+ % passing through target
+ {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}
+ % and the rectangle centered on the origin
+ % whose upper right corner is
+ % (width/2, +north east y - center raise) if target y > 0
+ % (width/2, -south west y + center raise) if target y < 0
+ {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
+ }%
+ % let (x,y) = the intersection
+ \pgf@process{\pgf@marshal}%
+ % let x = x + ax = width/2 + center x
+ \advance\pgf@x by\pgf@xa%
+ % let y = y + tempdima = ±(ne/sw y - center raise) + center raise
+ \advance\pgf@y by\pgfutil@tempdima%
+ % that is, y = + north east y if target y > 0
+ % y = - south west y + 2 * center raise if target y < 0
+ %
+ % NOTE: in essence, we're just compensating for the redefinition
+ % of ne/sw anchors that shifted them by cr below the real center.
+ % ┏━━━━━━┯━━━━━━┓ ╮╮
+ % ┃ │ ┃ ││ + ney - cr
+ % ╭╭ ┠──────┼──────┨ ╮│╯ y > 0
+ % - swy + cr │╰╭ ┣━━━━━━┿━━━━━━┫ ╯╯ ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
+ % ╰ ╰ ┗━━━━━━┷━━━━━━┛ y < 0
+ }%
+}%
+
+%==[ prompter ]=================================================================
+
+% This key is meant for visual assistance with the node labeling automation.
+
+\pgfqkeys{/codi}{
+ prompter label/.style={
+ /tikz/.cd,
+ inner sep=0sp,
+ font=\ttfamily\bfseries\tiny,
+ line width=1pt,
+ draw=violet,
+ fill=violet,
+ text=white,
+ overlay,
+ label anchor/.style={tikz@label@post/.append style={anchor=##1}},
+ label anchor=north east,
+ label position=south east
+ },
+ prompter pinner/.style={
+ /tikz/draw=violet,
+ /tikz/line width=1sp,
+ /tikz/label={[/codi/prompter label]:#1},
+ },
+ prompter/.style={/bapto/output/.forward to=/codi/prompter pinner}
+}
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mitra.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mitra.code.tex
new file mode 100644
index 00000000000..211ade2f4c8
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.mitra.code.tex
@@ -0,0 +1,207 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% μήτρα • (mítra)
+% 1. womb
+% 2. matrix
+% 3. mold
+
+% Mitra is an alternative parsing mechanism for TiKz matrices of nodes.
+% It couples with ozos to ensure the node contents always pass through the TikZ key.
+
+\usetikzlibrary{matrix}
+\usetikzlibrary{commutative-diagrams.koinos}
+
+%==[ TikZ/pgf layer ]===========================================================
+
+\pgfkeys{
+ /mitra/every node/.style={},
+ /mitra/every matrix/.style={
+ /tikz/matrix,
+ /tikz/cells={
+ /tikz/anchor=base
+ }
+ },
+ % NOTE: the alias key *cannot* be put along with global node styles
+ % because of execution order.
+ /mitra/matrix coordinates alias/.style={
+ /tikz/alias=\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn
+ }
+}
+
+%==[ main macro ]===============================================================
+
+\def\kDMitra
+ {\kDMitraFetchMatrixThen
+ {\kDMitraParseMatrixTableThen
+ \kDMitraOutput}}
+
+% General purpose scratch register.
+\newtoks\kDMitraTmpTok
+
+%==[ fetching routine ]=========================================================
+
+% I use the general one implemented by koinos.
+\let\kDMitraFetchMatrixThen\kDFetchOptAndGrpThen
+
+%==[ parsing routine: /table ]==================================================
+
+\newtoks\kDMitraMatOutTok
+
+\def\kDMitraParseMatrixTableThen#1{%
+ \kDMitraMatOutTok={}%
+ \expandafter\kDMitraParseTable\the\kDGrpTok\kD
+ #1}
+
+\def\kDMitraParseTable
+ {\kDMitraParseAllRowsThen\relax}
+
+\def\kDMitraParseAllRowsThen#1{%
+ \def\kDExit{#1}%
+ \kDIfNextHardCh\kD
+ {\expandafter\kDExit\kDGobbleHardTok}%
+ {\kDMitraParseOneRowThen{\kDMitraParseAllRowsThen{#1}}}}
+
+%==[ parsing routine: /table/row ]==============================================
+
+\def\kDMitraParseOneRowThen#1%
+ {\kDMitraMarkRowEndBefore
+ {\kDMitraParseAllColsThen
+ {\kDMitraParseRowEndThen
+ {#1}}}}
+
+\kDStoreCatcodeOf &
+\ifConTeXt\catcode`&=12\else\catcode`&=4\fi
+\def\kDMitraMarkRowEndBefore#1#2\\{#1#2&\kD\\}
+\kDRestoreCatcodeOf &
+
+\def\kDMitraParseAllColsThen#1{%
+ \def\kDExit{#1}%
+ \kDIfNextHardCh\kD
+ {\expandafter\kDExit\kDGobbleHardTok}%
+ {\kDMitraParseOneColThen{\kDMitraParseAllColsThen{#1}}}}
+
+\def\kDMitraParseRowEndThen#1%
+ {\kDMitraFetchRowEndThen
+ {\kDMitraPrintRowEndThen
+ {#1}}}
+
+\def\kDMitraFetchRowEndThen#1\\{\kDMitraMaybeFetchRowOptionsThen{#1}}
+
+\newtoks\kDMitraRowOptTok
+
+\def\kDMitraPrintRowEndThen#1{%
+ \edef\kDAct{\noexpand\kDMitraTmpTok={\noexpand\\\the\kDMitraRowOptTok}}%
+ \kDAct
+ \kDAppend\kDMitraTmpTok\kDMitraMatOutTok
+ #1}
+
+\def\kDMitraMaybeFetchRowOptionsThen#1{%
+ \kDMitraRowOptTok={}%
+ \kDIfNextHardCh[%
+ {\kDMitraFetchRowOptionsThen{#1}}%
+ {#1}}
+
+\def\kDMitraFetchRowOptionsThen#1[#2]{\kDMitraRowOptTok={[#2]}#1}
+
+%==[ parsing routine: /table/row/column ]=======================================
+
+\def\kDMitraParseOneColThen#1%
+ {\kDMitraParseCellThen
+ {\kDMitraParseColEndThen
+ {#1}}}
+
+\def\kDMitraParseColEndThen#1%
+ {\kDMitraMaybeFetchColOptionsThen
+ {\kDMitraMaybePrintColEndThen
+ {#1}}}
+
+\newtoks\kDMitraColOptTok
+
+\def\kDMitraMaybeFetchColOptionsThen#1{%
+ \kDMitraColOptTok={}%
+ \kDIfNextHardCh[%
+ {\kDMitraFetchColOptionsThen{#1}}%
+ {#1}}
+
+\def\kDMitraFetchColOptionsThen#1[#2]{\kDMitraColOptTok={[#2]}#1}
+
+\def\kDMitraMaybePrintColEndThen#1{%
+ \kDIfNextHardCh\kD
+ {#1}%
+ {% NOTE: we use \pgfmatrixnextcell instead of & to avoid catcode juggling
+ \edef\kDAct{\noexpand\kDMitraTmpTok={\noexpand\pgfmatrixnextcell\the\kDMitraColOptTok}}%
+ \kDAct
+ \kDAppend\kDMitraTmpTok\kDMitraMatOutTok
+ #1%
+ }}
+
+%==[ parsing routine: /table/row/column/cell ]==================================
+
+\def\kDMitraParseCellThen#1%
+ {\kDMitraMaybeFetchCellOptionsThen
+ {\kDMitraFetchCellContentThen
+ {\kDMitraPrintCellThen
+ {#1}}}}
+
+\newtoks\kDMitraCelOptTok
+
+\def\kDMitraMaybeFetchCellOptionsThen#1{%
+ \kDMitraCelOptTok={}%
+ \kDIfNextHardCh|%
+ {\kDMitraFetchCellOptionsThen{#1}}
+ {#1}}
+
+\def\kDMitraFetchCellOptionsThen#1|#2|{\kDMitraCelOptTok={#2}#1}
+
+\newtoks\kDMitraCelCntTok
+
+\kDStoreCatcodeOf &
+\ifConTeXt\catcode`&=12\else\catcode`&=4\fi
+\def\kDMitraFetchCellContentThen#1#2&{%
+ \kDMitraCelCntTok={#2}%
+ \kDTrimLeadingSpace\kDMitraCelCntTok
+ \kDTrimTrailingSpace\kDMitraCelCntTok
+ #1}
+\kDRestoreCatcodeOf &
+
+\def\kDMitraMaybeDoCellThen#1{%
+ \kDIfNextHardCh\kD
+ {#1}%
+ {\kDMitraParseOneColThen{#1}}}
+
+\def\kDMitraPrintCellThen#1{%
+ \edef\kDAct{%
+ \noexpand\kDMitraTmpTok={%
+ \noexpand\node
+ [/mitra/every node]
+ \the\kDMitraCelOptTok
+ [node contents={\the\kDMitraCelCntTok},/mitra/matrix coordinates alias];
+ \kDMitraMaybeDumpCell}}%
+ \kDAct
+ \kDAppend\kDMitraTmpTok\kDMitraMatOutTok
+ #1}
+
+%==[ dumping routine ]==========================================================
+
+\def\kDMitraMaybeDumpCell{\noexpand\pgfextra{%
+ \noexpand\kDDump{'\noexpand\the\noexpand\pgfmatrixcurrentrow-\noexpand\the\noexpand\pgfmatrixcurrentcolumn':}%
+ \noexpand\kDDump{\space\space options: '\the\kDMitraCelOptTok'}%
+ \noexpand\kDDump{\space\space content: '\the\kDMitraCelCntTok'}}}
+
+%==[ output routine ]===========================================================
+
+\def\kDMitraOutput{%
+ \edef\kDAct{%
+ \noexpand\kDMitraTmpTok={%
+ \noexpand\matrix
+ [/mitra/every matrix]%
+ \the\kDOptTok
+ {\the\kDMitraMatOutTok};}}%
+ \kDAct
+ \the\kDMitraTmpTok}
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ozos.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ozos.code.tex
new file mode 100644
index 00000000000..07d375cc434
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ozos.code.tex
@@ -0,0 +1,58 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% όζος • (ózos)
+% 1. node
+% 2. nodule
+% 3. gnarl
+
+% Ozos is an alternative parsing mechanism for TiKz nodes.
+% It implements the following transformation
+% \kDOzos ... {CONTENTS}; ---> \node ... [node contents={CONTENTS}];
+% to ensure the node contents always pass through the TikZ key.
+
+\usetikzlibrary{commutative-diagrams.koinos}
+
+%==[ TikZ/pgf layer ]===========================================================
+
+\pgfkeys{/ozos/every node/.style={}}
+
+%==[ main macro ]===============================================================
+
+\def\kDOzos%
+ {\kDOzosFetchThen
+ {\kDOzosMaybeDumpThen
+ \kDOzosOutput}}
+
+%==[ fetching routine ]=========================================================
+
+% I use the general one implemented by koinos.
+\let\kDOzosFetchThen\kDFetchOptAndGrpThen
+
+%==[ parsing routine ]==========================================================
+
+% Trivially solved by fetching.
+
+%==[ dumping routine ]==========================================================
+
+\def\kDOzosMaybeDumpThen#1{%
+ \kDDump{options: '\the\kDOptTok'}%
+ \kDDump{content: '\the\kDGrpTok'}%
+ #1}
+
+%==[ output routine ]===========================================================
+
+\def\kDOzosOutput{
+ \edef\kDAct{
+ \noexpand\node
+ [/ozos/every node]
+ \the\kDOptTok
+ [/tikz/node contents={\the\kDGrpTok}];
+ }
+ \kDAct
+}
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ramma.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ramma.code.tex
new file mode 100644
index 00000000000..1854abb67ec
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.ramma.code.tex
@@ -0,0 +1,158 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% ράμμα • (rámma)
+% 1. suture
+% 2. catgut
+% 3. stitch
+
+% Ramma ties together the lower level libraries to define
+% the user level functionality. NOTE: strictly no aesthetics, see mandyas.
+
+\usetikzlibrary[commutative-diagrams.bapto]
+\usetikzlibrary[commutative-diagrams.ektropi]
+\usetikzlibrary[commutative-diagrams.katharizo]
+\usetikzlibrary[commutative-diagrams.koinos]
+\usetikzlibrary[commutative-diagrams.ozos]
+\usetikzlibrary[commutative-diagrams.mitra]
+\usetikzlibrary[commutative-diagrams.velos]
+
+%==[ core concept ]=============================================================
+
+\pgfqkeys{/codi}{% TODO: is this the best scope to put the key into?
+ self naming/.style={
+ /tikz/node contents/.forward to=/bapto/input,
+ /bapto/trigger/.forward to=/katharizo/input,
+ /katharizo/output/.forward to=/bapto/dispatcher
+ }
+}
+
+%==[ baseline setup ]===========================================================
+
+% Some mischief with handlers and baseline math/labeling functionality.
+
+\pgfqkeys{/codi}{
+ .search also=/bapto,
+ .search also=/katharizo,
+ every thing/.style={
+ /ektropi/restore,
+ /ektropi/add=/codi,
+ /ektropi/add=/bapto,
+ /ektropi/add=/katharizo
+ },
+ every diagram/.style={% NOTE: restore hopefully unnecessary
+ /codi/every thing,
+ /ektropi/add=/codi/diagrams
+ },
+ every layout/.style={% NOTE: restore actually unnecessary
+ /codi/every thing,
+ /ektropi/add=/codi/layouts,
+ /mitra/every node/.append style={/codi/every object}
+ },
+ every object/.style={% NOTE: needed when inside matrices
+ /codi/every thing,
+ /ektropi/add=/codi/objects,
+ execute at begin node=$,%
+ execute at end node=$,%
+ /codi/self naming
+ },
+ every arrow/.style={% NOTE: restore unnecessary
+ /codi/every thing,
+ /ektropi/add=/codi/arrows
+ },
+ every label/.style={% NOTE: restore needed because inside edge
+ /codi/every thing,
+ /ektropi/add=/codi/labels,
+ execute at begin node=$,%
+ execute at end node=$,%
+ /codi/self naming
+ }
+}
+
+% The user level keys are bound to the underlying parsers.
+
+\pgfkeys{
+ /mitra/every matrix/.append style=/codi/every layout,
+ /ozos/every node/.append style=/codi/every object,
+ /velos/every path/.append style={
+ /tikz/every edge/.append style=/codi/every arrow,
+ /tikz/every edge quotes/.append style=/codi/every label
+ }
+}
+
+% I merge the macro syntax for objects and matrices. Convenient!
+
+\newif\ifkDRammaObjIsMatrix
+
+\def\kDRammaObjDecideWhetherIsMatrixThen#1{%
+ \def\kDRammaObjDWIM{\kDRammaObjDWIMSightThen{\kDRammaObjDWIMGobThen{#1}}}%
+ \expandafter\kDRammaObjDWIM\the\kDGrpTok\\\kD}
+
+\def\kDRammaObjDWIMSightThen#1#2\\%
+ {\kDIfNextHardCh\kD
+ {\kDRammaObjIsMatrixfalse#1}%
+ {\kDRammaObjIsMatrixtrue#1}}
+
+\def\kDRammaObjDWIMGobThen#1#2\kD{#1}
+
+\def\kDRammaObjOutput
+ {\ifkDRammaObjIsMatrix
+ \kDMitraParseMatrixTableThen\kDMitraOutput\else
+ \kDOzosOutput\fi}
+
+\def\kDRammaObj
+ {\kDFetchOptAndGrpThen
+ {\kDRammaObjDecideWhetherIsMatrixThen
+ \kDRammaObjOutput}}
+
+% Just an identity.
+\let\kDRammaMor\kDVelos
+
+%==[ TikZ/pgf layer ]===========================================================
+
+% I envelope the CoDi main macros in a simple key for maximal flexibility.
+
+\tikzset{
+ codi/.code={%
+ \ifConTeXt\catcode`\|=12\fi% TODO: is it sufficient? investigate
+ \let\obj\kDRammaObj
+ \let\mor\kDRammaMor
+ },
+ codi/.append style={/codi/every diagram}
+}
+
+%==[ main macro ]===============================================================
+
+\def\kDRamma
+ {\kDRammaMaybeFetchOptionsThen
+ \kDRammaOutput}
+
+\let\kDRammaOpen\kDRamma
+\let\kDRammaShut\endtikzpicture
+
+%==[ fetching routine ]=========================================================
+
+\newtoks\kDRammaOptTok
+\newtoks\kDRammaTmpTok
+
+\def\kDRammaMaybeFetchOptionsThen#1{%
+ \kDRammaOptTok={}%
+ \kDIfNextHardCh[%
+ {\kDRammaFetchOptionsThen{#1}}%
+ {#1}}
+
+\def\kDRammaFetchOptionsThen#1[#2]{\kDRammaOptTok={#2}#1}
+
+%==[ output routine ]===========================================================
+
+\def\kDRammaOutput{%
+ \edef\kDAct{%
+ \noexpand\kDRammaTmpTok={%
+ \noexpand\tikzpicture[codi, \the\kDRammaOptTok]}}%
+ \kDAct
+ \the\kDRammaTmpTok}
diff --git a/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.velos.code.tex b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.velos.code.tex
new file mode 100644
index 00000000000..5072b97d7cc
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.velos.code.tex
@@ -0,0 +1,280 @@
+%
+% CoDi: Commutative Diagrams for TeX
+% Copyright (c) 2015-2020 Paolo Brasolin <paolo.brasolin@gmail.com>
+% SPDX-License-Identifier: MIT
+%
+% This file is part of CoDi 1.0.0, released on 2020/06/06 under MIT license.
+%
+
+% βέλος • (vélos)
+% 1. arrow
+% 2. dart
+% 3. shaft
+
+% Velos is a parsing mechanism for arrow chains.
+
+\usetikzlibrary{commutative-diagrams.koinos}
+
+%==[ TikZ/pgf layer ]===========================================================
+
+\pgfkeys{
+ % NOTE: there might be some way to work w/ quotes library, but it's safer and
+ % easier to just have a custom handler mounted in the maximally local scope
+ % and avoid any conflict a priori.
+ /velos/install quote handler/.style={
+ /handlers/first char syntax=true,
+ /handlers/first char syntax/the character "/.initial=\kDVelosQuoteHandler
+ % node quotes mean={node contents={#1}},
+ % edge quotes mean={node contents={#1}}
+ },
+ /velos/every path/.style={
+ /velos/install quote handler
+ }
+}
+
+\def\kDVelosQuoteHandler#1%
+ {\pgfkeysalso{/tikz/node contents/.expand once={\kDVelosUnquote#1}}}
+
+\def\kDVelosUnquote"#1"{#1}
+
+%==[ global options ]===========================================================
+
+\newtoks\kDVelosTemp
+
+\newtoks\kDVelosGlobalLabelOptions
+\newtoks\kDVelosGlobalEdgeOptions
+
+\newif\ifkDVelosGOAfterColon
+
+\def\kDVelosFetchGlobalOptionsThen#1{%
+ \kDVelosGOAfterColonfalse
+ \kDVelosGlobalLabelOptions={}%
+ \kDVelosGlobalEdgeOptions={}%
+ \kDVelosGOMaybeFetchThen{\kDVelosGOThinkThen{#1}}}
+
+\def\kDVelosGOMaybeFetchThen#1{%
+ \kDVelosTemp={}%
+ \kDIfNextHardCh[%
+ {\kDVelosGOFetchThen{#1}}%
+ {#1}}
+
+\def\kDVelosGOFetchThen#1[#2]{%
+ \kDVelosTemp={#2}%
+ #1}
+
+\def\kDVelosGOThinkThen#1{%
+ \def\kDVelosGOLoop{\kDVelosGOThinkThen{#1}}%
+ \def\kDVelosGOBreak{#1}%
+ \kDIfNextHardCh:%
+ {%
+ \kDVelosGOAfterColontrue
+ \kDVelosGlobalLabelOptions\expandafter{\the\kDVelosTemp}%
+ \expandafter\kDVelosGOMaybeFetchThen\expandafter\kDVelosGOLoop\kDGobbleHardTok
+ }{%
+ \ifkDVelosGOAfterColon
+ \kDVelosGlobalEdgeOptions\expandafter{\the\kDVelosTemp}\else
+ \kDVelosGlobalLabelOptions\expandafter{\the\kDVelosTemp}\fi
+ \kDVelosGOBreak
+ }}
+
+%==[ first edge ]===============================================================
+
+\def\kDVelosDoFirstEdgeThen#1%
+ {\kDVelosFetchFirstSourceThen
+ {\kDVelosFetchFirstEdgeThen
+ {\kDVelosDrawFetchedEdgeThen
+ {#1}}}}
+
+\newtoks\kDVelosSource
+\newtoks\kDVelosCurFstSrc
+\newtoks\kDVelosPrvFstSrc
+
+\def\kDVelosFetchFirstSourceThen#1%
+ {\kDIfNextHardCh(%
+ {\kDVelosFFSBracketsThen{#1}}%
+ {\kDVelosFFSTillOverThen{#1}}}
+
+\def\kDVelosFFSBracketsThen#1(#2){%
+ \kDVelosSource={#2}%
+ \kDVelosCurFstSrc={#2}%
+ #1}
+
+\def\kDVelosFFSTillOverThen#1#2 {% <- mind the space!
+ \kDVelosSource={#2}%
+ \kDVelosCurFstSrc={#2}%
+ #1}
+
+\def\kDVelosFetchFirstEdgeThen#1%
+ {\kDVelosFetchEdgeThen
+ {\kDVelosFetchTargetThen
+ {#1}}}
+
+%==[ chained edges ]============================================================
+
+\newtoks\kDVelosEdge
+
+\def\kDVelosFetchEdgeThen#1{%
+ \kDVelosEdge={}%
+ \kDVelosFEThen{\kDVelosFEThinkThen{#1}}}
+
+\def\kDVelosFEThen#1%
+ {\kDIfNextHardCh[%
+ {\kDVelosFEKeysListThen{#1}}%
+ {\kDIfNextHardCh"%
+ {\kDVelosFEEnquotedThen{#1}}%
+ {\kDVelosFETillOverThen{#1}}}}
+
+\newif\ifkDVelosTempIsKeysList
+
+\def\kDVelosFEEnquotedThen#1"#2"{%
+ \kDVelosTempIsKeysListfalse
+ \kDVelosTemp={#2}%
+ #1}
+
+\def\kDVelosFEKeysListThen#1[#2]{%
+ \kDVelosTempIsKeysListtrue
+ \kDVelosTemp={#2}%
+ #1}
+
+\def\kDVelosFETillOverThen#1{%
+ \kDVelosTempIsKeysListfalse
+ \kDVelosTemp={}%
+ \kDVelosFETOThen{#1}}
+
+\def\kDVelosFETOThen#1%
+ {\kDIfNextSoftCh\kDBlankSpace
+ {#1}%
+ {\kDIfNextHardCh:%
+ {#1}
+ {\kDVelosFEAppendThen{\kDVelosFETOThen{#1}}}}}
+
+\def\kDVelosFEAppendThen#1#2{%
+ \kDVelosTemp=\expandafter{\the\kDVelosTemp#2}%
+ #1}
+
+\def\kDVelosFEEdgePrepend#1{%
+ \edef\Act{\noexpand\kDVelosEdge={#1,\the\kDVelosEdge}}%
+ \Act}
+
+\def\kDVelosFEEdgePrependNode#1%
+ {\kDVelosFEEdgePrepend{edge node={node[every edge quotes][/velos/install quote handler,#1]}}}
+
+\def\kDVelosFEThinkThen#1{%
+ \def\kDVelosFELoop{\kDVelosFEThinkThen{#1}}%
+ \def\kDVelosFEBreak{#1}%
+ \kDIfNextHardCh[%
+ {%
+ \kDVelosFEEdgePrependNode{\the\kDVelosTemp}%
+ \kDVelosFEThen\kDVelosFELoop
+ }{%
+ \kDIfNextHardCh:%
+ {%
+ \ifkDVelosTempIsKeysList
+ \kDVelosFEEdgePrependNode{\the\kDVelosTemp}\else
+ \kDVelosFEEdgePrependNode{"\the\kDVelosTemp"}\fi
+ \expandafter\kDVelosFEThen\expandafter\kDVelosFELoop\kDGobbleHardTok
+ }{%
+ \kDVelosFEEdgePrepend{\the\kDVelosTemp}%
+ \kDVelosFEBreak
+ }%
+ }}
+
+%==[ target ]===================================================================
+
+\newtoks\kDVelosTarget
+\newtoks\kDVelosCurLstTar
+\newtoks\kDVelosPrvLstTar
+
+\def\kDVelosFetchTargetThen#1%
+ {\kDIfNextHardCh(%
+ {\kDVelosFTBracketsThen{#1}}%
+ {\kDVelosFTTillOverThen{#1}}}
+
+\def\kDVelosFTBracketsThen#1(#2){%
+ \kDVelosTarget={#2}%
+ \kDVelosCurLstTar={#2}%
+ #1}
+
+\def\kDVelosFTTillOverThen#1{%
+ \kDVelosTarget={}%
+ \kDVelosFTTOThen{#1}}
+
+\def\kDVelosFTTOThen#1{%
+ \def\kDVelosFTTOLoop%
+ {\kDVelosFTTOThen{#1}}%
+ \def\kDVelosFTTOExit{%
+ \kDVelosCurLstTar\expandafter{\the\kDVelosTarget}%
+ #1}%
+ \kDIfNextSoftCh\kDBlankSpace
+ {\kDVelosFTTOExit}%
+ {\kDIfNextHardCh;%
+ {\kDVelosFTTOExit}%
+ {\kDVelosFTAppendThen\kDVelosFTTOLoop}}}
+
+\def\kDVelosFTAppendThen#1#2{%
+ \kDVelosTarget=\expandafter{\the\kDVelosTarget#2}%
+ #1}
+
+%==[ rendering/dereferencing ]==================================================
+
+\def\kDVelosAlias{*}
+\def\kDVelosSaila{+}
+
+\newtoks\kDVelosDerefSrc
+\newtoks\kDVelosDerefTar
+
+\def\kDVelosDrawFetchedEdgeThen#1{
+ \edef\cS{\the\kDVelosSource}%
+ \kDVelosDerefSrc\expandafter{\the\kDVelosSource}%
+ \ifx\cS\kDVelosAlias\kDVelosDerefSrc\expandafter{\the\kDVelosPrvFstSrc}\fi
+ \ifx\cS\kDVelosSaila\kDVelosDerefSrc\expandafter{\the\kDVelosPrvLstTar}\fi
+ \edef\cT{\the\kDVelosTarget}%
+ \kDVelosDerefTar\expandafter{\the\kDVelosTarget}%
+ \ifx\cT\kDVelosAlias\kDVelosDerefTar\expandafter{\the\kDVelosPrvLstTar}\fi
+ \ifx\cT\kDVelosSaila\kDVelosDerefTar\expandafter{\the\kDVelosPrvFstSrc}\fi
+ \edef\Act{%
+ \noexpand\path
+ [/velos/every path]%
+ [%
+ /tikz/every edge/.append style=%
+ {\the\kDVelosGlobalEdgeOptions},%
+ /tikz/every edge quotes/.append style=%
+ {auto,\the\kDVelosGlobalLabelOptions},%
+ ]%
+ (\the\kDVelosDerefSrc)%
+ edge[\the\kDVelosEdge]%
+ (\the\kDVelosDerefTar);}%
+ \Act%
+ #1}
+
+%==[ high level ]===============================================================
+
+\def\kDVelos%
+ {\kDVelosFetchGlobalOptionsThen
+ {\kDVelosDoFirstEdgeThen
+ \kDVelosMaybeChainEdge}}
+
+\def\kDVelosMaybeChainEdge{%
+ \kDIfNextHardCh;%
+ {%
+ \edef\cS{\the\kDVelosCurFstSrc}%
+ \ifx\cS\kDVelosAlias
+ \kDVelosCurFstSrc\expandafter{\the\kDVelosPrvFstSrc}%
+ \else\ifx\cS\kDVelosSaila
+ \kDVelosCurFstSrc\expandafter{\the\kDVelosPrvLstTar}%
+ \fi\fi
+ \edef\cT{\the\kDVelosCurLstTar}%
+ \ifx\cT\kDVelosAlias
+ \kDVelosCurLstTar\expandafter{\the\kDVelosPrvLstTar}%
+ \else\ifx\cT\kDVelosSaila
+ \kDVelosCurLstTar\expandafter{\the\kDVelosPrvFstSrc}%
+ \fi\fi
+ \kDVelosPrvFstSrc\expandafter{\the\kDVelosCurFstSrc}%
+ \kDVelosPrvLstTar\expandafter{\the\kDVelosCurLstTar}%
+ }{%
+ \kDVelosSource\expandafter{\the\kDVelosTarget}
+ \kDVelosFetchEdgeThen
+ {\kDVelosFetchTargetThen
+ {\kDVelosDrawFetchedEdgeThen
+ \kDVelosMaybeChainEdge}}%
+ }}