% % 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. % % βέλος • (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, % NOTE: next line is required by recent versions of ConTeXt /handlers/first char syntax/the character U+0022 'quotation mark'/.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}% \kDGobbleHardTok }{% \kDVelosSource\expandafter{\the\kDVelosTarget} \kDVelosFetchEdgeThen {\kDVelosFetchTargetThen {\kDVelosDrawFetchedEdgeThen \kDVelosMaybeChainEdge}}% }}