trac-set.lua /size: 14 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
trac-set
'
]
=
{
-- might become util-set.lua
2
version
=
1
.
001
,
3
comment
=
"
companion to luat-lib.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
-- maybe this should be util-set.lua
10 11
local
type
,
next
,
tostring
,
tonumber
=
type
,
next
,
tostring
,
tonumber
12
local
print
=
print
13
local
concat
,
sortedhash
=
table
.
concat
,
table
.
sortedhash
14
local
formatters
,
find
,
lower
,
gsub
,
topattern
=
string
.
formatters
,
string
.
find
,
string
.
lower
,
string
.
gsub
,
string
.
topattern
15
local
is_boolean
=
string
.
is_boolean
16
local
settings_to_hash
=
utilities
.
parsers
.
settings_to_hash
17
local
allocate
=
utilities
.
storage
.
allocate
18 19
utilities
=
utilities
or
{
}
20
local
utilities
=
utilities
21 22
local
setters
=
utilities
.
setters
or
{
}
23
utilities
.
setters
=
setters
24 25
local
data
=
{
}
26 27
-- We can initialize from the cnf file. This is sort of tricky as
28
-- later defined setters also need to be initialized then. If set
29
-- this way, we need to ensure that they are not reset later on.
30
--
31
-- The sorting is needed to get a predictable setters in case of *.
32 33
local
trace_initialize
=
false
-- only for testing during development
34
local
frozen
=
true
-- this needs checking
35 36
local
function
initialize_setter
(
filename
,
name
,
values
)
-- filename only for diagnostics
37
local
setter
=
data
[
name
]
38
if
setter
then
39
-- trace_initialize = true
40
local
data
=
setter
.
data
41
if
data
then
42
for
key
,
newvalue
in
sortedhash
(
values
)
do
43
local
newvalue
=
is_boolean
(
newvalue
,
newvalue
,
true
)
-- strict
44
local
functions
=
data
[
key
]
45
if
functions
then
46
local
oldvalue
=
functions
.
value
47
if
functions
.
frozen
then
48
if
trace_initialize
then
49
setter
.
report
(
"
%s: %a is %s to %a
"
,
filename
,
key
,
"
frozen
"
,
oldvalue
)
50
end
51
elseif
#
functions
>
0
and
not
oldvalue
then
52
-- elseif #functions > 0 and oldvalue == nil then
53
if
trace_initialize
then
54
setter
.
report
(
"
%s: %a is %s to %a
"
,
filename
,
key
,
"
set
"
,
newvalue
)
55
end
56
for
i
=
1
,
#
functions
do
57
functions
[
i
]
(
newvalue
)
58
end
59
functions
.
value
=
newvalue
60
functions
.
frozen
=
functions
.
frozen
or
frozen
61
else
62
if
trace_initialize
then
63
setter
.
report
(
"
%s: %a is %s as %a
"
,
filename
,
key
,
"
kept
"
,
oldvalue
)
64
end
65
end
66
else
67
-- we do a simple preregistration i.e. not in the
68
-- list as it might be an obsolete entry
69
functions
=
{
default
=
newvalue
,
frozen
=
frozen
}
70
data
[
key
]
=
functions
71
if
trace_initialize
then
72
setter
.
report
(
"
%s: %a is %s to %a
"
,
filename
,
key
,
"
defaulted
"
,
newvalue
)
73
end
74
end
75
end
76
return
true
77
end
78
end
79
end
80 81
-- user interface code
82 83
local
function
set
(
t
,
what
,
newvalue
)
84
local
data
=
t
.
data
-- somehow this can be nil
85
if
data
and
not
data
.
frozen
then
86
local
done
=
t
.
done
87
if
type
(
what
)
=
=
"
string
"
then
88
what
=
settings_to_hash
(
what
)
-- inefficient but ok
89
end
90
if
type
(
what
)
~
=
"
table
"
then
91
return
92
end
93
if
not
done
then
-- catch ... why not set?
94
done
=
{
}
95
t
.
done
=
done
96
end
97
for
w
,
value
in
sortedhash
(
what
)
do
98
if
value
=
=
"
"
then
99
value
=
newvalue
100
elseif
not
value
then
101
value
=
false
-- catch nil
102
else
103
value
=
is_boolean
(
value
,
value
,
true
)
-- strict
104
end
105
w
=
topattern
(
w
,
true
,
true
)
106
for
name
,
functions
in
sortedhash
(
data
)
do
107
if
done
[
name
]
then
108
-- prevent recursion due to wildcards
109
elseif
find
(
name
,
w
)
then
110
done
[
name
]
=
true
111
for
i
=
1
,
#
functions
do
112
functions
[
i
]
(
value
)
113
end
114
functions
.
value
=
value
115
end
116
end
117
end
118
end
119
end
120 121
local
function
reset
(
t
)
122
local
data
=
t
.
data
123
if
data
and
not
data
.
frozen
then
124
for
name
,
functions
in
sortedthash
(
data
)
do
125
for
i
=
1
,
#
functions
do
126
functions
[
i
]
(
false
)
127
end
128
functions
.
value
=
false
129
end
130
end
131
end
132 133
local
function
enable
(
t
,
what
)
134
set
(
t
,
what
,
true
)
135
end
136 137
local
function
disable
(
t
,
what
)
138
local
data
=
t
.
data
139
if
not
what
or
what
=
=
"
"
then
140
t
.
done
=
{
}
141
reset
(
t
)
142
else
143
set
(
t
,
what
,
false
)
144
end
145
end
146 147
local
function
register_setter
(
t
,
what
,
...
)
148
local
data
=
t
.
data
149
what
=
lower
(
what
)
150
local
functions
=
data
[
what
]
151
if
not
functions
then
152
functions
=
{
}
153
data
[
what
]
=
functions
154
if
trace_initialize
then
155
t
.
report
(
"
defining %a
"
,
what
)
156
end
157
end
158
local
default
=
functions
.
default
-- can be set from cnf file
159
for
i
=
1
,
select
(
"
#
"
,
...
)
do
160
local
fnc
=
select
(
i
,
...
)
161
local
typ
=
type
(
fnc
)
162
if
typ
=
=
"
string
"
then
163
if
trace_initialize
then
164
t
.
report
(
"
coupling %a to %a
"
,
what
,
fnc
)
165
end
166
local
s
=
fnc
-- else wrong reference
167
fnc
=
function
(
value
)
set
(
t
,
s
,
value
)
end
168
elseif
typ
=
=
"
table
"
then
169
functions
.
values
=
fnc
170
fnc
=
nil
171
elseif
typ
~
=
"
function
"
then
172
fnc
=
nil
173
end
174
if
fnc
then
175
functions
[
#
functions
+
1
]
=
fnc
176
-- default: set at command line or in cnf file
177
-- value : set in tex run (needed when loading runtime)
178
local
value
=
functions
.
value
or
default
179
if
value
~
=
nil
then
180
fnc
(
value
)
181
functions
.
value
=
value
182
end
183
end
184
end
185
return
false
-- so we can use it in an assignment
186
end
187 188
local
function
enable_setter
(
t
,
what
)
189
local
e
=
t
.
enable
190
t
.
enable
,
t
.
done
=
enable
,
{
}
191
set
(
t
,
what
,
true
)
192
enable
(
t
,
what
)
193
t
.
enable
,
t
.
done
=
e
,
{
}
194
end
195 196
local
function
disable_setter
(
t
,
what
)
197
local
e
=
t
.
disable
198
t
.
disable
,
t
.
done
=
disable
,
{
}
199
disable
(
t
,
what
)
200
t
.
disable
,
t
.
done
=
e
,
{
}
201
end
202 203
local
function
reset_setter
(
t
)
204
t
.
done
=
{
}
205
reset
(
t
)
206
end
207 208
local
function
list_setter
(
t
)
-- pattern
209
local
list
=
table
.
sortedkeys
(
t
.
data
)
210
local
user
,
system
=
{
}
,
{
}
211
for
l
=
1
,
#
list
do
212
local
what
=
list
[
l
]
213
if
find
(
what
,
"
^%*
"
)
then
214
system
[
#
system
+
1
]
=
what
215
else
216
user
[
#
user
+
1
]
=
what
217
end
218
end
219
return
user
,
system
220
end
221 222
local
function
show_setter
(
t
,
pattern
)
223
local
list
=
list_setter
(
t
)
224
t
.
report
(
)
225
for
k
=
1
,
#
list
do
226
local
name
=
list
[
k
]
227
if
not
pattern
or
find
(
name
,
pattern
)
then
228
local
functions
=
t
.
data
[
name
]
229
if
functions
then
230
local
value
=
functions
.
value
231
local
default
=
functions
.
default
232
local
values
=
functions
.
values
233
local
modules
=
#
functions
234
if
default
=
=
nil
then
235
default
=
"
unset
"
236
elseif
type
(
default
)
=
=
"
table
"
then
237
default
=
concat
(
default
,
"
|
"
)
238
else
239
default
=
tostring
(
default
)
240
end
241
if
value
=
=
nil
then
242
value
=
"
unset
"
243
elseif
type
(
value
)
=
=
"
table
"
then
244
value
=
concat
(
value
,
"
|
"
)
245
else
246
value
=
tostring
(
value
)
247
end
248
t
.
report
(
name
)
249
t
.
report
(
"
modules : %i
"
,
modules
)
250
t
.
report
(
"
default : %s
"
,
default
)
251
t
.
report
(
"
value : %s
"
,
value
)
252
if
values
then
253
local
v
=
{
}
for
i
=
1
,
#
values
do
v
[
i
]
=
tostring
(
values
[
i
]
)
end
254
t
.
report
(
"
values : % t
"
,
v
)
255
end
256
t
.
report
(
)
257
end
258
end
259
end
260
end
261 262
-- we could have used a bit of oo and the trackers:enable syntax but
263
-- there is already a lot of code around using the singular tracker
264 265
-- we could make this into a module but we also want the rest avaliable
266 267
function
setters
.
report
(
setter
,
fmt
,
...
)
268
if
fmt
then
269
print
(
formatters
[
"
%-15s : %s
"
]
(
setter
.
name
,
formatters
[
fmt
]
(
...
)
)
)
270
else
271
print
(
"
"
)
272
end
273
end
274 275
local
function
setter_default
(
setter
,
name
)
276
local
d
=
setter
.
data
[
name
]
277
return
d
and
d
.
default
278
end
279 280
local
function
setter_value
(
setter
,
name
)
281
local
d
=
setter
.
data
[
name
]
282
return
d
and
(
d
.
value
or
d
.
default
)
283
end
284 285
local
function
setter_values
(
setter
,
name
)
286
local
d
=
setter
.
data
[
name
]
287
return
d
and
d
.
values
288
end
289 290
local
function
new_setter
(
name
)
-- we could use foo:bar syntax (but not used that often)
291
local
setter
-- we need to access it in setter itself
292
setter
=
{
293
data
=
allocate
(
)
,
-- indexed, but also default and value fields
294
name
=
name
,
295
report
=
function
(
...
)
setters
.
report
(
setter
,
...
)
end
,
-- setters.report gets implemented later
296
enable
=
function
(
...
)
enable_setter
(
setter
,
...
)
end
,
297
disable
=
function
(
...
)
disable_setter
(
setter
,
...
)
end
,
298
reset
=
function
(
...
)
reset_setter
(
setter
,
...
)
end
,
-- can be dangerous
299
register
=
function
(
...
)
register_setter
(
setter
,
...
)
end
,
300
list
=
function
(
...
)
return
list_setter
(
setter
,
...
)
end
,
301
show
=
function
(
...
)
show_setter
(
setter
,
...
)
end
,
302
default
=
function
(
...
)
return
setter_default
(
setter
,
...
)
end
,
303
value
=
function
(
...
)
return
setter_value
(
setter
,
...
)
end
,
304
values
=
function
(
...
)
return
setter_values
(
setter
,
...
)
end
,
305
}
306
data
[
name
]
=
setter
307
return
setter
308
end
309 310
setters
.
enable
=
enable_setter
311
setters
.
disable
=
disable_setter
312
-------.report = report_setter -- todo: adapt after call (defaults to print)
313
setters
.
register
=
register_setter
314
setters
.
list
=
list_setter
315
setters
.
show
=
show_setter
316
setters
.
reset
=
reset_setter
317
setters
.
new
=
new_setter
318
setters
.
initialize
=
initialize_setter
319 320
trackers
=
new_setter
(
"
trackers
"
)
321
directives
=
new_setter
(
"
directives
"
)
322
experiments
=
new_setter
(
"
experiments
"
)
323 324
local
t_enable
,
t_disable
=
trackers
.
enable
,
trackers
.
disable
325
local
d_enable
,
d_disable
=
directives
.
enable
,
directives
.
disable
326
local
e_enable
,
e_disable
=
experiments
.
enable
,
experiments
.
disable
327 328
-- nice trick: we overload two of the directives related functions with variants that
329
-- do tracing (itself using a tracker) .. proof of concept
330 331
local
trace_directives
=
false
local
trace_directives
=
false
trackers
.
register
(
"
system.directives
"
,
function
(
v
)
trace_directives
=
v
end
)
332
local
trace_experiments
=
false
local
trace_experiments
=
false
trackers
.
register
(
"
system.experiments
"
,
function
(
v
)
trace_experiments
=
v
end
)
333 334
function
directives
.
enable
(
...
)
335
if
trace_directives
then
336
directives
.
report
(
"
enabling: % t
"
,
{
...
}
)
337
end
338
d_enable
(
...
)
339
end
340 341
function
directives
.
disable
(
...
)
342
if
trace_directives
then
343
directives
.
report
(
"
disabling: % t
"
,
{
...
}
)
344
end
345
d_disable
(
...
)
346
end
347 348
function
experiments
.
enable
(
...
)
349
if
trace_experiments
then
350
experiments
.
report
(
"
enabling: % t
"
,
{
...
}
)
351
end
352
e_enable
(
...
)
353
end
354 355
function
experiments
.
disable
(
...
)
356
if
trace_experiments
then
357
experiments
.
report
(
"
disabling: % t
"
,
{
...
}
)
358
end
359
e_disable
(
...
)
360
end
361 362
-- a useful example
363 364
directives
.
register
(
"
system.nostatistics
"
,
function
(
v
)
365
if
statistics
then
366
statistics
.
enable
=
not
v
367
else
368
-- forget about it
369
end
370
end
)
371 372
directives
.
register
(
"
system.nolibraries
"
,
function
(
v
)
373
if
libraries
then
374
libraries
=
nil
-- we discard this tracing for security
375
else
376
-- no libraries defined
377
end
378
end
)
379 380
-- experiment
381 382
if
environment
then
383 384
-- The engineflags are known earlier than environment.arguments but maybe we
385
-- need to handle them both as the later are parsed differently. The c: prefix
386
-- is used by mtx-context to isolate the flags from those that concern luatex.
387 388
local
engineflags
=
environment
.
engineflags
389 390
if
engineflags
then
391
local
list
=
engineflags
[
"
c:trackers
"
]
or
engineflags
[
"
trackers
"
]
392
if
type
(
list
)
=
=
"
string
"
then
393
initialize_setter
(
"
commandline flags
"
,
"
trackers
"
,
settings_to_hash
(
list
)
)
394
-- t_enable(list)
395
end
396
local
list
=
engineflags
[
"
c:directives
"
]
or
engineflags
[
"
directives
"
]
397
if
type
(
list
)
=
=
"
string
"
then
398
initialize_setter
(
"
commandline flags
"
,
"
directives
"
,
settings_to_hash
(
list
)
)
399
-- d_enable(list)
400
end
401
end
402 403
end
404 405
-- here
406 407
if
texconfig
then
408 409
-- this happens too late in ini mode but that is no problem
410 411
local
function
set
(
k
,
v
)
412
local
v
=
tonumber
(
v
)
413
if
v
then
414
texconfig
[
k
]
=
v
415
end
416
end
417 418
directives
.
register
(
"
luatex.expanddepth
"
,
function
(
v
)
set
(
"
expand_depth
"
,
v
)
end
)
419
directives
.
register
(
"
luatex.hashextra
"
,
function
(
v
)
set
(
"
hash_extra
"
,
v
)
end
)
420
directives
.
register
(
"
luatex.nestsize
"
,
function
(
v
)
set
(
"
nest_size
"
,
v
)
end
)
421
directives
.
register
(
"
luatex.maxinopen
"
,
function
(
v
)
set
(
"
max_in_open
"
,
v
)
end
)
422
directives
.
register
(
"
luatex.maxprintline
"
,
function
(
v
)
set
(
"
max_print_line
"
,
v
)
end
)
423
directives
.
register
(
"
luatex.maxstrings
"
,
function
(
v
)
set
(
"
max_strings
"
,
v
)
end
)
424
directives
.
register
(
"
luatex.paramsize
"
,
function
(
v
)
set
(
"
param_size
"
,
v
)
end
)
425
directives
.
register
(
"
luatex.savesize
"
,
function
(
v
)
set
(
"
save_size
"
,
v
)
end
)
426
directives
.
register
(
"
luatex.stacksize
"
,
function
(
v
)
set
(
"
stack_size
"
,
v
)
end
)
427 428
end
429 430
-- for now here:
431 432
local
data
=
table
.
setmetatableindex
(
"
table
"
)
433 434
updaters
=
{
435
register
=
function
(
what
,
f
)
436
local
d
=
data
[
what
]
437
d
[
#
d
+
1
]
=
f
438
end
,
439
apply
=
function
(
what
,
...
)
440
local
d
=
data
[
what
]
441
for
i
=
1
,
#
d
do
442
d
[
i
]
(
...
)
443
end
444
end
,
445
}
446