syst-aux.lua /size: 24 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
syst-aux
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to syst-aux.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
-- slower than lpeg:
10
--
11
-- utfmatch(str,"(.?)(.*)$")
12
-- utf.sub(str,1,1)
13 14
local
tonumber
,
next
,
type
=
tonumber
,
next
,
type
15
local
utfsub
=
utf
.
sub
16
local
P
,
S
,
R
,
C
,
Cc
,
Cs
,
Carg
,
lpegmatch
=
lpeg
.
P
,
lpeg
.
S
,
lpeg
.
R
,
lpeg
.
C
,
lpeg
.
Cc
,
lpeg
.
Cs
,
lpeg
.
Carg
,
lpeg
.
match
17
local
next
=
next
18
local
find
,
formatters
=
string
.
find
,
string
.
formatters
19 20
local
context
=
context
21
local
implement
=
interfaces
.
implement
22
local
setmacro
=
interfaces
.
setmacro
23
local
setcatcode
=
tex
.
setcatcode
24
local
texget
=
tex
.
get
25
local
utf8character
=
lpeg
.
patterns
.
utf8character
26
local
settings_to_array
=
utilities
.
parsers
.
settings_to_array
27
local
settings_to_set
=
utilities
.
parsers
.
settings_to_set
28 29
local
pattern
=
C
(
utf8character
^
-1
)
*
C
(
P
(
1
)
^
0
)
30 31
implement
{
32
name
=
"
getfirstcharacter
"
,
33
arguments
=
"
string
"
,
34
actions
=
function
(
str
)
35
local
first
,
rest
=
lpegmatch
(
pattern
,
str
)
36
setmacro
(
"
firstcharacter
"
,
first
)
37
setmacro
(
"
remainingcharacters
"
,
rest
)
38
end
39
}
40 41
implement
{
42
name
=
"
thefirstcharacter
"
,
43
arguments
=
"
string
"
,
44
actions
=
function
(
str
)
45
local
first
,
rest
=
lpegmatch
(
pattern
,
str
)
46
context
(
first
)
47
end
48
}
49 50
implement
{
51
name
=
"
theremainingcharacters
"
,
52
arguments
=
"
string
"
,
53
actions
=
function
(
str
)
54
local
first
,
rest
=
lpegmatch
(
pattern
,
str
)
55
context
(
rest
)
56
end
57
}
58 59
local
pattern
=
C
(
utf8character
^
-1
)
60
local
ctx_doifelse
=
commands
.
doifelse
61 62
implement
{
63
name
=
"
doifelsefirstchar
"
,
64
arguments
=
"
2 strings
"
,
65
actions
=
function
(
str
,
chr
)
66
ctx_doifelse
(
lpegmatch
(
pattern
,
str
)
=
=
chr
)
67
end
68
}
69 70
implement
{
71
name
=
"
getsubstring
"
,
72
arguments
=
"
3 strings
"
,
73
actions
=
function
(
str
,
first
,
last
)
74
context
(
utfsub
(
str
,
tonumber
(
first
)
,
tonumber
(
last
)
)
)
75
end
76
}
77 78
-- function commands.addtocommalist(list,item)
79
-- if list == "" then
80
-- context(item)
81
-- else
82
-- context("%s,%s",list,item) -- using tex.print is some 10% faster
83
-- end
84
-- end
85
--
86
-- function commands.removefromcommalist(list,item)
87
-- if list == "" then
88
-- context(item)
89
-- else
90
-- -- okay, using a proper lpeg is probably faster
91
-- -- we could also check for #l = 1
92
-- local l = settings_to_array(list)
93
-- local t, n = { }
94
-- for i=1,#l do
95
-- if l[i] ~= item then
96
-- n = n + 1
97
-- t[n] = item
98
-- end
99
-- end
100
-- if n == 0 then
101
-- context(item)
102
-- else
103
-- context(concat(list,","))
104
-- end
105
-- end
106
-- end
107 108
local
pattern
=
(
C
(
(
1
-
P
(
"
%
"
)
)
^
1
)
*
Carg
(
1
)
)
/
function
(
n
,
d
)
109
return
formatters
[
"
%.0fsp
"
]
(
d
*
tonumber
(
n
)
/
100
)
end
*
P
(
"
%
"
)
*
P
(
-1
)
-- .0 ?
110 111
-- percentageof("10%",65536*10)
112 113
implement
{
114
name
=
"
percentageof
"
,
115
arguments
=
{
"
string
"
,
"
dimen
"
}
,
116
actions
=
function
(
str
,
dim
)
117
context
(
lpegmatch
(
pattern
,
str
,
1
,
dim
)
or
str
)
118
end
119
}
120 121
-- \gdef\setpercentdimen#1#2%
122
-- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax}
123 124
local
space
=
P
(
"
"
)
/
"
"
125
local
spaces
=
P
(
"
"
)
^
0
/
"
"
126
local
nohash
=
1
-
P
(
"
#
"
)
127
local
digit
=
R
(
"
09
"
)
128
local
double
=
P
(
"
##
"
)
/
"
#
"
129
local
single
=
P
(
"
#
"
)
130
local
sentinel
=
spaces
*
(
nohash
^
1
/
"
\\%0
"
)
131
local
sargument
=
(
single
*
digit
)
^
1
132
local
dargument
=
(
double
*
digit
)
^
1
133 134
-- first variant:
135
--
136
-- local texpreamble = nil
137
-- local usespaces = nil
138
--
139
-- local pattern = Cs( -- ^-1
140
-- ( P("spaces") / function() usespaces = true return "" end )^0
141
-- * spaces
142
-- * ( P("nospaces") / function() usespaces = false return "" end )^0
143
-- * spaces
144
-- * ( P("global") / "\\global" )^0
145
-- * spaces
146
-- * ( P("unexpanded") / "\\unexpanded" )^0
147
-- * spaces
148
-- * Cc("\\expandafter\\")
149
-- * spaces
150
-- * ( P("expanded") / "e" )^0
151
-- * spaces
152
-- * ( P((1-S(" #"))^1) / "def\\csname %0\\endcsname" )
153
-- * spaces
154
-- * (
155
-- -- (double * digit)^1 * sentinel^-1 * double^-1
156
-- -- + (single * digit)^1 * sentinel^-1 * single^-1
157
-- ( P("[") * dargument * P("]") + dargument)^1 * sentinel^-1 * double^-1
158
-- + ( P("[") * sargument * P("]") + sargument)^1 * sentinel^-1 * single^-1
159
-- + sentinel^-1 * (double+single)^-1
160
-- )
161
-- )
162
--
163
-- local ctx_dostarttexdefinition = context.dostarttexdefinition
164
--
165
-- local function texdefinition_one(str)
166
-- usespaces = nil
167
-- texpreamble = lpegmatch(pattern,str)
168
-- if usespaces == true then
169
-- setcatcode(32,10) -- space
170
-- setcatcode(13, 5) -- endofline
171
-- elseif usespaces == false then
172
-- setcatcode(32, 9) -- ignore
173
-- setcatcode(13, 9) -- ignore
174
-- else
175
-- -- this is default
176
-- -- setcatcode(32,10) -- space
177
-- -- setcatcode(13, 9) -- ignore
178
-- end
179
-- ctx_dostarttexdefinition()
180
-- end
181
--
182
-- local function texdefinition_two()
183
-- context(texpreamble)
184
-- end
185 186
-- second variant:
187
--
188
-- -- default:
189
-- --
190
-- -- setcatcode(32,10) -- space
191
-- -- setcatcode(13, 9) -- ignore
192
--
193
-- local function catcodes_s()
194
-- setcatcode(32,10) -- space
195
-- setcatcode(13, 5) -- endofline
196
-- return ""
197
-- end
198
--
199
-- local function catcodes_n()
200
-- setcatcode(32, 9) -- ignore
201
-- setcatcode(13, 9) -- ignore
202
-- return ""
203
-- end
204
--
205
-- local pattern = Cs( -- ^-1
206
-- ( P("spaces") * space / catcodes_s )^0
207
-- * spaces * ( P("nospaces") * space / catcodes_n )^0
208
-- * spaces * ( P("global") * space / "\\global" )^0
209
-- * spaces * ( P("unexpanded") * space / "\\unexpanded" )^0
210
-- * spaces * Cc("\\expandafter\\")
211
-- * spaces * ( P("expanded") / "e" )^0
212
-- * spaces * ( P((1-S(" #["))^1) / "def\\csname %0\\endcsname" )
213
-- * spaces * (
214
-- -- (double * digit)^1 * sentinel^-1 * double^-1
215
-- -- + (single * digit)^1 * sentinel^-1 * single^-1
216
-- ( P("[") * dargument * P("]") + dargument)^1 * sentinel^-1 * double^-1
217
-- + ( P("[") * sargument * P("]") + sargument)^1 * sentinel^-1 * single^-1
218
-- + sentinel^-1 * (double+single)^-1
219
-- )
220
-- )
221
--
222
-- local texpreamble = nil
223
--
224
-- local ctx_dostarttexdefinition = context.dostarttexdefinition
225
--
226
-- local function texdefinition_one(str)
227
-- texpreamble = lpegmatch(pattern,str)
228
-- ctx_dostarttexdefinition()
229
-- end
230
--
231
-- local function texdefinition_two()
232
-- context(texpreamble)
233
-- end
234 235
-- third variant:
236 237
local
global
=
nil
238
local
unexpanded
=
nil
239
local
expanded
=
nil
240
local
optional
=
nil
241
local
csname
=
nil
242
local
rest
=
nil
243 244
local
function
catcodes_s
(
)
245
setcatcode
(
32
,
10
)
-- space
246
setcatcode
(
13
,
5
)
-- endofline
247
end
248 249
local
function
catcodes_n
(
)
250
setcatcode
(
32
,
9
)
-- ignore
251
setcatcode
(
13
,
9
)
-- ignore
252
end
253 254
local
space
=
P
(
"
"
)
255
local
spaces
=
space
^
0
256 257
local
option
=
(
258
P
(
"
single
"
)
259
+
P
(
"
double
"
)
260
+
P
(
"
triple
"
)
261
+
P
(
"
quadruple
"
)
262
+
P
(
"
quintuple
"
)
263
+
P
(
"
sixtuple
"
)
264
)
*
(
P
(
"
empty
"
)
+
P
(
"
argument
"
)
)
265 266
local
pattern
=
(
267
(
P
(
"
spaces
"
)
*
space
/
catcodes_s
)
^
0
268
*
spaces
*
(
P
(
"
nospaces
"
)
*
space
/
catcodes_n
)
^
0
269
*
spaces
*
(
P
(
"
global
"
)
*
space
*
Cc
(
true
)
+
Cc
(
false
)
)
270
*
spaces
*
(
P
(
"
unexpanded
"
)
*
space
*
Cc
(
true
)
+
Cc
(
false
)
)
271
*
spaces
*
(
P
(
"
expanded
"
)
*
space
*
Cc
(
true
)
+
Cc
(
false
)
)
272
*
spaces
*
(
C
(
option
)
*
space
+
Cc
(
false
)
)
273
*
spaces
*
(
C
(
(
1
-
S
(
"
#[
"
)
)
^
1
)
)
274
*
spaces
*
Cs
(
275
(
P
(
"
[
"
)
*
dargument
*
P
(
"
]
"
)
+
dargument
)
^
1
*
sentinel
^
-1
*
double
^
-1
276
+
(
P
(
"
[
"
)
*
sargument
*
P
(
"
]
"
)
+
sargument
)
^
1
*
sentinel
^
-1
*
single
^
-1
277
+
sentinel
^
-1
*
(
double
+
single
)
^
-1
278
)
279
)
280 281
local
ctx_dostarttexdefinition
=
context
.
dostarttexdefinition
282 283
local
function
texdefinition_one
(
str
)
284
global
,
unexpanded
,
expanded
,
optional
,
csname
,
rest
=
lpegmatch
(
pattern
,
str
)
285
ctx_dostarttexdefinition
(
)
286
end
287 288
local
function
texdefinition_two
(
)
289
if
optional
then
290
context
(
291
[[
\unexpanded\expandafter
]]
.
.
292
(
global
and
[[
\xdef
]]
or
[[
\edef
]]
)
.
.
293
[[
\csname
]]
.
.
294
csname
.
.
295
[[
\endcsname{\expandafter\noexpand\expandafter\do
]]
.
.
296
optional
.
.
297
[[
\csname _do_
]]
.
.
298
csname
.
.
299
-- [[_\endcsname}\unexpanded\expandafter]] ..
300
[[
_\endcsname}\expandafter
]]
.
.
301
(
global
and
[[
\gdef
]]
or
[[
\edef
]]
)
.
.
302
[[
\csname _do_
]]
.
.
303
csname
.
.
304
[[
_\endcsname
]]
.
.
305
rest
306
)
307
else
308
context
(
309
[[
\unexpanded\expandafter
]]
.
.
310
(
global
and
(
311
expanded
and
[[
\xdef
]]
or
[[
\gdef
]]
312
)
or
(
313
expanded
and
[[
\edef
]]
or
[[
\def
]]
314
)
)
.
.
315
[[
\csname
]]
.
.
316
csname
.
.
317
[[
\endcsname
]]
.
.
318
rest
319
)
320
end
321
end
322 323
implement
{
name
=
"
texdefinition_one
"
,
actions
=
texdefinition_one
,
scope
=
"
private
"
,
arguments
=
"
string
"
}
324
implement
{
name
=
"
texdefinition_two
"
,
actions
=
texdefinition_two
,
scope
=
"
private
"
}
325 326
do
327 328
-- Quite probably we don't yet have characters loaded so we delay some
329
-- aliases.
330 331
local
_lower_
,
_upper_
,
_strip_
332 333
_lower_
=
function
(
s
)
334
if
characters
and
characters
.
lower
then
335
_lower_
=
characters
.
lower
336
return
_lower_
(
s
)
337
end
338
return
string
.
lower
(
s
)
339
end
340 341
_upper_
=
function
(
s
)
342
if
characters
and
characters
.
upper
then
343
_upper_
=
characters
.
upper
344
return
_upper_
(
s
)
345
end
346
return
string
.
upper
(
s
)
347
end
348 349
_strip_
=
function
(
s
)
350
-- or utf.strip
351
if
string
.
strip
then
352
_strip_
=
string
.
strip
353
return
_strip_
(
s
)
354
end
355
return
s
356
end
357 358
local
function
lower
(
s
)
context
(
_lower_
(
s
)
)
end
359
local
function
upper
(
s
)
context
(
_upper_
(
s
)
)
end
360
local
function
strip
(
s
)
context
(
_strip_
(
s
)
)
end
361 362
implement
{
name
=
"
upper
"
,
arguments
=
"
string
"
,
actions
=
upper
}
363
implement
{
name
=
"
lower
"
,
arguments
=
"
string
"
,
actions
=
lower
}
364
implement
{
name
=
"
strip
"
,
arguments
=
"
string
"
,
actions
=
strip
}
365 366
end
367 368
implement
{
369
name
=
"
converteddimen
"
,
370
arguments
=
{
"
dimen
"
,
"
string
"
}
,
371
actions
=
function
(
dimen
,
unit
)
372
context
(
number
.
todimen
(
dimen
,
unit
or
"
pt
"
,
"
%0.5f
"
)
)
-- no unit appended (%F)
373
end
374
}
375 376
-- where, not really the best spot for this:
377 378
implement
{
379
name
=
"
immediatemessage
"
,
380
arguments
=
{
"
'message'
"
,
"
string
"
}
,
381
actions
=
logs
.
status
382
}
383 384
implement
{
385
name
=
"
resettimer
"
,
386
actions
=
function
(
)
387
statistics
.
resettiming
(
"
whatever
"
)
388
statistics
.
starttiming
(
"
whatever
"
)
389
end
390
}
391 392
implement
{
393
name
=
"
benchmarktimer
"
,
394
actions
=
function
(
)
395
statistics
.
benchmarktimer
(
"
whatever
"
)
396
end
397
}
398 399
implement
{
400
name
=
"
elapsedtime
"
,
401
actions
=
function
(
)
402
statistics
.
stoptiming
(
"
whatever
"
)
403
context
(
statistics
.
elapsedtime
(
"
whatever
"
)
)
404
end
405
}
406 407
implement
{
408
name
=
"
elapsedsteptime
"
,
409
arguments
=
"
integer
"
,
410
actions
=
function
(
n
)
411
statistics
.
stoptiming
(
"
whatever
"
)
412
local
t
=
statistics
.
elapsed
(
"
whatever
"
)
/
(
n
>
0
and
n
or
1
)
413
if
t
>
0
then
414
context
(
"
%0.9f
"
,
t
)
415
else
416
context
(
0
)
417
end
418
end
419
}
420 421
local
accuracy
=
table
.
setmetatableindex
(
function
(
t
,
k
)
422
local
v
=
formatters
[
"
%0.
"
.
.
k
.
.
"
f
"
]
423
t
[
k
]
=
v
424
return
v
425
end
)
426 427
implement
{
428
name
=
"
rounded
"
,
429
arguments
=
"
integer
"
,
430
actions
=
function
(
n
,
m
)
context
(
accuracy
[
n
]
(
m
)
)
end
431
}
432 433
-- not faster but just less tracing:
434 435
local
ctx_protected_cs
=
context
.
protected
.
cs
-- more efficient
436 437
local
ctx_firstoftwoarguments
=
ctx_protected_cs
.
firstoftwoarguments
438
local
ctx_secondoftwoarguments
=
ctx_protected_cs
.
secondoftwoarguments
439
local
ctx_firstofoneargument
=
ctx_protected_cs
.
firstofoneargument
440
local
ctx_gobbleoneargument
=
ctx_protected_cs
.
gobbleoneargument
441 442
context
.
firstoftwoarguments
=
ctx_firstoftwoarguments
443
context
.
secondoftwoarguments
=
ctx_secondoftwoarguments
444
context
.
firstofoneargument
=
ctx_firstofoneargument
445
context
.
gobbleoneargument
=
ctx_gobbleoneargument
446 447
local
ctx_iftrue
=
context
.
iftrue
448
local
ctx_iffalse
=
context
.
iffalse
449 450
local
hash
=
utilities
.
parsers
.
hashes
.
settings_to_set
451 452
local
function
doifelsecommon
(
a
,
b
)
453
if
a
=
=
b
then
454
setmacro
(
"
commalistelement
"
,
a
)
455
if
a
=
=
"
"
then
456
ctx_secondoftwoarguments
(
)
457
else
458
ctx_firstoftwoarguments
(
)
459
end
460
return
461
end
462
local
ba
=
find
(
a
,
"
,
"
,
1
,
true
)
463
local
bb
=
find
(
b
,
"
,
"
,
1
,
true
)
464
if
ba
and
bb
then
465
local
ha
=
hash
[
a
]
466
local
hb
=
hash
[
b
]
467
-- local ha = settings_to_set(a)
468
-- local hb = settings_to_set(b)
469
for
k
in
next
,
ha
do
470
if
hb
[
k
]
then
471
setmacro
(
"
commalistelement
"
,
k
)
472
ctx_firstoftwoarguments
(
)
473
return
474
end
475
end
476
elseif
ba
then
477
if
hash
[
a
]
[
b
]
then
478
-- if settings_to_set(a)[b] then
479
setmacro
(
"
commalistelement
"
,
b
)
480
ctx_firstoftwoarguments
(
)
481
return
482
end
483
elseif
bb
then
484
if
hash
[
b
]
[
a
]
then
485
-- if settings_to_set(b)[a] then
486
setmacro
(
"
commalistelement
"
,
a
)
487
ctx_firstoftwoarguments
(
)
488
return
489
end
490
end
491
setmacro
(
"
commalistelement
"
,
"
"
)
492
ctx_secondoftwoarguments
(
)
493
end
494 495
local
function
doifcommon
(
a
,
b
)
496
if
a
=
=
b
then
497
setmacro
(
"
commalistelement
"
,
a
)
498
if
a
=
=
"
"
then
499
ctx_gobbleoneargument
(
)
500
else
501
ctx_firstofoneargument
(
)
502
end
503
return
504
end
505
local
ba
=
find
(
a
,
"
,
"
,
1
,
true
)
506
local
bb
=
find
(
b
,
"
,
"
,
1
,
true
)
507
if
ba
and
bb
then
508
local
ha
=
hash
[
a
]
509
local
hb
=
hash
[
b
]
510
-- local ha = settings_to_set(a)
511
-- local hb = settings_to_set(b)
512
for
k
in
next
,
ha
do
513
if
hb
[
k
]
then
514
setmacro
(
"
commalistelement
"
,
k
)
515
ctx_firstofoneargument
(
)
516
return
517
end
518
end
519
elseif
ba
then
520
if
hash
[
a
]
[
b
]
then
521
-- if settings_to_set(a)[b] then
522
setmacro
(
"
commalistelement
"
,
b
)
523
ctx_firstofoneargument
(
)
524
return
525
end
526
elseif
bb
then
527
if
hash
[
b
]
[
a
]
then
528
-- if settings_to_set(b)[a] then
529
setmacro
(
"
commalistelement
"
,
a
)
530
ctx_firstofoneargument
(
)
531
return
532
end
533
end
534
setmacro
(
"
commalistelement
"
,
"
"
)
535
ctx_gobbleoneargument
(
)
536
end
537 538
local
function
doifnotcommon
(
a
,
b
)
539
if
a
=
=
b
then
540
setmacro
(
"
commalistelement
"
,
a
)
541
if
a
=
=
"
"
then
542
ctx_firstofoneargument
(
)
543
else
544
ctx_gobbleoneargument
(
)
545
end
546
return
547
end
548
local
ba
=
find
(
a
,
"
,
"
,
1
,
true
)
549
local
bb
=
find
(
b
,
"
,
"
,
1
,
true
)
550
if
ba
and
bb
then
551
local
ha
=
hash
[
a
]
552
local
hb
=
hash
[
b
]
553
-- local ha = settings_to_set(a)
554
-- local hb = settings_to_set(b)
555
for
k
in
next
,
ha
do
556
if
hb
[
k
]
then
557
setmacro
(
"
commalistelement
"
,
k
)
558
ctx_gobbleoneargument
(
)
559
return
560
end
561
end
562
elseif
ba
then
563
if
hash
[
a
]
[
b
]
then
564
-- if settings_to_set(a)[b] then
565
setmacro
(
"
commalistelement
"
,
b
)
566
ctx_gobbleoneargument
(
)
567
return
568
end
569
elseif
bb
then
570
if
hash
[
b
]
[
a
]
then
571
-- if settings_to_set(b)[a] then
572
setmacro
(
"
commalistelement
"
,
a
)
573
ctx_gobbleoneargument
(
)
574
return
575
end
576
end
577
setmacro
(
"
commalistelement
"
,
"
"
)
578
ctx_firstofoneargument
(
)
579
end
580 581
-- local function hascommonargumentcondition(a,b)
582
-- if a == b then
583
-- setmacro("commalistelement",a)
584
-- if a == "" then
585
-- ctx_iffalse()
586
-- else
587
-- ctx_iftrue()
588
-- end
589
-- return
590
-- end
591
-- local ba = find(a,",",1,true)
592
-- local bb = find(b,",",1,true)
593
-- if ba and bb then
594
-- local ha = hash[a]
595
-- local hb = hash[b]
596
-- for k in next, ha do
597
-- if hb[k] then
598
-- setmacro("commalistelement",k)
599
-- ctx_iftrue()
600
-- return
601
-- end
602
-- end
603
-- elseif ba then
604
-- if hash[a][b] then
605
-- setmacro("commalistelement",b)
606
-- ctx_iftrue()
607
-- return
608
-- end
609
-- elseif bb then
610
-- if hash[b][a] then
611
-- setmacro("commalistelement",a)
612
-- ctx_iftrue()
613
-- return
614
-- end
615
-- end
616
-- setmacro("commalistelement","")
617
-- ctx_iffalse()
618
-- end
619 620
local
function
doifelseinset
(
a
,
b
)
621
if
a
=
=
b
then
622
setmacro
(
"
commalistelement
"
,
a
)
623
if
a
=
=
"
"
then
624
ctx_secondoftwoarguments
(
)
625
else
626
ctx_firstoftwoarguments
(
)
627
end
628
return
629
end
630
local
bb
=
find
(
b
,
"
,
"
,
1
,
true
)
631
if
bb
then
632
if
hash
[
b
]
[
a
]
then
633
-- if settings_to_set(b)[a] then
634
setmacro
(
"
commalistelement
"
,
a
)
635
ctx_firstoftwoarguments
(
)
636
return
637
end
638
end
639
setmacro
(
"
commalistelement
"
,
"
"
)
640
ctx_secondoftwoarguments
(
)
641
end
642 643
local
function
doifinset
(
a
,
b
)
644
if
a
=
=
b
then
645
setmacro
(
"
commalistelement
"
,
a
)
646
if
a
=
=
"
"
then
647
ctx_gobbleoneargument
(
)
648
else
649
ctx_firstofoneargument
(
)
650
end
651
return
652
end
653
local
bb
=
find
(
b
,
"
,
"
,
1
,
true
)
654
if
bb
then
655
if
hash
[
b
]
[
a
]
then
656
-- if settings_to_set(b)[a] then
657
setmacro
(
"
commalistelement
"
,
a
)
658
ctx_firstofoneargument
(
)
659
return
660
end
661
end
662
setmacro
(
"
commalistelement
"
,
"
"
)
663
ctx_gobbleoneargument
(
)
664
end
665 666
local
function
doifnotinset
(
a
,
b
)
667
if
a
=
=
b
then
668
setmacro
(
"
commalistelement
"
,
a
)
669
if
a
=
=
"
"
then
670
ctx_firstofoneargument
(
)
671
else
672
ctx_gobbleoneargument
(
)
673
end
674
return
675
end
676
local
bb
=
find
(
b
,
"
,
"
,
1
,
true
)
677
if
bb
then
678
if
hash
[
b
]
[
a
]
then
679
-- if settings_to_set(b)[a] then
680
setmacro
(
"
commalistelement
"
,
a
)
681
ctx_gobbleoneargument
(
)
682
return
683
end
684
end
685
setmacro
(
"
commalistelement
"
,
"
"
)
686
ctx_firstofoneargument
(
)
687
end
688 689
implement
{
690
name
=
"
doifelsecommon
"
,
691
actions
=
doifelsecommon
,
692
arguments
=
"
2 strings
"
,
693
}
694 695
implement
{
696
name
=
"
doifcommon
"
,
697
actions
=
doifcommon
,
698
arguments
=
"
2 strings
"
,
699
}
700 701
implement
{
702
name
=
"
doifnotcommon
"
,
703
actions
=
doifnotcommon
,
704
arguments
=
"
2 strings
"
,
705
}
706 707
-- implement {
708
-- name = "hascommonargumentcondition",
709
-- actions = hascommonargumentcondition,
710
-- arguments = "2 strings",
711
-- arguments = { "argument", "argument" },
712
-- }
713 714
implement
{
715
name
=
"
doifelseinset
"
,
716
actions
=
doifelseinset
,
717
arguments
=
"
2 strings
"
,
718
-- arguments = { "argument", "argument" },
719
}
720 721
implement
{
722
name
=
"
doifinset
"
,
723
actions
=
doifinset
,
724
arguments
=
"
2 strings
"
,
725
}
726 727
implement
{
728
name
=
"
doifnotinset
"
,
729
actions
=
doifnotinset
,
730
arguments
=
"
2 strings
"
,
731
}
732 733
-- done elsewhere:
734
--
735
-- local function firstinset(a)
736
-- local aa = hash[a]
737
-- context(aa and aa[1] or a)
738
-- end
739
--
740
-- implement {
741
-- name = "firstinset",
742
-- actions = firstinset,
743
-- arguments = "string",
744
-- private = false,
745
-- }
746 747
-- implement {
748
-- name = "stringcompare",
749
-- arguments = "2 strings",
750
-- actions = function(a,b)
751
-- context((a == b and 0) or (a > b and 1) or -1)
752
-- end
753
-- }
754
--
755
-- implement {
756
-- name = "doifelsestringafter",
757
-- arguments = "2 strings",
758
-- actions = function(a,b)
759
-- ctx_doifelse((a == b and 0) or (a > b and 1) or -1)
760
-- end
761
-- }
762
--
763
-- implement {
764
-- name = "doifelsestringbefore",
765
-- arguments = "2 strings",
766
-- actions = function(a,b)
767
-- ctx_doifelse((a == b and 0) or (a < b and -1) or 1)
768
-- end
769
-- }
770 771
-- implement { -- not faster than addtocommalist
772
-- name = "additemtolist", -- unique
773
-- arguments = "2 strings",
774
-- actions = function(l,s)
775
-- if l == "" or s == l then
776
-- -- s = s
777
-- elseif find("," .. l .. ",","," .. s .. ",") then
778
-- s = l
779
-- else
780
-- s = l .. "," .. s
781
-- end
782
-- context(s)
783
-- end
784
-- }
785 786
local
bp
=
number
.
dimenfactors
.
bp
787 788
implement
{
789
name
=
"
tobigpoints
"
,
790
actions
=
function
(
d
)
context
(
"
%.5F
"
,
bp
*
d
)
end
,
791
arguments
=
"
dimension
"
,
792
}
793 794
implement
{
795
name
=
"
towholebigpoints
"
,
796
actions
=
function
(
d
)
context
(
"
%r
"
,
bp
*
d
)
end
,
797
arguments
=
"
dimension
"
,
798
}
799 800
-- for now here:
801 802
local
function
getshape
(
s
)
803
local
t
=
texget
(
s
)
804
local
n
=
t
and
#
t
or
0
805
context
(
n
)
806
if
n
>
0
then
807
for
i
=
1
,
n
do
808
local
ti
=
t
[
i
]
809
if
type
(
ti
)
=
=
"
table
"
then
810
context
(
"
%isp %isp
"
,
ti
[
1
]
,
ti
[
2
]
)
811
else
812
context
(
"
%i
"
,
ti
)
813
end
814
end
815
end
816
end
817 818
implement
{
819
name
=
"
getparshape
"
,
820
public
=
true
,
821
actions
=
function
(
)
getshape
(
"
parshape
"
)
end
,
822
}
823
implement
{
824
name
=
"
getclubpenalties
"
,
825
public
=
true
,
826
actions
=
function
(
)
getshape
(
"
clubpenalties
"
)
end
,
827
}
828
implement
{
829
name
=
"
getinterlinepenalties
"
,
830
public
=
true
,
831
actions
=
function
(
)
getshape
(
"
interlinepenalties
"
)
end
,
832
}
833
implement
{
834
name
=
"
getdisplaywidowpenalties
"
,
835
public
=
true
,
836
actions
=
function
(
)
getshape
(
"
displaywidowpenalties
"
)
end
,
837
}
838
implement
{
839
name
=
"
getwidowpenalties
"
,
840
public
=
true
,
841
actions
=
function
(
)
getshape
(
"
widowpenalties
"
)
end
,
842
}
843 844
if
CONTEXTLMTXMODE
>
0
then
845 846
-- This is kind of tricky and might not work for all csnames but as long as we use
847
-- it in a controlled way, we're okay. The engine implementation might be changed
848
-- a bit (no need to go through strings, but fetching a cs index and passing that
849
-- back also takes time).
850 851
-- Another approach is to have the predefined stack operate use private stacks and
852
-- then the pop doesn't need the cs. But ... we then also need to store stuff in
853
-- the format so that complicates maters more than I'm willing to do.
854 855
local
insert
,
remove
=
table
.
insert
,
table
.
remove
856 857
local
push_macro
=
token
.
push_macro
858
local
pop_macro
=
token
.
pop_macro
859
local
scan_csname
=
token
.
scan_csname
860 861
local
stack
=
table
.
setmetatableindex
(
"
table
"
)
862 863
local
report
=
logs
.
reporter
(
"
system
"
,
"
macrostack
"
)
864 865
local
function
pushmacro
(
name
,
global
)
866
local
s
=
push_macro
(
name
,
global
)
867
if
s
then
868
insert
(
stack
[
name
]
,
s
)
869
else
870
report
(
"
no macro %a
"
,
name
)
871
insert
(
stack
[
name
]
,
false
)
872
end
873
end
874 875
local
function
popmacro
(
name
)
876
local
s
=
remove
(
stack
[
name
]
)
877
if
s
then
878
pop_macro
(
s
)
879
else
880
-- error
881
end
882
end
883 884
tokens
.
pushmacro
=
pushmacro
885
tokens
.
popmacro
=
popmacro
886 887
interfaces
.
implement
{
888
name
=
"
localpushmacro
"
,
889
public
=
true
,
890
protected
=
true
,
891
actions
=
function
(
)
892
pushmacro
(
scan_csname
(
)
)
893
end
894
}
895 896
interfaces
.
implement
{
897
name
=
"
globalpushmacro
"
,
898
public
=
true
,
899
protected
=
true
,
900
actions
=
function
(
)
901
pushmacro
(
scan_csname
(
)
,
true
)
902
end
903
}
904 905
interfaces
.
implement
{
906
name
=
"
localpopmacro
"
,
907
public
=
true
,
908
protected
=
true
,
909
actions
=
function
(
)
910
popmacro
(
scan_csname
(
)
)
911
end
912
}
913 914
interfaces
.
implement
{
915
name
=
"
globalpopmacro
"
,
916
public
=
true
,
917
protected
=
true
,
918
actions
=
function
(
)
919
popmacro
(
scan_csname
(
)
)
920
end
921
}
922 923
interfaces
.
implement
{
924
name
=
"
showmacrostack
"
,
925
public
=
true
,
926
protected
=
true
,
927
actions
=
function
(
)
928
local
n
=
scan_csname
(
)
929
local
s
=
stack
[
n
]
930
local
m
=
#
s
931
report
(
"
%s : %i stack slots used
"
,
n
,
m
)
932
for
i
=
1
,
m
do
933
report
(
"
% 3i %S
"
,
i
,
s
[
i
]
)
934
end
935
end
936
}
937 938
end
939