diff options
21 files changed, 3414 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/generic/commutative-diagrams/README b/Master/texmf-dist/doc/generic/commutative-diagrams/README new file mode 100644 index 00000000000..d4395793784 --- /dev/null +++ b/Master/texmf-dist/doc/generic/commutative-diagrams/README @@ -0,0 +1,6 @@ +CoDi: Commutative Diagrams for TeX +================================== + +CoDi is a TikZ library. Its aim +is making commutative diagrams +easy to design, parse and tweak. diff --git a/Master/texmf-dist/doc/generic/commutative-diagrams/commutative-diagrams-doc.pdf b/Master/texmf-dist/doc/generic/commutative-diagrams/commutative-diagrams-doc.pdf Binary files differnew file mode 100644 index 00000000000..e479e4960f5 --- /dev/null +++ b/Master/texmf-dist/doc/generic/commutative-diagrams/commutative-diagrams-doc.pdf diff --git a/Master/texmf-dist/doc/generic/commutative-diagrams/commutative-diagrams-doc.tex b/Master/texmf-dist/doc/generic/commutative-diagrams/commutative-diagrams-doc.tex new file mode 100644 index 00000000000..5c68664271a --- /dev/null +++ b/Master/texmf-dist/doc/generic/commutative-diagrams/commutative-diagrams-doc.tex @@ -0,0 +1,1729 @@ +% +% 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. +% + +%==[ document class ]=========================================================== + +\documentclass[12pt]{scrbook} + +%==[ languages ]================================================================ + +\usepackage[british]{babel} +% \hyphenation{Fortran hy-phen-ation} + +%==[ fonts, encoding ]========================================================== + +\usepackage{libertine} +\usepackage{libertinust1math} +\usepackage[ttdefault=true]{AnonymousPro} + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} + +%==[ page geometry ]============================================================ + +\usepackage{geometry} + +\geometry{ + a4paper, + portrait, + marginparwidth=4.25cm, + marginparsep=.75cm, + %% showframe, + width=11cm, + hmarginratio=10:25, + height=23cm, + vmarginratio=20:30, +} + +\makeatletter +\let\org@Gm@pageframes\Gm@pageframes +\renewcommand*{\Gm@pageframes}{% + \begingroup + \color{gray}% + \org@Gm@pageframes + \endgroup +} +\makeatother + +%==[ page layout ]============================================================== + +%\usepackage{multicol} +%\usepackage{tabularx} +\usepackage{booktabs} +%\usepackage{verbatimbox} +%\usepackage{wrapfig} + +\usepackage{float} +% \usepackage{framed} +% \usepackage{lipsum} +\usepackage{enumitem} +% \usepackage{pdfpages} + +% \usepackage{caption} +\usepackage{sidenotes} + +% \DeclareCaptionStyle{sidenote}{font=scriptsize} + +% \usepackage{todonotes} +% \usepackage{marginnote} + +\usepackage[ + headwidth=textwithmarginpar, + footwidth=textwithmarginpar, +]{scrlayer-scrpage} +%\clearpairofpagestyles + +% \lofoot{} +% \cofoot{} +% \rofoot{} +% \lohead{} +% \cohead{} +% \rohead{\thepage} + +%==[ page style ]=============================================================== + +\setkomafont{disposition}{\rmfamily\scshape} + +\usepackage{parskip} + +% \usepackage{csquotes} + +\usepackage{caption} +\usepackage{subcaption} + +\DeclareCaptionStyle{marginfigure}{ + font=footnotesize, + justification=centering, +} + +\captionsetup[subfigure]{ + textfont=footnotesize, + %% singlelinecheck=off, + justification=centering +} + +\setcounter{secnumdepth}{0} + +%==[ commonplace math ]========================================================= + +\usepackage{mathtools} +\usepackage{amsfonts} +\usepackage{amssymb} + +\DeclareMathOperator{\coker}{coker} + +% \def\id{{\mathbf 1}} +% \DeclareUnicodeCharacter{0131}{{\noexpand\mathbf R}} +% \DeclareUnicodeCharacter{00D7}{{\otimes}} +% \catcode`ı=\active \letı\id +% \catcode`×=\active \let×\otimes +% NOTE: needed just for the associahedron example +\usepackage{newunicodechar} +\newunicodechar{ı}{\mathbf 1} +\newunicodechar{×}{\otimes} + +%==[ graphics ]================================================================= + +\usepackage{graphicx} +\usepackage{xcolor} +% TODO: what did I need soul for again? +\usepackage{color,soul} + +\usepackage{tikz} +\usetikzlibrary{decorations.pathreplacing} + +%==[ CoDi ]===================================================================== + +% \usetikzlibrary{commutative-diagrams} +\usepackage{commutative-diagrams} +\usetikzlibrary{positioning} + +%==[ alternatives to CoDi ]===================================================== + +% So, yeah, I got *really* tired... +\usepackage{filecontents} + +% Copied from Xy sourcecode +\def\Xy{\hbox{\kern-.1em X\kern-.3em\lower.4ex\hbox{Y\kern-.15em}}} + +%==[ utilities and custom macros ]============================================== + +\usepackage{etoolbox} +\usepackage{xparse} + +% \NewDocumentCommand{\SmashAndCenter}{m}{% +% \begingroup\setbox0=\hbox{#1}% +% \newdimen\tmp\tmp=\dimexpr-.5\ht0+.5\dp0\relax% +% \hfill\smash{\raisebox{\the\tmp}{\box0}}\hfill\null\endgroup% +% } + +\newsavebox\SmashAndCenterBox +\newdimen\SmashandCenterRaise + +% TODO: make overflow on left pages go left +\NewDocumentEnvironment{SmashAndCenter}{}{% +\begin{lrbox}{\SmashAndCenterBox}}{% +\end{lrbox}% +\SmashandCenterRaise=\dimexpr-.5\ht\SmashAndCenterBox+.5\dp\SmashAndCenterBox\relax% +\hfill\smash{\raisebox{\the\SmashandCenterRaise}{\usebox\SmashAndCenterBox}}\hfill\null% +} + +\def\eg{e.\,g.} +%% \deg\ie{i.\,e.} + +%==[ sourcecode and examples ]================================================== + +\usepackage{listings} + +% http://tex.stackexchange.com/a/336331/82186 +\makeatletter +\lst@Key{lastline}\relax{\ifnumcomp{#1}{<}{0}{% + \let\mylst@file\kvtcb@listingfile\sbox0{\lstinputlisting{\mylst@file}}% + \def\lst@lastline{\the\numexpr#1+\value{lstnumber}-1\relax}}% + {\def\lst@lastline{#1\relax}}} +\makeatother + +\usepackage{showexpl} + +\makeatletter +\lst@Key{postset}\relax{\def\SX@postset{#1}} +\newcommand\SX@postset{} +\renewcommand*\SX@resultInput{% + \ifx\SX@graphicname\@empty + \begingroup + \MakePercentComment\makeatother\catcode`\^^M=5\relax + \SX@@preset\SX@preset + \if@SX@rangeaccept + \let\SX@tempa=\SX@input + \else + \let\SX@tempa=\input + \fi + \if\SX@scaled ?% + \let\SX@tempb=\@firstofone + \else + \if\SX@scaled !% + \def\SX@tempb##1{\resizebox{\SX@width}{!}{##1}}% + \else + \def\SX@tempb##1{\scalebox{\SX@scaled}{##1}}% + \fi + \fi + \SX@tempb{\SX@tempa{\SX@codefile}}\SX@postset\par + \endgroup + \else + \expandafter\includegraphics\expandafter[\SX@graphicparam]% + {\SX@graphicname}% + \fi +} +\makeatother + +% \lstdefinelanguage{TikZ}{ +% morekeywords={for}, +% sensitive=false, +% morecomment=[l]{//}, +% morecomment=[s]{/*}{*/}, +% morestring=[b]", +% } + +\lstdefinestyle{TeX}{ + language=[LaTeX]TeX, + basicstyle=\ttfamily\lst@ifdisplaystyle\scriptsize\fi, + backgroundcolor=\color{teal!10}, + % keywordstyle=*\color{blue}, + % identifierstyle=\color{orange}\bfseries, + % morekeywords={\path}, + alsoother={@}, + moretexcs={ + \starttext,\stoptext,\usemodule, + \tikzpicture,\endtikzpicture, + \tikzexternalize, + \starttikzpicture,\stoptikzpicture, + \usetikzlibrary, + \codi,\endcodi, + \startcodi,\stopcodi, + \lay,\obj,\mor, + \bye, + \draw,\foreach, + \ar, + \psset,\everypsbox,\ncline,\ncarc, + \xymatrix, + }, + texcsstyle=*\bfseries, + % morestring=[b]", + commentstyle=\itshape\color{black!60}, + frame=none, + % extendedchars=false, + inputencoding=utf8, + escapeinside={(@}{@)}, + moredelim=**[is][\color{orange!80!black}]{@opt@}{@/opt@}, + moredelim=**[is][\color{blue!80!black}]{@nws@}{@/nws@}, + % moredelim=**[is][\color\underbar]{@rep@}{@/rep@}, + moredelim=**[s][\itshape]{<}{>}, + % NOTE: × and ı are needed just for the associahedron example + literate={~}{{\textvisiblespace}}1 {XOR}{{$\vert$}}1 {:}{{\textbf{:}}}1 {:=}{{$\equiv$}}1 {×}{{\texttimes}}1 {ı}{{\i}}1, +} + +\lstset{style=TeX} +% \lstMakeShortInline[style=TeX]" + +% \makeatletter +% \newcount\ublvl\ublvl=0 +% \newcount\ubdpt\ubdpt=0 +% \newdimen\ubgap\ubgap=.2em +% \def\underbra#1{\underline {\sbox \tw@ {\global\advance\ubdpt1\advance\ublvl1#1}\dp \tw@ \dimexpr\ubgap*(\ubdpt-\ublvl-1)\relax \box \tw@ }\ifnum\ublvl=0\ubdpt=0\fi} +% \makeatother + +% \lstset{explpreset={ +% wide, +% basicstyle=\ttfamily\scriptsize, +% pos=o, +% width=\marginparwidth, +% hsep=\marginparsep, +% rframe={}, +% preset={\centering\tikzpicture[codi]}, +% postset={\endtikzpicture} +% }} + +\usepackage{tcolorbox} +\tcbuselibrary{listingsutf8} +\tcbset{listing utf8=latin1} + +\tcbset{ + smash and center/.style={ + if odd page={ + before lower=\begin{SmashAndCenter}, + after lower=\end{SmashAndCenter} + }{ + before upper=\begin{SmashAndCenter}, + after upper=\end{SmashAndCenter} + }}, + trim/.style args={#1 and #2}{ + listing options={ + firstline=#1, + lastline=#2}}, + trim/.default={2 and -1}, + snippet/.style={ + size=tight, + colback=white, + colframe=white, + if odd page={ + listing side text, + lefthand width=\textwidth, + righthand width=\marginparwidth, + halign lower=center, + }{ + text side listing, + righthand width=\textwidth, + lefthand width=\marginparwidth, + halign upper=center, + }, + toggle enlargement, + grow to right by=\marginparsep+\marginparwidth, + sidebyside gap=\marginparsep, + smash and center, + listing options={} + }, + commented snippet/.style={ + snippet, + comment={}, % avoids text compilation (possible tcb bug?) + if odd page={ + listing side comment, + }{ + comment side listing, + }, + }, + gallery/.style={ + size=tight, + colback=white, + colframe=white, + if odd page={ + % listing side text, + % lefthand width=\textwidth, + % righthand width=\marginparwidth, + grow to right by=\marginparsep+\marginparwidth, + }{ + grow to right by=\marginparsep+\marginparwidth, + % text side listing, + % righthand width=\textwidth, + % lefthand width=\marginparwidth, + % halign upper=center, + }, + toggle enlargement, + % grow to right by=\marginparsep+\marginparwidth, + text above listing, + listing options={} + } +} + +% \tcbset{codi snippet/.style={snippet, trim, smash and center}} + +\def\nilstrut{\rule{0sp}{0sp}} + +%==[ extra stuff ]============================================================== + +\usepackage{soul} + +% \usepackage{lipsum} + +\usepackage{hologo} +\def\ConTeXt{\hologo{ConTeXt}} +\def\CoDi{{\scshape CoDi}} +\def\TikZ{{\scshape TikZ}} + +% \usepackage[lastpage,user]{zref} +\usepackage[ + % colorlinks=true, + % urlcolor=blue, + % linkbordercolor=black, + % pdfborderstyle={/S/U/W .4}% border style will be underline of width 1pt + % urlbordercolor=cyan % color of external links + hidelinks +]{hyperref} + +\def\NiceURL#1#2{\href{#2}{\color{blue}\ul{#1}}} + +%==[ microtype ]================================================================ + +\usepackage{microtype} + +\begin{document} + +%==[ TITLE PAGE ]=============================================================== + +\thispagestyle{empty} +\noindent +\resizebox{\linewidth}{!}{\scshape CoDi}\\[0.62em] +\resizebox{\linewidth}{!}{\scshape Commutative Diagrams for \TeX}\\[1.62em] +\resizebox{\linewidth}{!}{\scshape enchiridion}\par +\vfill +\marginpar{ + \resizebox{\linewidth}{!}{\scshape 1.0.0}\\[0.62em] + \resizebox{\linewidth}{!}{\scshape \today} +} + +%==[ FOREWORD ]================================================================= + +\newpage +\begin{adjustwidth}{.47\textwidth-\marginparwidth-\marginparsep}{.47\textwidth} +\noindent\CoDi\ is a \TikZ\ library. Its aim is\linebreak +making commutative diagrams\linebreak +easy to design, parse and tweak.\par +\end{adjustwidth} + +\newpage +\section{Preliminaries} +\TikZ\ is the only dependency of \CoDi. +This ensures compatibility with most\footnote{\CoDi\ builds upon \TikZ, which builds upon {\ttfamily\small pgf}, which after version 3.1 requires at least \hologo{eTeX} version 2. This is inconsequential except in the unlikely event you're using Knuth's original {\ttfamily\small tex} format.} \TeX\ flavours. +Furthermore, it can be invoked both as a standalone and as a \TikZ\ library. +Below are minimal working examples for the main dialects. + +\begin{figure}[H] + \begin{adjustwidth}{0sp}{-\marginparwidth-\marginparsep} + \begin{subfigure}{\marginparwidth} + \caption*{\TeX\ package} + \begin{lstlisting}[gobble=8] + + \input + {commutative-diagrams} + + \codi + % diagram here + \endcodi + \bye + \end{lstlisting} + \end{subfigure} + \hfill + \begin{subfigure}{\marginparwidth} + \caption*{\ConTeXt\ module} + \begin{lstlisting}[gobble=8] + + \usemodule + [commutative-diagrams] + \starttext + \startcodi + % diagram here + \stopcodi + \stoptext + \end{lstlisting} + \end{subfigure} + \hfill + \begin{subfigure}{\marginparwidth} + \caption*{\LaTeX\ package} + \begin{lstlisting}[gobble=8] + \documentclass{article} + \usepackage + {commutative-diagrams} + \begin{document} + \begin{codi} + % diagram here + \end{codi} + \end{document} + \end{lstlisting} + \end{subfigure} + \par + \begin{subfigure}{\marginparwidth} + \caption*{\TeX\ (\TikZ\ library)} + \begin{lstlisting}[gobble=8] + + \input{tikz} + \usetikzlibrary + [commutative-diagrams] + + \tikzpicture[codi] + % diagram here + \endtikzpicture + \bye + \end{lstlisting} + \end{subfigure} + \hfill + \begin{subfigure}{\marginparwidth} + \caption*{\ConTeXt\ (\TikZ\ library)} + \begin{lstlisting}[gobble=8] + + \usemodule[tikz] + \usetikzlibrary + [commutative-diagrams] + \starttext + \starttikzpicture[codi] + % diagram here + \stoptikzpicture + \stoptext + \end{lstlisting} + \end{subfigure} + \hfill + \begin{subfigure}{\marginparwidth} + \caption*{\LaTeX\ (\TikZ\ library)} + \begin{lstlisting}[gobble=8] + \documentclass{article} + \usepackage{tikz} + \usetikzlibrary + {commutative-diagrams} + \begin{document} + \begin{tikzpicture}[codi] + % diagram here + \end{tikzpicture} + \end{document} + \end{lstlisting} + \end{subfigure} + \end{adjustwidth} +\end{figure} + +\begin{marginfigure}[0em] + % \caption*{\TikZ\ externalization} + \begin{lstlisting}[gobble=4] + \documentclass{article} + + \usepackage + {commutative-diagrams} + % Or, equivalently: + %\usepackage{tikz} + %\usetikzlibrary + % {commutative-diagrams} + + \usetikzlibrary{external} + \tikzexternalize + [prefix=tikzpics/] + + \begin{document} + \begin{tikzpicture}[codi] + % diagram here + \end{tikzpicture} + \end{document} + \end{lstlisting} +\end{marginfigure} + +A useful \TikZ\ feature exclusive to \LaTeX\ is +\NiceURL + {externalization} + {http://texdoc.net/texmf-dist/doc/generic/pgf/pgfmanual.pdf\#page=607}. +It is an effective way to boost processing times by (re)\-compiling figures as +external files only when strictly necessary. + +A small expedient is necessary to use it with \CoDi: diagrams must be wrapped in +\lstinline|tikzpicture| environments endowed with the \lstinline|/tikz/codi| key. + +On the side is an example saving the pictures in the \lstinline|./tikzpics/| folder +to keep things tidy. + +\hfill$\therefore$\hfill\null + +Basic knowledge of \TikZ\ is assumed. A plethora of excellent +resources exist, so no crash course on the matter will be improvised +here. +Higher proficiency is not necessary, though recommended: +it will make \CoDi\ a pliable framework instead of a black box. +\newpage +\section{Quick tour} +Objects are typeset using the \lstinline|\obj| macro. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj {X}; +\end{codi} +\end{tcblisting} + +Almost every diagram is laid along a regular grid, +so the customary tabular syntax of \TeX\ is recognized. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj { + A & B \\ + C & D \\ +}; +\end{codi} +\end{tcblisting} + +\CoDi\ objects are self-aware and clever enough to name themselves +so you can comfortably refer to them. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj {\lim F}; +\draw (lim F) circle (4ex); +\end{codi} +\end{tcblisting} + +Morphisms are typeset using the \lstinline!\mor! macro. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj { A & B \\ }; +\mor A f:-> B; +\end{codi} +\end{tcblisting} + +Commutative diagrams exist to illustrate composition and commutation, +so \CoDi\ allows arrow chaining and chain gluing. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj { A & B \\ C & D \\ }; +\mor A -> B -> D; +\mor * -> C -> *; +\end{codi} +\end{tcblisting} + +These are the only two macros defined by \CoDi. + +There are more features, though.\\ +Read on if this caught your attention. +\newpage +\section{Alternatives} +It is only fair to mutely offer a comparison with mainstream packages, +showing idiomatic code to draw the same diagram. + +Let \NiceURL + {\Xy-pic} + {http://texdoc.net/texmf-dist/doc/generic/xypic/xyrefer.pdf\#page=1} +set the bar with a \emph{verbatim} extract from its manual. + +% Well, I got to admit that among the three alternatives +% Xy-pics was by far the best citizen. Mad props. + +\begin{filecontents*}{alternatives-xypic-pic.tex} +\documentclass[12pt]{standalone} +\usepackage{libertine} +\usepackage{libertinust1math} +\usepackage[all]{xy} +\begin{document} +\xymatrix{ + U \ar@/_/[ddr]_y \ar[dr] \ar@/^/[drr]^x \\ + & X \times_Z Y \ar[d]^q \ar[r]_p + & X \ar[d]_f \\ + & Y \ar[r]^g & Z } +\end{document} +\end{filecontents*} + +\IfFileExists{alternatives-xypic-pic.pdf}{}{\immediate\write18{pdflatex alternatives-xypic-pic.tex}} + +\begin{tcblisting}{ + commented snippet, + image comment={}{alternatives-xypic-pic.pdf}, +} +\xymatrix{ + U \ar@/_/[ddr]_y \ar[dr] \ar@/^/[drr]^x \\ + & X \times_Z Y \ar[d]^q \ar[r]_p + & X \ar[d]_f \\ + & Y \ar[r]^g & Z } +\end{tcblisting} + +Here is an example adapted from \NiceURL + {\ttfamily\small pst-node} + {http://texdoc.net/texmf-dist/doc/generic/pst-node/pst-node-doc.pdf\#page=23}'s +documentation. + +% I got really, really tired of pstricks subtle limitations. +% auto-pst-pdf doesnt really work on externalized listings. +% Ordinary compilation gotta pass through PS so it's tricky. +% Furthermore it just breaks TikZ opacity unless you use PS. +% Ain't nobody got time for that. + +\begin{filecontents*}{alternatives-pstnode-pic.tex} +\documentclass[12pt]{standalone} +\usepackage{libertine} +\usepackage{libertinust1math} +\usepackage{pstricks} +\usepackage{pst-node} +\begin{document} +$ \psset{colsep=2.5em, rowsep=2em} + \begin{psmatrix} + U \\ + & X\times_Z Y & X \\ + & Y & Z + \psset{arrows=->, nodesep=3pt} + \everypsbox{\scriptstyle} + \ncline{1,1}{2,2} + \ncarc[arcangle=-10]{1,1}{3,2}_{y} + \ncarc[arcangle=10]{1,1}{2,3}^{x} + \ncline{2,2}{3,2}>{q} + \ncline{2,2}{2,3}_{p} + \ncline{2,3}{3,3}<{f} + \ncline{3,2}{3,3}^{g} + \end{psmatrix}$ +\end{document} +\end{filecontents*} + +\IfFileExists{alternatives-pstnode-pic.pdf}{}{\immediate\write18{latex alternatives-pstnode-pic.tex && dvips alternatives-pstnode-pic.dvi && ps2pdf alternatives-pstnode-pic.ps}} + +\begin{tcblisting}{ + commented snippet, + image comment={}{alternatives-pstnode-pic.pdf} +} +$ \psset{colsep=2.5em, rowsep=2em} + \begin{psmatrix} + U \\ + & X\times_Z Y & X \\ + & Y & Z + \psset{arrows=->, nodesep=3pt} + \everypsbox{\scriptstyle} + \ncline{1,1}{2,2} + \ncarc[arcangle=-10]{1,1}{3,2}_{y} + \ncarc[arcangle=10]{1,1}{2,3}^{x} + \ncline{2,2}{3,2}>{q} + \ncline{2,2}{2,3}_{p} + \ncline{2,3}{3,3}<{f} + \ncline{3,2}{3,3}^{g} + \end{psmatrix}$ +\end{tcblisting} + +Next one is refitted from the guide to \NiceURL + {\ttfamily\small\{tikz-cd\}} + {http://texdoc.net/texmf-dist/doc/latex/tikz-cd/tikz-cd-doc.pdf\#page=3}. + +% It seems that tikz-cd is overwriting some arrows.meta +% global keys. I have no intention of investigating +% so let's just isolate the problem. + +\begin{filecontents*}{alternatives-tikzcd-pic.tex} +\documentclass[12pt]{standalone} +\usepackage{libertine} +\usepackage{libertinust1math} +\usepackage{tikz} +\usetikzlibrary{cd} +\begin{document} +\begin{tikzcd}[column sep=scriptsize, row sep=scriptsize] + U + \arrow[drr, bend left=10, "x"] + \arrow[ddr, bend right=10, swap, "y"] + \arrow[dr] & & \\ + & X \times_Z Y \arrow[r, swap, "p"] \arrow[d, "q"] + & X \arrow[d, swap, "f"] \\ + & Y \arrow[r, "g"] + & Z +\end{tikzcd} +\end{document} +\end{filecontents*} + +\IfFileExists{alternatives-tikzcd-pic.pdf}{}{\immediate\write18{pdflatex alternatives-tikzcd-pic.tex}} + +\begin{tcblisting}{ + commented snippet, + image comment={}{alternatives-tikzcd-pic.pdf}, +} +\begin{tikzcd}[column sep=scriptsize, row sep=scriptsize] + U + \arrow[drr, bend left=10, "x"] + \arrow[ddr, bend right=10, swap, "y"] + \arrow[dr] & & \\ + & X \times_Z Y \arrow[r, swap, "p"] \arrow[d, "q"] + & X \arrow[d, swap, "f"] \\ + & Y \arrow[r, "g"] + & Z +\end{tikzcd} +\end{tcblisting} + +Finally, \textbf{\CoDi}. + +\begin{tcblisting}{snippet} +\begin{codi}[tetragonal] + \obj { |(pb)| X \times_Z Y & X \\ + Y & Z \\ }; + \obj [above left=of pb] {U}; + + \mor[swap] pb p:-> X f:-> Z; + \mor * q:-> Y g:-> *; + + \mor U -> pb; + \mor :[bend left=10] * x:-> X; + \mor[swap]:[bend right=10] * y:-> Y; +\end{codi} +\end{tcblisting} +\newpage +\section{Syntax: objects} +The first of the two macros that \CoDi\ offers is \lstinline|\obj|. +It is polymorphic and can draw both single objects and layouts. + +\begin{lstlisting} +\obj@opt@ <object options> @/opt@{<math>};(@ + \marginpar{\scriptsize {\color{orange!80!black}Orange fragments} are optional.}@) +\obj@opt@ <layout options> @/opt@{<layout>}; +\end{lstlisting} + +Layouts are described using the customary \TeX\ tabular syntax. + +\begin{lstlisting} +<layout> := (@\itshape\underbar{<row> <row separator>}@)(@ + \marginpar{\scriptsize \underbar{Underlined fragments} can repeat one or more times.}@) +<row> := <cell> (@\itshape\color{orange!80!black}\underbar{<cell separator> <cell>}@) +<row separator> := \\ @opt@[<length>]@/opt@ +<cell> := @opt@|<object options>| @/opt@<math> +<cell separator> := & @opt@[<length>]@/opt@ +\end{lstlisting} + +The discretionary options syntax is analogous to standard \TikZ\ nodes and +matrices, respectively. + +\begin{lstlisting} +<object options> := (@\itshape\color{orange!80!black}\underbar{[object keylist]}@) @opt@(<name>) at (<coordinate>)@/opt@ +<layout options> := (@\itshape\color{orange!80!black}\underbar{[layout keylist]}@) @opt@(<name>) at (<coordinate>)@/opt@ +\end{lstlisting} + +\hfill$\therefore$\hfill\null + +Nothing of the given syntax is specific to \CoDi. +In fact, \lstinline|\obj| can draw both single objects and layouts +by behaving like the standard \TikZ\ macros +\lstinline|\node| and \lstinline|\matrix| respectively. + +Furthermore, layouts content is specified using the common \TeX\ +tabular syntax. +The only catch is that row and column separators are always mandatory. + +Here is a kitchen sink that includes custom spacing: + +\begin{tcblisting}{snippet, trim} +\begin{codi}[square=3em] +\obj { + A & B &[1em] C \\ + D & E & F \\[-1em] + G & H & I \\ +}; +\end{codi} +\end{tcblisting} + +Here is another one that includes custom options: + +\begin{tcblisting}{snippet, trim} +\begin{codi}[square=3em] +\obj [red] { + A & |[blue]| B & C \\ +}; +\end{codi} +\end{tcblisting} + +A standard feature inherited from \TikZ\ worth a mention +is the ability to name a layout and refer to cells +by their row/column index pairs. + +\begin{tcblisting}{snippet, trim} +\begin{codi}[square=3em] +\obj (M) { A & A \\ A & A \\ }; +\node [draw=red, shape=circle, minimum size=2em] at (M-1-2) {}; +\node [draw=blue, shape=circle, minimum size=2em] at (M-2-1) {}; +\end{codi} +\end{tcblisting} +\newpage +\section{Syntax: morphisms} +\begingroup\tcbset{trim/.default={3 and -1}} + +The second and last macro that \CoDi\ offers is \lstinline|\mor|. +It can draw single or chained morphisms. + +\begin{lstlisting} +\mor@opt@ <chain options> @/opt@<object>(@ + \itshape\underbar{\textvisiblespace<morphism>\textvisiblespace<object>}@);(@ + \marginpar{\scriptsize Whitespace marked as \textvisiblespace\ is mandatory.}@) +\end{lstlisting} + +Source and target objects are referred to by their name. + +\begin{lstlisting} +<object> := @nws@(<name>)@/nws@ (@ + \marginpar{\scriptsize {\color{blue!80!black}Blue fragments} can be either enclosed in the shown delimiters, or a \TeX\ group (not idiomatic), or simply devoid of whitespace.}@) +\end{lstlisting} + +Morphisms consist of one or more optional labels and an arrow. + +\begin{lstlisting} +<morphism> := @opt@<labels> : @/opt@<arrow> +<labels> := @nws@"<math>"@/nws@ XOR (@\underbar{[{\itshape "<math>", <label keylist>}]}@) (@ + \marginpar{\scriptsize Alternatives are separated by $\vert$s.}@) +<arrow> := @nws@[<arrow keylist>]@/nws@ +\end{lstlisting} +% <labels> := @nws@"<math>"@/nws@ XOR @nws@[<label keylist>]@/nws@ XOR (@\underbar{[{\itshape <label keylist>}]}@) + +Global options can be given to both labels and arrows. + +\begin{lstlisting} +<chain options> := [<label keylist>] @opt@: [<arrow keylist>]@/opt@ +\end{lstlisting} + +\hfill$\therefore$\hfill\null + +These rules allow for a label syntax that sprouts gracefully +from the simplest to the most complex case. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj { A & B & C \\ F & E & D \\ }; +\mor A -> B; +\mor B f:-> C; +\mor C \hat g:-> D; +\mor D "h i":-> E; +\mor E ["L", above]:-> F; +\mor F ["m", near start]["n", swap]["o", near end]:-> A; +\end{codi} +\end{tcblisting} + +The same holds for arrow syntax. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj { A & B & C \\ }; +\mor A -> B; +\mor B [>-, dashed] C; +\end{codi} +\end{tcblisting} + +Global options can be used to minimize local ones +and keep the code terse and readable. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj { A & B & C \\ F & E & D \\ }; +\mor [swap]:[bend left] B f:-> C g:>-> D h:>- E i:- B; +\mor :[bend right] E x:-> F y:>-> A z:>- B; +\mor [mid] B m:-> D; +\end{codi} +\end{tcblisting} + +\endgroup +\newpage +\section{Names} +As you'll have guessed by now, objects name themselves. + +The process happens in three steps: +\begin{itemize}[nosep] + \item expand tokens; + \item replace characters; + \item apply name, overwriting if necessary. +\end{itemize} + +Each one can be configured in any \CoDi\ scope with the keys. + +While you're getting acquainted with the process +you can use the \lstinline|/codi/prompter| key to +display labels with generated names. + +\begin{tcblisting}{snippet} +\begin{codi}[prompter] + \obj{ A & \lim A \\ }; + \mor A f:-> (lim A); +\end{codi} +\end{tcblisting} +\newpage +\subsection{Names: shortcuts} +\begingroup\tcbset{trim/.default={3 and -1}} + +Two special labels exist: {\ttfamily *} and {\ttfamily +}. + +As a source, {\ttfamily *} evaluates to the head of the previous chain. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { A & B & C & \phantom{D} \\ }; +\mor B -> C; +\mor * -> A; +\end{codi} +\end{tcblisting} + +As a target, {\ttfamily *} evaluates to the tail of the previous chain. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { \phantom{A} & B & C & D \\ }; +\mor B -> C; +\mor D -> *; +\end{codi} +\end{tcblisting} + +The natural use case for {\ttfamily *} is chain gluing. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { A & B \\ D & C \\ }; +\mor A -> B -> C; +\mor * -> D -> *; +\end{codi} +\end{tcblisting} + +As a source, {\ttfamily +} evaluates to the tail of the previous chain. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { \phantom{A} & B & C & D \\ }; +\mor B -> C; +\mor + -> D; +\end{codi} +\end{tcblisting} + +As a target, {\ttfamily +} evaluates to the head of the previous chain. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { A & B & C & \phantom{D} \\ }; +\mor B -> C; +\mor A -> +; +\end{codi} +\end{tcblisting} + +The natural use case for {\ttfamily +} is chain extension. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { A & B & C & D \\ }; +\mor B -> C; +\mor A -> + -> D; +\end{codi} +\end{tcblisting} + +The meanings of {\ttfamily *} and {\ttfamily +} swap on opposite chains. + +Chain extension can be obtained using {\ttfamily *}. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { A & B & C & D \\ }; +\mor B <- C; +\mor D -> * -> A; +\end{codi} +\end{tcblisting} + +Chain gluing can be obtained using {\ttfamily +}. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [square=2.5em] { A & B \\ D & C \\ }; +\mor A <- B <- C; +\mor + -> D -> +; +\end{codi} +\end{tcblisting} + +\endgroup +\newpage +\subsection{Names: expansion} +The expansion behaviour of the naming routine can be configured +inside any \CoDi\ scope using the \lstinline!expand! key. + +\begin{lstlisting} +/codi/expand = none | once | full +\end{lstlisting} + +The three available settings correspond to different degrees of expansion. +A side by side comparison completely illustrates their meanings. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\def\B{Z} +\def\A{\B} +\obj{ |[expand=none]| \A & % name: A (default) + |[expand=once]| \A & % name: B + |[expand=full]| \A \\ }; % name: Z +\mor A -> B -> Z; +\end{codi} +\end{tcblisting} + +\hfill$\therefore$\hfill\null + +The default behaviour is to avoid expansion in compliance with the principle +that \emph{names should be predictable from the \emph{literal} code}. +Furthermore, it is seldom wise to liberally expand tokens. + +There are circumstances in which it is useful to perform token expansion, +though. A useful application is procedural drawing. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\foreach [count=\r] \l in {A,B,C} + \foreach [count=\c] \n in {n-1,n,n+1} + \obj [expand=full] at (3em*\c,-2em*\r) {\l_{\n}}; +\mor (A_{n}) -> (B_{n+1}) -> (C_{n}) -> (B_{n-1}) -> (A_{n}); +\end{codi} +\end{tcblisting} + +In some cases finer control is needed. For instance, full expansion +yields unpractical results when parametrizing macros. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\foreach [count=\c] \m in {\lim,\prod} + \obj [expand=full] at (4em*\c,0) {\m F}; +\mor (protect mathop {relax kern z@ mathgroup + symoperators lim}nmlimits@ F) + -> (DOTSI prodop slimits@ F); +\end{codi} +\end{tcblisting} + +This explains why a setting to force a single expansion exists. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\foreach [count=\c] \m in {\lim,\prod} + \obj [expand=once] at (4em*\c,0) {\m F}; +\mor (lim F) -> (prod F); +\end{codi} +\end{tcblisting} +\newpage +\subsection{Names: replacement} +The character replacement behaviour of the naming routine can be configured +inside any \CoDi\ scope using various keys. + +\begin{lstlisting} +/codi/replace character = <character> with <character> +/codi/replace charcode = <charcode> with <character> +/codi/remove characters = <characters> +/codi/remove character = <character> +/codi/remove charcode = <charcode> +\end{lstlisting} + +You can set up a replacement for any character, using the character code for +the hardest to type, like {\ttfamily \textvisiblespace} or {\ttfamily \textbackslash}. + +\begin{tcblisting}{snippet, trim} +\begin{codi}[tetragonal] +\obj{ |[replace character=F with G]| \lim F & % name: lim G + |[remove character=F]| \lim F \\ % name: lim + |[replace charcode=92 with /]| \lim F & % name: /lim F + |[remove charcode=32]| \lim F \\ }; % name: limF +\mor (lim G) -> (lim) -> (/lim F) -> (limF); +\end{codi} +\end{tcblisting} + +\hfill$\therefore$\hfill\null + +The default behaviour is removal of the minimal set of universally annoying% +\footnote{The difficult part is not creating the names but having to type them.} +characters: {\ttfamily (),.:} have special meanings to \TikZ\ while +{\ttfamily \textbackslash} is impossible to type by ordinary means, so they're \emph{kaput}. + +Each one can be restored by replacing it with itself. Don't. + +Another egregiously bad idea is replacing characters with spaces. +It's tempting because it solves a somewhat common edge case. + +\begin{tcblisting}{snippet, trim} +\begin{codi}[tetragonal] +\obj{ \beta & F & b\eta \\ }; +\mor F -> beta; +\end{codi} +\end{tcblisting} + +Since characters in names are literal, this causes whitespace +duplication and names become inaccessible by ordinary means. + +\begin{tcblisting}{snippet, trim} +\begin{codi}[tetragonal] +\obj [replace charcode=92 with \space] + { \beta & b\eta & \beta \eta \\ }; +\mor beta -> (b eta) -> (beta \space eta); +\end{codi} +\end{tcblisting} + +The wise solution is writing better code. + +\begin{tcblisting}{snippet, trim} +\begin{codi}[tetragonal] +\obj{ \beta & F & b \eta \\ }; +\mor F -> beta; +\end{codi} +\end{tcblisting} + +\newpage +\subsection{Names: overwriting} +The name overwriting behaviour of the naming routine can be configured +inside any \CoDi\ scope using the \lstinline!overwrite! key. + +\begin{lstlisting} +/codi/overwrite = false | alias | true +\end{lstlisting} + +The three available settings correspond to different naming priorities. +A side by side comparison completely illustrates their meanings. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj{ |[overwrite=false] (A')| A & % names: A' (default) + |[overwrite=alias] (B')| B & % names: B', B + |[overwrite=true] (C')| C \\ }; % names: C +\mor A' -> B'; +\mor B -> C; +\end{codi} +\end{tcblisting} + +\hfill$\therefore$\hfill\null + +The default behaviour avoids overwriting explicit labels in order +to give you a simple means of naming conflict resolution. + +\begin{tcblisting}{snippet, trim} +\begin{codi}[tetragonal] +\obj { A & |(A')| A \\ + |(Z')| Z & Z \\ }; +\mor A -> A'; +\mor Z -> Z'; +\end{codi} +\end{tcblisting} + +Sometimes you might want an object to have both a literal and a +semantic alias. + +\begin{tcblisting}{snippet, trim} +\begin{codi} +\obj [overwrite=alias] { A & |(center)| B & |(right)| C \\ }; +\mor A -> B; +\mor center -> right; +\end{codi} +\end{tcblisting} + +The hard overwriting behaviour ignores any label except generated +ones; it exists for completeness and debugging purposes. +\newpage +\section{Styles: scopes} +\CoDi\ structures diagrams into five layers implemented with \TikZ. + +\begin{center} +\begin{tabular}{ccc} + \toprule + \CoDi's & represents an & using \TikZ's \\ + \midrule + \lstinline|diagram| & (commutative) diagram & \lstinline|tikzpicture| \\ + \lstinline|layout| & arrangement of vertices & \lstinline|matrix| \\ + \lstinline|object| & vertex & \lstinline|node| \\ + \lstinline|arrow| & edge between vertices & \lstinline|edge| \\ + \lstinline|label| & label of an edge & \lstinline|node| \\ + \bottomrule +\end{tabular} +\end{center} + +Each layer can be styled using \TikZ\ keys. + +Each layer possesses a default style: +\begin{lstlisting} +/codi/every diagram +/codi/every layout +/codi/every object +/codi/every arrow +/codi/every label +\end{lstlisting} + +You can customize them using \TikZ\ key handlers, \eg +\begin{lstlisting} +/codi/every label/.append style={red} +\end{lstlisting} + +Each layer possesses a library of commonplace styles: +\begin{lstlisting} +/codi/diagrams/ +/codi/layouts/ +/codi/objects/ +/codi/arrows/ +/codi/labels/ +\end{lstlisting} + +They are the proper place to find styles and define you own: +\begin{lstlisting} +/codi/arrows/fat/.style={ultra thick} +\end{lstlisting} + +Fully scoping keys is usually unnecessary, as \CoDi\ searches for keys +in the library of the layer it's in before falling back to \TikZ\ default +search algorithm. Here's some meta code demonstrating this: + +\begin{lstlisting} +\begin{codi}[<diagram keylist>] + \obj [<layout keylist>] { |[<object keylist>]| a & b \\ }; + \obj [<object keylist>] {x}; + \mor [<label keylist>]:[<arrow keylist>] + a [<label keylist>]:[<arrow keylist>] b; +\end{codi} +\end{lstlisting} + +\newpage +\section{Styles: diagrams} +\tikzset{ + versor/.style={ultra thick, black, ->, >=latex, line cap=round}, + checkers/.style={fill=teal!15}, + measure/.style={decorate, decoration={brace, amplitude=4pt, aspect=#1}}, + measure/.default=0.5, + label/.style={font=\scriptsize, outer sep=.5em, inner sep=0sp}, + dots/.style={fill=teal!50}, + label style/.style={label, outer sep=.2em, font={\ttfamily\tiny}}, + anchor style/.style={inner sep=0sp, outer sep=0sp, anchor=center}, + pin style/.style={pin distance=.75em, pin edge={thin, black, shorten <=3pt}, label style} +} + +\begin{marginfigure}[0cm] + \begin{subfigure}{\marginparwidth} + \begin{tikzpicture}[codi, tetragonal=base {0.2\marginparwidth} height {0.2*1.618\marginparwidth}] + % drawing area + \clip (-2.5,-2.5) rectangle (2.5,2.5); + % checkers and dots + \foreach \i in {-3, ..., 2} \foreach \j in {-3, ..., 2} { + \pgfmathparse{int(1+abs(\i)+abs(\j))} + \ifodd\pgfmathresult \fill [checkers] (\i,\j) rectangle +(1,1);\fi + \pgfmathparse{ \i == sign(\i) && \j == sign(\j) && abs(\i) != -abs(\j) } + \fill [fill/.expanded={\ifnum\pgfmathresult=1 red\else teal!50\fi}] + (\i,\j) circle (2pt); + } + % base circle + \fill [red, opacity=0.1] (1,1) -- (-1,1) -- (-1,-1) -- (1,-1) -- cycle; + % width marker + \draw + [measure, decoration=mirror, yshift=-3pt] + (0,0) -- (1,0) + node [label style, midway, below, yshift=-3pt] {base}; + % height marker + \draw + [measure=0.7, xshift=-3pt] + (0,0) -- (0,1) + node [label style, pos=0.7, left, xshift=-3pt] {height}; + % origin + \coordinate (O) at (0,0); + \node at (O) [anchor style, pin={[pin style]-135:{O}}] {}; + % neighbours + \node [anchor style, pin={[pin style]-45:{above=of O}}, above=of O] {}; + \node [anchor style, pin={[pin style]60:{above left=of O}}, above left=of O] {}; + \node [anchor style, pin={[pin style]90:{left=1 of O}}, left=1 of O] {}; + \node [anchor style, pin={[pin style]120:{below right=2 of O}}, below right=2 of O] {}; + \node [anchor style, pin={[pin style]-45:{below left=1 and 2 of O}}, below left=1 and 2 of O] {}; + % versors + \draw [versor] (0,0) -- (1,0); + \draw [versor] (0,0) -- (0,1); + \end{tikzpicture} + \subcaption*{Tetragonal}\bigskip + \end{subfigure} + \begin{subfigure}{\linewidth} + \begin{tikzpicture}[codi, hexagonal=horizontal side {0.4*\marginparwidth} angle 60] + % drawing area + \clip (-2.5,-2.5) rectangle (2.5,2.5); + % checkers and dots + \foreach \i in {-4, ..., 2} \foreach \j in {-3, ..., 2} { + \pgfmathparse{int(abs(\i)+abs(\j))} + \ifodd\pgfmathresult\else \fill [checkers] (\i,\j) -- +(1,1) -- +(2,0);\fi + \pgfmathsetmacro\dotsize{isodd(\pgfmathresult)?1:2} + \fill [fill/.expanded={\ifnum\pgfmathresult=2 red\else teal!50\fi}] + (\i,\j) circle (\dotsize pt); + } + % base circle + \fill [red, opacity=0.1] + (2,0) -- (0,2) -- (-2,0) -- (0,-2) -- cycle; + % side marker + \draw [measure, decoration=mirror, yshift=-3pt] + (0,0) -- (2,0) + node [label style, midway, below, yshift=-3pt] {side}; + % angle marker + \draw (0.66*1.7cm, 0) + arc (0:30:0.66*1.7cm) + node [label style, above right] {angle} + arc (30:60:0.66*1.7cm); + % origin + \coordinate (O) at (0,0); + \node at (O) [anchor style, pin={[pin style]-135:{O}}] {}; + % neighbours + \node [anchor style, pin={[pin style]-45:{above=of O}}, above=of O] {}; + \node [anchor style, pin={[pin style]60:{above left=of O}}, above left=of O] {}; + \node [anchor style, pin={[pin style]90:{left=1 of O}}, left=1 of O] {}; + \node [anchor style, pin={[pin style]120:{below right=2 of O}}, below right=2 of O] {}; + \node [anchor style, pin={[pin style]-45:{below left=1 and 2 of O}}, below left=1 and 2 of O] {}; + % versors + \draw [versor] (0,0) -- (1,0); + \draw [versor] (0,0) -- (0,1); + \end{tikzpicture} + \subcaption*{Hexagonal (horizontal)}\bigskip + \end{subfigure} + \begin{subfigure}{\linewidth} + \begin{tikzpicture}[codi, hexagonal=vertical side {0.2*\marginparwidth*2/sqrt(3)} angle 60] + % drawing area + \clip (-2.5,-2.5) rectangle (2.5,2.5); + % checkers and dots + \foreach \i in {-3, ..., 2} \foreach \j in {-4, ..., 3} { + \pgfmathparse{int(1+abs(\i)+abs(\j))} + \ifodd\pgfmathresult \fill [checkers] (\i,\j) -- +(1,1) -- +(0,2);\fi + \pgfmathsetmacro\dotsize{isodd(\pgfmathresult)?2:1} + \fill [fill/.expanded={\ifnum\pgfmathresult=3 red\else teal!50\fi}] + (\i,\j) circle (\dotsize pt); + } + % base circle + \fill [red, opacity=0.1] (2,0) -- (0,2) -- (-2,0) -- (0,-2) -- cycle; + % side marker + \draw [measure=0.3, xshift=-3pt] + (0,0) -- (0,2) node [label style, pos=0.3, left, xshift=-3pt] {side}; + % angle marker + \draw + ([shift=(30:0.66*0.982cm)]0,0) + arc (30:60:0.66*0.982cm) + node [label style, above right] {angle} + arc (60:90:0.66*0.982cm); + % origin + \coordinate (O) at (0,0); + % neighbours + % versors + \draw [versor] (0,0) -- (1,0); + \draw [versor] (0,0) -- (0,1); + \end{tikzpicture} + \subcaption*{Hexagonal (vertical)}\bigskip + \end{subfigure} + %% \caption*{Diagram grid examples} +\end{marginfigure} + +Diagrams can be laid over regular grids: + +\begin{lstlisting} +/codi/diagrams/tetragonal=base <length> height <length> + (@\hfill@) (default: base 4.5em height 2.8em) +\end{lstlisting} + +\begin{lstlisting} +/codi/diagrams/hexagonal=<direction> side <length> angle <angle> + (@\hfill@) (default: horizontal side 4.5em angle 60) +\end{lstlisting} + +When one of these keys is used +\begin{itemize}[noitemsep] + \item the versors of the \NiceURL{coordinate system}{http://texdoc.net/texmf-dist/doc/generic/pgf/pgfmanual.pdf\#page=357} are changed, + \item the \NiceURL{node positioning}{http://texdoc.net/texmf-dist/doc/generic/pgf/pgfmanual.pdf\#page=229} is set up to lay them on grid, + \item and the corresponding key will be applied to all layouts. +\end{itemize} + +The pictures show the key parameters, versors, and a unitary grid. + +This setup allows you to mix coordinates and +relative positioning keys to arrange objects. + +As usual, relative positioning keys can accept two components, a radius, +or nothing at all (which defaults to a certain radius). + +When using a radius (or defaulting to $1$) +the tetragonal grid uses Manhattan distance to +lay objects along concentric rectangles. + +When using a radius (or defaulting to $2$) +the hexagonal grid% +\footnote{which in truth is built upon a tetragonal grid} +uses Chebyshev distance to +lay objects along concentric rhombi. + +To clarify, a few relative positioning keys are drawn along +with red zones displaying the default radii around the origins. +\newpage +\section{Styles: layouts} +Layouts can be laid over regular grids: + +\begin{lstlisting} +/codi/layouts/tetragonal=base <length> height <length> + (@\hfill@) (default: base 4.5em height 2.8em) +\end{lstlisting} + +\begin{lstlisting} +/codi/layouts/hexagonal=<direction> side <length> angle <angle> + (@\hfill@) (default: horizontal side 4.5em angle 60) +\end{lstlisting} + +When one of these keys is used the layout columns and rows will be +spaced and offset in order to reproduce the grids given by diagram styles. + +\begin{tcblisting}{snippet, trim={2 and -1}} +\begin{codi} + \obj [hexagonal=horizontal side 1.5em angle 60] { + A & B & \\ + C & D & E \\ + F & G & \\ + }; +\end{codi} +\end{tcblisting} + +\begin{tcblisting}{snippet, trim={2 and -1}} +\begin{codi} + \obj [hexagonal=vertical side 1.5em angle 60] { + A & C & F \\ + B & D & G \\ + & E & \\ + }; +\end{codi} +\end{tcblisting} + +Note that \emph{each row must have the same number of cells}% +\footnote{this is different from the behaviour of, say, tables} +or the spacing will be incorrect. +\newpage +\section{Styles: objects} +No styles are available at the moment. +\newpage +\section{Styles: arrows} +\begin{lstlisting} +/codi/arrows/crossing over +/codi/arrows/crossing over/clearance=<length> (@\hfill@) (default: 0.5ex) +/codi/arrows/crossing over/color=<color> (@\hfill@) (default: white) +\end{lstlisting} + +This key a provides the configurable illusion of an arrow passing +over a \emph{previously drawn} one. + +\begin{tcblisting}{snippet, trim={3 and -1}} +\begin{codi}[tetragonal=base 4.5em height 1em] +\obj { A & B \\ D & C \\}; +\mor A -> C; +\mor :[crossing over] D -> B; +\end{codi} +\end{tcblisting} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{lstlisting} +/codi/arrows/slide=<length> +\end{lstlisting} + +This key slides an arrow backward (negative) and forward (positive) along its direction of the given length. + +\begin{tcblisting}{snippet, trim={3 and -1}} +\begin{codi}[tetragonal=base 4.5em height 1em] +\obj { A & B \\ C & D \\ E & F \\ }; +\mor :[slide=-.3em, red] A -> B; +\mor C -> D; +\mor :[slide=+.3em, blue] E -> F; +\end{codi} +\end{tcblisting} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{lstlisting} +/codi/arrows/shove=<length> +\end{lstlisting} + +This key shoves an arrow to the left (negative) and to the right (positive) with respect to its direction of the given length. + +\begin{tcblisting}{snippet, trim={3 and -1}} +\begin{codi} +\obj { A & B \\ }; +\mor :[shove=-.3em, red] A -> B; +\mor A -> B; +\mor :[shove=+.3em, blue] A -> B; +\end{codi} +\end{tcblisting} +\newpage +\section{Styles: labels} +\begin{lstlisting} +/codi/labels/mid +\end{lstlisting} + +This key places a label in the middle of an arrow. + +\begin{tcblisting}{snippet, trim={3 and -1}} +\begin{codi} +\obj { A & B \\ }; +\mor [mid] A f:-> B; +\end{codi} +\end{tcblisting} +\newpage +\section{Gallery} +% \makeatletter +% \newcommand\prev{\the\tikz@lastxsaved,\the\tikz@lastysaved} +% \makeatother + +The remainder of the text is just commented examples. + +\clearpage + +\subsection{Snake} + +\begin{tcblisting}{gallery} +\begin{codi}[tetragonal] + \obj{ & \ker a & \ker b & \ker c & \\ + & A & B & C & 0 \\ + |(0')| 0 & A' & B' & C' & \\ + & \coker a & \coker b & \coker c & \\ }; + + \mor (ker a) -> (ker b) -> (ker c); + \mor (coker a) -> (coker b) -> (coker c); + \mor A f :-> B g :-> C -> 0; + \mor 0' -> A' f':-> B' g':-> C'; + + \mor[near start] (ker a) -> A a:-> A' -> (coker a); + \mor[near start] (ker b) -> B b:-> B' -> (coker b); + \mor[near start] (ker c) -> C c:-> C' -> (coker c); + + \draw[/codi/arrows/crossing over, ->, rounded corners, >=stealth] + (ker c) -- ++( 0.6,0) -- ++(0,-1.55) + -- ++(-3.2,0) -- ++(0,-1.45) -- (coker a); +\end{codi} +\end{tcblisting} + +\clearpage + +\subsection{The fourth associahedron} + +\begin{tcblisting}{gallery} +\begin{codi} +% From the LaTeX preamble: +% \usepackage{newunicodechar} +% \newunicodechar{ı}{\mathbf 1} +% \newunicodechar{×}{\otimes} + + \foreach [count=\n] \o in { + ((w×x)×y)×x, + (w×(x×y))×x, + w×((x×y)×x), + w×(x×(y×x)), + (w×x)×(y×x) + } \obj (\n) at (72*\n:7em) {\o}; + + \mor 1 "a_{w,x,y}×ı_z": -> 2 + "a_{w,x×y,z}": -> 3 + "ı_w×a_{x,y,z}": -> 4; + \mor * "a_{w×x,y,z}": -> 5 + "a_{w,x,y×z}": -> *; +\end{codi} +\end{tcblisting} + +\clearpage + +\subsection{Pullback \& pushout} + +\begin{tcblisting}{gallery} +\begin{codi}[hexagonal] + \obj{ |(pb)| A \times_Z B & B \\ + A & Z \\ }; + \obj[above left=of pb] {Q}; + + \mor[swap] pb p_1:-> A f:-> Z; + \mor * p_2:-> B g:-> *; + + \mor[swap]:[bend right] Q q_1:-> A; + \mor :[bend left] * q_2:-> B; + \mor [mid]:[dashed] * u:-> pb; +\end{codi} +\end{tcblisting} + +\begin{tcblisting}{gallery} +\begin{codi}[hexagonal] + \obj{ Z & B \\ + A & |(po)| A \sqcup_Z B \\ }; + \obj[below right=of po] {Q}; + + \mor[swap] Z f:-> A i_1:-> po; + \mor * g:-> B i_2:-> *; + + \mor[swap]:[bend right] A j_1:-> Q; + \mor :[bend left] B j_2:-> *; + \mor [mid]:[dashed] po u:-> *; +\end{codi} +\end{tcblisting} + +\clearpage + +\subsection{Complexes sequence} + +\begin{tcblisting}{gallery} +\begin{codi} + \obj (M) { & \vdots & \vdots & \vdots & \\ + 0 & A_{n+1} & B_{n+1} & C_{n+1} & 0 \\ + 0 & A_{n} & B_{n} & C_{n} & 0 \\ + 0 & A_{n-1} & B_{n-1} & C_{n-1} & 0 \\ + & \vdots & \vdots & \vdots & \\ }; + + \foreach \n/\row in {n+1/2, n/3, n-1/4} + \mor (M-\row-1) -> (A_{\n}) "\alpha_{\n}":-> (B_{\n}) + "\beta_{\n}":-> (C_{\n}) -> (M-\row-5); + + \foreach \l/\col/\q in {A/2/, B/3/', C/4/''} + \mor (M-1-\col) -> (\l_{n+1}) "\partial\q_{n+1}":-> (\l_{n}) + "\partial\q_{n}" :-> (\l_{n-1}) -> (M-5-\col); +\end{codi} +\end{tcblisting} + +\clearpage + +\subsection{Braid} + +% TODO: there's a bug here. If one does \begin{codi}[ l/.style={bend left} +% TODO: (note the space before l) then it's not recognized. Investigate. +\begin{tcblisting}{gallery} +\begin{codi}[l/.style={bend left}, r/.style={bend right} ] + \obj [ hexagonal=horizontal side 6em angle 45, remove characters=H_\{q+\} ] { + H_{q+2}(X) & H_{q+2}(X,Y) & H_{q+1}(Y,Z) & H_{q}(Z) \\ + H_{q+2}(Y) & H_{q+2}(X,Z) & H_{q+1}(Y) & H_{q+1}(X,Z) \\ + H_{q+2}(Y,Z) & H_{q+1}(Z) & H_{q+1}(X) & \\ + }; + + \mor :[blue] 2Y -> 2X l,-> 2XY -> 1Y -> 1X; + \mor :[green] 2Y -> 2YZ r,-> 1Z -> 1Y -> 1YZ l,-> Z; + \mor :[cyan] 2X -> 2XZ -> 1Z r,-> 1X -> 1XZ -> Z; + \mor :[red] 2YZ -> 2XZ -> 2XY l,-> 1YZ -> 1XZ; +\end{codi} +\end{tcblisting} + +\clearpage + +\subsection{Hammock} + +\begingroup\catcode`~=12 +\begin{tcblisting}{gallery} +\begin{codi}[x=4em, y=-3em, node distance=1 and 1, + sim/.style={sloped, auto, + edge node={node[every edge quotes][/velos/install quote + handler,"\sim", anchor=south, outer sep=-.15em]} + }, + ~>/.style={->, sim}, + <~/.style={<-, sim}, + ../.style={line width=.25ex, dash pattern=on 0sp off .75ex, line cap=round}, + remove characters=_\{\}, + expand=full, + ] + + \foreach [count=\c] \col in {1, 2, 3, n} + \foreach [count=\r] \row in {K_{\col}, C_{0\col}, \vdots, C_{m\col}, L_{\col}} + \obj [name/.expanded={\ifnum\r=3 vdots\col\fi}] at (\c,\r) {\row}; + + \obj [left=of vdots1] {X}; + \obj [right=of vdotsn] {Y}; + + \foreach \col in {1, 2, 3, n} + \mor (K\col) ~> (C0\col) ~> (vdots\col) ~> (Cm\col) ~> (L\col); + + \foreach \row in {K, C0, Cm, L} { + \mor (\row1) -> (\row2) <~ (\row3) .. (\row n); + \mor X <~ + -> Y; + } +\end{codi} +\end{tcblisting} +\endgroup + + +% \input{test} + +\end{document} diff --git a/Master/texmf-dist/tex/context/third/commutative-diagrams/t-commutative-diagrams.tex b/Master/texmf-dist/tex/context/third/commutative-diagrams/t-commutative-diagrams.tex new file mode 100644 index 00000000000..2c03eaa9486 --- /dev/null +++ b/Master/texmf-dist/tex/context/third/commutative-diagrams/t-commutative-diagrams.tex @@ -0,0 +1,16 @@ +% +% 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. +% + +\writestatus{loading}{2020/06/06 1.0.0 CoDi: Commutative Diagrams for TeX} +\startmodule[commutative-diagrams] +\usemodule[tikz] +\usetikzlibrary[commutative-diagrams] +\let\startcodi\kDRammaOpen +\let\stopcodi\kDRammaShut +\stopmodule +\endinput 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}}% + }} diff --git a/Master/texmf-dist/tex/latex/commutative-diagrams/commutative-diagrams.sty b/Master/texmf-dist/tex/latex/commutative-diagrams/commutative-diagrams.sty new file mode 100644 index 00000000000..63bfde447f4 --- /dev/null +++ b/Master/texmf-dist/tex/latex/commutative-diagrams/commutative-diagrams.sty @@ -0,0 +1,14 @@ +% +% 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. +% + +\RequirePackage{tikz}%[2013/12/13] % pgf version 3.0.0 required +\ProvidesPackage{commutative-diagrams}[2020/06/06 1.0.0 CoDi: Commutative Diagrams for TeX] +\usetikzlibrary{commutative-diagrams} +\let\codi\kDRammaOpen +\let\endcodi\kDRammaShut +\endinput diff --git a/Master/texmf-dist/tex/latex/commutative-diagrams/kodi.sty b/Master/texmf-dist/tex/latex/commutative-diagrams/kodi.sty new file mode 100644 index 00000000000..9443a2d8b01 --- /dev/null +++ b/Master/texmf-dist/tex/latex/commutative-diagrams/kodi.sty @@ -0,0 +1,60 @@ +% +% 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. +% + +\RequirePackage{commutative-diagrams} + +\PackageWarningNoLine{kodi}{this package is only a compatibility layer +to help you migrate from 'kodi' to 'commutative-diagrams'. It is NOT +intended for production use. Please solve all other warnings and then +switch to 'commutative-diagrams'} + +% TikZ keys: /kodi/**/* -> /codi/**/* + +\pgfkeys{ + /handlers/.unknown/.code={% + \def\pgfkeysisdescendantof@impl/##1/##2\pgf@@eov{% + \def\wot{##1}% + \def\asd{kD}% + \ifx\wot\asd + \def\tmp{/codi/##2}% + \PackageWarning{kodi}{automatically remapped key '\pgfkeyscurrentkey' + to key '\tmp'. Please switch to the latter} + \ifx\pgfkeyscurrentvalue\pgfkeysnovalue + \expandafter\pgfkeysalso\expandafter{\tmp}% + \else + \expandafter\expandafter\expandafter\pgfkeysalso\expandafter\expandafter\expandafter{\expandafter\expandafter\expandafter\tmp\expandafter=\pgfkeyscurrentvalue}% + \fi + \else + % NOTE: this is the default /handlers/.unknown/.code + \def\pgf@marshal{\pgfkeysvalueof{/errors/unknown key/.@cmd}}% + {\expandafter\expandafter\expandafter\pgf@marshal\expandafter\expandafter\expandafter{\expandafter\pgfkeyscurrentkey\expandafter}\expandafter{\pgfkeyscurrentvalue}\pgfeov}% + \fi + }% + \expandafter\pgfkeysisdescendantof@impl\pgfkeyscurrentkey\pgf@@eov + } +} + +% TikZ key: /tikz/kodi -> /tikz/codi + +\pgfkeys{ + /tikz/kodi/.code={% + \PackageWarning{kodi}{automatically remapped key '/tikz/kodi' + to key '/tikz/codi'. Please switch to the latter}% + \pgfkeysalso{/tikz/codi}% + } +} + +% Environment: kodi -> codi + +\def\kodi{% + \PackageWarning{kodi}{automatically remapped environment 'kodi' + to environment 'codi'. Please switch to the latter}% + \codi} +\let\endkodi\endcodi + +\endinput diff --git a/Master/texmf-dist/tex/plain/commutative-diagrams/commutative-diagrams.tex b/Master/texmf-dist/tex/plain/commutative-diagrams/commutative-diagrams.tex new file mode 100644 index 00000000000..f9ac654c651 --- /dev/null +++ b/Master/texmf-dist/tex/plain/commutative-diagrams/commutative-diagrams.tex @@ -0,0 +1,14 @@ +% +% 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. +% + +\input tikz.tex +% TODO: loading message +\usetikzlibrary{commutative-diagrams} +\let\codi\kDRammaOpen +\let\endcodi\kDRammaShut +\endinput diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 63476157ba2..0aede9a2afc 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -182,7 +182,7 @@ my @TLP_working = qw( colorsep colorspace colortab colortbl colorwav colorweb colourchange combelow combine combinedgraphics combofont comfortaa comicneue - comma commado commath commedit comment + comma commado commath commedit comment commutative-diagrams compactbib compare competences complexity components-of-TeX comprehensive computational-complexity concepts concmath concmath-fonts concprog concrete diff --git a/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc b/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc index 0cc68b76ffd..0ec91797ce8 100644 --- a/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-mathscience.tlpsrc @@ -53,6 +53,7 @@ depend clrscode depend clrscode3e depend codeanatomy depend commath +depend commutative-diagrams depend complexity depend computational-complexity depend concmath diff --git a/Master/tlpkg/tlpsrc/commutative-diagrams.tlpsrc b/Master/tlpkg/tlpsrc/commutative-diagrams.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/commutative-diagrams.tlpsrc |