%
% CoDi: Commutative Diagrams for TeX
% Copyright (c) 2015-2024 Paolo Brasolin <
[email protected]>
% SPDX-License-Identifier: MIT
%
% This file is part of CoDi 1.1.2, released on 2024/04/22 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
{\ifkDDTSPrevSpace\kDDTSHasTrailtrue\else\kDDTSHasTrailfalse\fi\kDGobbleHardTok}
{\kDIfNextSoftCh\kDBlankSpace
{\kDDTSPrevSpacetrue\expandafter\kDDTSGob\kDGobbleSoftTok}
{\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}