-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlist.tex
183 lines (172 loc) · 6.42 KB
/
list.tex
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
% #1 name (allows quicker access), #2 comma-separated elements
% note: your name (#1) must be a valid command sequence to work!
\def\chr@list#1#2{%
\chr@tempcount=\z@\relax
\def\chr@listcheck{#2}%
\ifx\chr@listcheck\chr@empty\else
\chr@for\chr@elem:={#2}\do{%
% you gotta love tex :3 we have to expand \chr@elem once to persist the content
\expandafter\expandafter\expandafter\def
\expandafter\csname\expandafter#1@\expandafter\the\expandafter\chr@tempcount
\expandafter\endcsname\expandafter{\chr@elem}%
\chr@step\chr@tempcount
}%
\fi
\expandafter\def\csname#1\endcsname##1{\csname#1@##1\endcsname}%
\expandafter\edef\csname#1length\endcsname{\the\chr@tempcount}%
\chr@verbose{Created list '#1' (\the\chr@tempcount).}%
}
\chr@list{@empty@list}{}
% FIXME: we should just use the current listname but is it worth the register and scoping?
\def\chr@break{\chr@tempcountc=100000}
% #1 name, #2 and #3 are the indices
\def\chr@list@swap#1#2#3{%
% the worse, the cake is a lie shuffle!
\chr@list@let\chr@swp@temp=#1[#2]%
\expandafter\chr@list@let\csname #1@#2\endcsname=#1[#3]%
\expandafter\let\csname #1@#3\endcsname=\chr@swp@temp
}
\def\chr@list@print#1{%
\chr@list@to@string\chr@tmp{#1}{\csname #1length\endcsname}%
\chr@tmp
}
\def\chr@list@log#1{\begingroup
\ifnum\csname#1length\endcsname=\z@\relax
\chr@log{List #1 is empty}%
\else
\chr@list@to@string\chr@tmp@list{#1}{\csname#1length\endcsname}%
\chr@log{List #1: \chr@tmp@list}%
\fi
\endgroup}
% collects the first #3 elements of the list with name #2 in #1
\def\chr@list@to@string#1#2#3{\begingroup
\global\let#1=\chr@empty
\chr@tempcount=\z@
\ifnum\csname#2length\endcsname=\z@\relax \else
\ifnum#3>\z@\relax
\chr@list@iter\chr@elem:=#2\do{%
\ifnum\chr@tempcount=\z@\relax
\expandafter\chr@gapp\expandafter#1\expandafter{\chr@elem}%
\else
\expandafter\chr@gapp\expandafter#1\expandafter{\expandafter,\chr@elem}%
\fi
\chr@step\chr@tempcount
\ifnum\the\chr@tempcount<#3\else
\chr@break
\fi
}%
\fi\fi
% \chr@verbose{List #2 to string: '#1' (#3)}%
\endgroup}
% similar to \chr@for but does the expansion for the list under the hood :3
\def\chr@list@iter#1:=#2\do#3{%
\chr@tempcountc=\z@
\edef\chr@length{\csname#2length\endcsname}%
\ifnum\chr@length>0\relax
\loop
\expandafter\let\expandafter#1\expandafter=\csname#2@\the\chr@tempcountc\endcsname
#3%
\chr@step\chr@tempcountc
% automatic break insertion
\ifnum\chr@tempcountc<\chr@length
\repeat
\fi
}
% get the #3th element of list #2 and store it into #1
\def\chr@list@let#1=#2[#3]{%
\expandafter\let\expandafter#1\expandafter=\csname#2@#3\endcsname
}
\def\chr@list@set#1[#2]=#3;{%
\expandafter\def\csname#1@#2\endcsname{#3}%
}
\def\chr@list@eset#1[#2]=#3;{%
\expandafter\edef\csname#1@#2\endcsname{#3}%
}
\def\chr@list@eget#1=#2[#3]{%
\expandafter\edef\expandafter#1\expandafter{\expandafter\expandafter\expandafter\chr@strip@meaning\expandafter\meaning\csname#2@\the\chr@tempcount\endcsname}
}
% TODO: optimize?
\def\chr@list@concat#1#2#3{%
\chr@list{#1}{}%
\def\chr@tmp@listname{#1}%
\ifnum\csname#2length\endcsname=\z@\relax \else
\chr@list@iter\chr@elem:=#2\do{%
\expandafter\chr@list@append\expandafter{\expandafter\chr@tmp@listname\expandafter}\expandafter{\chr@elem}%
}%
\fi
\ifnum\csname#3length\endcsname=\z@\relax \else
\chr@list@iter\chr@elem:=#3\do{%
\expandafter\chr@list@append\expandafter{\expandafter\chr@tmp@listname\expandafter}\expandafter{\chr@elem}%
}%
\fi
\chr@verbose{Lists: #1 = #2 ++ #3 (length: \csname#1length\endcsname).}%
}
% remove the first occurence of #2 in list with name #1
\def\chr@list@remove#1#2{%
\chr@verbose{Remove first occurrence of #2 in list #1.}%
\chr@list@log{#1}%
\def\chr@scndelem{#2}%
\chr@list{#1@tmp}{}%
\def\chr@tmplistname{#1@tmp}%
\chr@list@iter\chr@elem:=#1\do{%
\ifx\chr@elem\chr@scndelem
\else
\expandafter\chr@list@append\expandafter{\expandafter\chr@tmplistname\expandafter}\expandafter{\chr@elem}%
\fi
}%
\chr@list@concat{#1}{\chr@tmplistname}{@empty@list}% poor mans overwrite, code getting really horrible here... could use some thought
\chr@list@log{#1}%
}
% names of both lists, expands to \chr@true if equal, \chr@false otherwise
% compares on the values as stored in the list
\def\chr@list@equal#1#2{\begingroup
\chr@verbose{Check if lists #1 and #2 are equal.}%
\chr@tempcount=\csname#1length\endcsname\relax
\chr@tempcountb=\csname#2length\endcsname\relax
\ifnum\chr@tempcount=\chr@tempcountb
\global\chr@result@true
\chr@tempcount=\z@
% allow loop
\chr@tempif@true
\loop
\chr@list@eget\@chr@left=#1[\the\chr@tempcount]%
\chr@list@eget\@chr@right=#2[\the\chr@tempcount]%
% compar
\ifx\@chr@left\@chr@right
% \chr@verbose{Lists are equal at index \the\chr@tempcount.}%
\else
\chr@verbose{Lists are not equal at index \the\chr@tempcount\space (\@chr@left\space vs. \@chr@right).}%
\global\chr@result@false
\chr@tempif@false
\fi
% automatic break insertion
\chr@step\chr@tempcount
\ifnum\chr@tempcount<\csname#1length\endcsname \else \chr@tempif@false \fi
\ifchr@tempif@
\repeat
\chr@verbose{Lists are \ifchr@result@\else not\space\fi equal.}%
\else
\chr@verbose{Different lengths (\the\chr@tempcount\space vs. \the\chr@tempcountb).}%
\global\chr@result@false
\fi
\aftergroup\ifchr@result@
\endgroup}
% #1 name of list, #2 element to append
\def\chr@list@append#1#2{\begingroup
\chr@tempcountc=\csname#1length\endcsname\relax
\expandafter\gdef\csname#1@\the\chr@tempcountc\endcsname{#2}%
\chr@step\chr@tempcountc
\expandafter\xdef\csname#1length\endcsname{\the\chr@tempcountc}%
\endgroup}
% too much copy pasta
\def\chr@list@eappend#1#2{\begingroup
\chr@tempcountc=\csname#1length\endcsname\relax
\expandafter\xdef\csname#1@\the\chr@tempcountc\endcsname{#2}%
\chr@step\chr@tempcountc
\expandafter\xdef\csname#1length\endcsname{\the\chr@tempcountc}%
\endgroup}
% #1 name of list, #2 index to delete
\def\chr@list@delete#1#2{%
% TODO: check for if last element => pop
% otherwise replace with \main{next-idx}
}