summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/commutative-diagrams/tikzlibrarycommutative-diagrams.katharizo.code.tex
blob: bafba23823ff55a70e2543058f68505e081374c5 (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
%
% CoDi: Commutative Diagrams for TeX
% Copyright (c) 2015-2024 Paolo Brasolin <paolo.brasolin@gmail.com>
% SPDX-License-Identifier: MIT
%
% This file is part of CoDi 1.1.1, released on 2024/03/29 under MIT license.
%

% καθαρίζω • (katharízo)
%   1. clean, wash
%   2. peel, descale
%   3. (slang) kill

% Katharizo is a detokenization/sanitation mechanism.
% It produces "safe" strings from tokens.

% ,-- input          input hook
% `-> expander ---.  performs expansion according to
% ,---[expand]----'    macro expansion configuration
% `-> expanded ---.  pre-sanitation hook
% ,-- sanitizer <-'  performs detokenization and sanitation according to
% `---[replace]---.    character replacement configuration
% ,-- sanitized <-'  pre-output hook
% `-> output         output hook

%==[ input stage ]==============================================================

\pgfqkeys{/katharizo/input}{
  .forward to=/katharizo/expander
}

%==[ expansion stage ]==========================================================

\pgfqkeys{/katharizo/expand}{.is choice,
  once/.style={/katharizo/expander/.style={/katharizo/expanded/.expand once={##1}}},
  full/.style={/katharizo/expander/.style={/katharizo/expanded/.expanded={##1}}},
  none/.style={/katharizo/expander/.style={/katharizo/expanded={##1}}},
  none % default is no expansion
}

\pgfqkeys{/katharizo/expanded}{
  .forward to=/katharizo/sanitizer
}

%==[ sanitation stage ]=========================================================

\pgfqkeys{/katharizo}{
  replace charcode/.code args={#1 with #2}{%
    % TODO: would a \string be of any use? or at least a stringification?
    \pgfkeys{/katharizo/replacements/characters/#1/.initial={#2}}%
  },
  remove charcode/.style={/katharizo/replace charcode={{#1} with {}}},
  remove charcodes/.style args={#1}{%
    /katharizo/remove charcodes loop={#1 \kD},
  },
  remove charcodes loop/.code args={#1 #2\kD}{%
    % \message{|||#1|#2|||}
    \ifx\relax#1\else\pgfkeys{/katharizo/remove charcode={#1}}\fi
    \ifx\relax#2\else\pgfkeys{/katharizo/remove charcodes loop={#2\kD}}\fi
  },
  replace character/.code args={#1 with #2}{%
    \edef\kDFoo{\number`#1}% TODO: can I inline this?
    % TODO: would a \string be of any use? or at least a stringification?
    \pgfkeys{/katharizo/replacements/characters/\kDFoo/.initial={#2}}%
  },
  remove character/.style={/katharizo/replace character={{#1} with {}}},
  remove characters/.code args={#1#2}{%
    \ifx\relax#1\else\pgfkeys{/katharizo/remove character={#1}}\fi
    \ifx\relax#2\else\pgfkeys{/katharizo/remove characters={#2}}\fi
  },
  remove characters={(),.:},
  remove charcode=92,% \ backslash
}

\pgfqkeys{/katharizo}{
  sanitizer/.code={
    % TODO: token replacement routine? Would that be useful?
    \kDKatharizoStringify#1\kD
    \expandafter\kDKatharizoSanitize\the\kDKatharizoStringified\kD
    \pgfkeysalso{/katharizo/sanitized/.expanded=\the\kDKatharizoSanitized}
    % \message{^^J:::\the\kDKatharizoSanitized:::^^J}
  }
}

\pgfqkeys{/katharizo/sanitized}{
  .forward to=/katharizo/output
}

%==[ output stage ]=============================================================

% NOTE: this must be defined/hooked before calling input
\pgfqkeys{/katharizo/output}{
  .code={}
}

\newtoks\kDKatharizoStringified

\def\kDKatharizoStringify#1\kD{
  \def\kDFoo{#1}
  \edef\kDFoo{\meaning\kDFoo}
  % NOTE: in recent versions of ConTeXt \macro does not output an arrow
  \ifdefined\contextversion\def\kDAct##1:##2\kD{##2}\else\def\kDAct##1:->##2\kD{##2}\fi
  \edef\kDFoo{\expandafter\kDAct\kDFoo\kD}
  \kDKatharizoStringified\expandafter{\kDFoo}
}

\newtoks\kDKatharizoSanitized

\def\kDKatharizoSanitize#1\kD{
  \pgfkeysifdefined{/katharizo/replacements/characters/32}%
    {\edef\kDKatharizoSSpace{\pgfkeysvalueof{/katharizo/replacements/characters/32}}}%
    {\edef\kDKatharizoSSpace{\space}}%
  \def\kDKatharizoSAppendSpace
    {\edef\kDAct{\noexpand\kDKatharizoSanitized={\the\kDKatharizoSanitized\kDKatharizoSSpace}}\kDAct}
  \kDKatharizoSanitized={}
  \kDKatharizoSString#1 \kD}% NOTE: the whitespace is a mandatory string terminator

\def\kDKatharizoSString#1 #2\kD{%
  \ifx\relax#1\else                       % if string head word is not empty
    \kDKatharizoSWord#1\kD                % parse string head word
    \if#2\space\else                      % if string tail is not the space terminator
      \ifx\relax#2\else                   %   if string tail is not empty
        \kDKatharizoSAppendSpace\fi\fi\fi %     append space substitute to output
  \ifx\relax#2\else                       % if string tail is not empty
    \kDKatharizoSString#2\kD\fi}          %   recurse on string tail

\def\kDKatharizoSWord#1#2\kD{%
  \kDKatharizoSCharacter#1\kD   % parse word head character
  \ifx\relax#2\else             % if word tail is not empty
    \kDKatharizoSWord#2\kD\fi}  %   recurse on word tail

\def\kDKatharizoSCharacter#1\kD{%
  \pgfkeysifdefined{/katharizo/replacements/characters/\number`#1}%
    {\edef\kDFoo{\pgfkeysvalueof{/katharizo/replacements/characters/\number`#1}}}%
    {\edef\kDFoo{#1}}%
  \edef\kDAct{\noexpand\kDKatharizoSanitized={\the\kDKatharizoSanitized\kDFoo}}%
  \kDAct}