summaryrefslogtreecommitdiff
path: root/graphics/pgf/contrib/commutative-diagrams/tikzlibrarycommutative-diagrams.koinos.code.tex
blob: 5e15eab768b6787bc2edac846a11d6bb3da3250a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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.1, released on 2020/06/11 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}