% % CoDi: Commutative Diagrams for TeX % Copyright (c) 2015-2020 Paolo Brasolin % 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}