% % CoDi: Commutative Diagrams for TeX % Copyright (c) 2015-2024 Paolo Brasolin % SPDX-License-Identifier: MIT % % This file is part of CoDi 1.1.2, released on 2024/04/22 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} % Use straight quotes in code listings. https://tex.stackexchange.com/a/145417/82186 \usepackage{textcomp} \lstset{upquote=true} % 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,\pgfqkeys, \ar, \psset,\everypsbox,\ncline,\ncarc, \xymatrix, }, texcsstyle=*\bfseries, % morestring=[b]", commentstyle=\itshape\color{black!60}, frame=none, % extendedchars=false, inputencoding=utf8, } \lstdefinestyle{metacode}{ 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]{<}{>}, literate={XOR}{{$\vert$}}1 {:}{{\textbf{:}}}1 {:=}{{$\equiv$}}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}}} %==[ Import tikz-cd arrow styles ]=============================================? \usepackage{tikz-cd} \pgfqkeys{/codi}{every arrow/.append style={/ektropi/add=/tikz/commutative diagrams}} %==[ 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.1.2}\\[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}[style=metacode] \obj@opt@ @/opt@{};(@ \marginpar{\scriptsize {\color{orange!80!black}Orange fragments} are optional.}@) \obj@opt@ @/opt@{}; \end{lstlisting} Layouts are described using the customary \TeX\ tabular syntax. \begin{lstlisting}[style=metacode] := (@\itshape\underbar{ }@)(@ \marginpar{\scriptsize \underbar{Underlined fragments} can repeat one or more times.}@) := (@\itshape\color{orange!80!black}\underbar{ }@) := \\ @opt@[]@/opt@ := @opt@|| @/opt@ := & @opt@[]@/opt@ \end{lstlisting} The discretionary options syntax is analogous to standard \TikZ\ nodes and matrices, respectively. \begin{lstlisting}[style=metacode] := (@\itshape\color{orange!80!black}\underbar{[object keylist]}@) @opt@() at ()@/opt@ := (@\itshape\color{orange!80!black}\underbar{[layout keylist]}@) @opt@() at ()@/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}[style=metacode] \mor@opt@ @/opt@(@ \itshape\underbar{\textvisiblespace\textvisiblespace}@);(@ \marginpar{\scriptsize Whitespace marked as \textvisiblespace\ is mandatory.}@) \end{lstlisting} Source and target objects are referred to by their name. \begin{lstlisting}[style=metacode] := @nws@()@/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}[style=metacode] := @opt@ : @/opt@ := @nws@""@/nws@ XOR (@\underbar{[{\itshape "",