strc-mar.lua /size: 25 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
strc-mar
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to strc-mar.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
-- todo: cleanup stack (structures.marks.reset(v_all) also does the job)
10
-- todo: only commands.* print to tex, native marks return values
11 12
local
insert
,
concat
=
table
.
insert
,
table
.
concat
13
local
tostring
,
next
,
rawget
,
type
=
tostring
,
next
,
rawget
,
type
14
local
lpegmatch
=
lpeg
.
match
15 16
local
context
=
context
17
local
commands
=
commands
18 19
local
implement
=
interfaces
.
implement
20 21
local
allocate
=
utilities
.
storage
.
allocate
22
local
setmetatableindex
=
table
.
setmetatableindex
23 24
local
nuts
=
nodes
.
nuts
25
local
tonut
=
nuts
.
tonut
26 27
local
getid
=
nuts
.
getid
28
local
getlist
=
nuts
.
getlist
29
local
getattr
=
nuts
.
getattr
30
local
getbox
=
nuts
.
getbox
31 32
local
nextnode
=
nuts
.
traversers
.
node
33 34
local
nodecodes
=
nodes
.
nodecodes
35
local
whatsitcodes
=
nodes
.
whatsitcodes
36 37
local
glyph_code
=
nodecodes
.
glyph
38
local
hlist_code
=
nodecodes
.
hlist
39
local
vlist_code
=
nodecodes
.
vlist
40
local
whatsit_code
=
nodecodes
.
whatsit
41 42
local
lateluawhatsit_code
=
whatsitcodes
.
latelua
43 44
local
texsetattribute
=
tex
.
setattribute
45 46
local
a_marks
=
attributes
.
private
(
"
structure
"
,
"
marks
"
)
47 48
local
trace_set
=
false
trackers
.
register
(
"
marks.set
"
,
function
(
v
)
trace_set
=
v
end
)
49
local
trace_get
=
false
trackers
.
register
(
"
marks.get
"
,
function
(
v
)
trace_get
=
v
end
)
50
local
trace_details
=
false
trackers
.
register
(
"
marks.details
"
,
function
(
v
)
trace_details
=
v
end
)
51 52
local
report_marks
=
logs
.
reporter
(
"
structure
"
,
"
marks
"
)
53 54
local
variables
=
interfaces
.
variables
55 56
local
v_first
=
variables
.
first
57
local
v_last
=
variables
.
last
58
local
v_previous
=
variables
.
previous
59
local
v_next
=
variables
.
next
60
local
v_top
=
variables
.
top
61
local
v_bottom
=
variables
.
bottom
62
local
v_current
=
variables
.
current
63
local
v_default
=
variables
.
default
64
local
v_page
=
variables
.
page
65
local
v_all
=
variables
.
all
66
local
v_keep
=
variables
.
keep
67 68
local
v_nocheck_suffix
=
"
:
"
.
.
variables
.
nocheck
69 70
local
v_first_nocheck
=
variables
.
first
.
.
v_nocheck_suffix
71
local
v_last_nocheck
=
variables
.
last
.
.
v_nocheck_suffix
72
local
v_previous_nocheck
=
variables
.
previous
.
.
v_nocheck_suffix
73
local
v_next_nocheck
=
variables
.
next
.
.
v_nocheck_suffix
74
local
v_top_nocheck
=
variables
.
top
.
.
v_nocheck_suffix
75
local
v_bottom_nocheck
=
variables
.
bottom
.
.
v_nocheck_suffix
76 77
local
structures
=
structures
78
local
marks
=
structures
.
marks
79
local
lists
=
structures
.
lists
80 81
local
settings_to_array
=
utilities
.
parsers
.
settings_to_array
82 83
local
boxes_too
=
false
-- at some point we can also tag boxes or use a zero char
84 85
directives
.
register
(
"
marks.boxestoo
"
,
function
(
v
)
boxes_too
=
v
end
)
86 87
local
data
=
marks
.
data
or
allocate
(
)
88
marks
.
data
=
data
89 90
storage
.
register
(
"
structures/marks/data
"
,
marks
.
data
,
"
structures.marks.data
"
)
91 92
local
stack
,
topofstack
=
{
}
,
0
93 94
local
ranges
=
{
95
[
v_page
]
=
{
96
first
=
0
,
97
last
=
0
,
98
}
,
99
}
100 101
local
function
resolve
(
t
,
k
)
102
if
k
then
103
if
trace_set
or
trace_get
then
104
report_marks
(
"
undefined mark, name %a
"
,
k
)
105
end
106
local
crap
=
{
autodefined
=
true
}
-- maybe set = 0 and reset = 0
107
t
[
k
]
=
crap
108
return
crap
109
else
110
-- weird: k is nil
111
end
112
end
113 114
setmetatableindex
(
data
,
resolve
)
115 116
function
marks
.
exists
(
name
)
117
return
rawget
(
data
,
name
)
~
=
nil
118
end
119 120
-- identify range
121 122
local
function
sweep
(
head
,
first
,
last
)
123
for
n
,
id
,
subtype
in
nextnode
,
head
do
124
-- we need to handle empty heads so we test for latelua
125
if
id
=
=
glyph_code
or
(
id
=
=
whatsit_code
and
subtype
=
=
lateluawhatsit_code
)
then
126
local
a
=
getattr
(
n
,
a_marks
)
127
if
not
a
then
128
-- next
129
elseif
first
=
=
0
then
130
first
,
last
=
a
,
a
131
elseif
a
>
last
then
132
last
=
a
133
end
134
elseif
id
=
=
hlist_code
or
id
=
=
vlist_code
then
135
if
boxes_too
then
136
local
a
=
getattr
(
n
,
a_marks
)
137
if
not
a
then
138
-- next
139
elseif
first
=
=
0
then
140
first
,
last
=
a
,
a
141
elseif
a
>
last
then
142
last
=
a
143
end
144
end
145
local
list
=
getlist
(
n
)
146
if
list
then
147
first
,
last
=
sweep
(
list
,
first
,
last
)
148
end
149
end
150
end
151
return
first
,
last
152
end
153 154
local
classes
=
{
}
155 156
setmetatableindex
(
classes
,
function
(
t
,
k
)
local
s
=
settings_to_array
(
k
)
t
[
k
]
=
s
return
s
end
)
157 158
local
lasts
=
{
}
159 160
function
marks
.
synchronize
(
class
,
n
,
option
)
161
local
box
=
getbox
(
n
)
162
if
box
then
163
local
first
,
last
=
sweep
(
getlist
(
box
)
,
0
,
0
)
164
if
option
=
=
v_keep
and
first
=
=
0
and
last
=
=
0
then
165
if
trace_get
or
trace_set
then
166
report_marks
(
"
action %a, class %a, box %a
"
,
"
retain at synchronize
"
,
class
,
n
)
167
end
168
-- todo: check if still valid firts/last in range
169
first
=
lasts
[
class
]
or
0
170
last
=
first
171
else
172
lasts
[
class
]
=
last
173
local
classlist
=
classes
[
class
]
174
for
i
=
1
,
#
classlist
do
175
local
class
=
classlist
[
i
]
176
local
range
=
ranges
[
class
]
177
if
range
then
178
range
.
first
=
first
179
range
.
last
=
last
180
else
181
range
=
{
182
first
=
first
,
183
last
=
last
,
184
}
185
ranges
[
class
]
=
range
186
end
187
if
trace_get
or
trace_set
then
188
report_marks
(
"
action %a, class %a, first %a, last %a
"
,
"
synchronize
"
,
class
,
range
.
first
,
range
.
last
)
189
end
190
end
191
end
192
elseif
trace_get
or
trace_set
then
193
report_marks
(
"
action %s, class %a, box %a
"
,
"
synchronize without content
"
,
class
,
n
)
194
end
195
end
196 197
-- define etc
198 199
local
function
resolve
(
t
,
k
)
200
if
k
=
=
"
fullchain
"
then
201
local
fullchain
=
{
}
202
local
chain
=
t
.
chain
203
while
chain
and
chain
~
=
"
"
do
204
insert
(
fullchain
,
1
,
chain
)
205
chain
=
data
[
chain
]
.
chain
206
end
207
t
[
k
]
=
fullchain
208
return
fullchain
209
elseif
k
=
=
"
chain
"
then
210
t
[
k
]
=
"
"
211
return
"
"
212
elseif
k
=
=
"
reset
"
or
k
=
=
"
set
"
then
213
t
[
k
]
=
0
214
return
0
215
elseif
k
=
=
"
parent
"
then
216
t
[
k
]
=
false
217
return
false
218
end
219
end
220 221
function
marks
.
define
(
name
,
settings
)
222
if
not
settings
then
223
settings
=
{
}
224
elseif
type
(
settings
)
=
=
"
string
"
then
225
settings
=
{
parent
=
settings
}
226
end
227
data
[
name
]
=
settings
228
local
parent
=
settings
.
parent
229
if
parent
=
=
nil
or
parent
=
=
"
"
or
parent
=
=
name
then
230
settings
.
parent
=
false
231
else
232
local
dp
=
data
[
parent
]
233
if
not
dp
then
234
settings
.
parent
=
false
235
elseif
dp
.
parent
then
236
settings
.
parent
=
dp
.
parent
237
end
238
end
239
setmetatableindex
(
settings
,
resolve
)
240
end
241 242
for
k
,
v
in
next
,
data
do
243
setmetatableindex
(
v
,
resolve
)
-- runtime loaded table
244
end
245 246
local
function
parentname
(
name
)
247
local
dn
=
data
[
name
]
248
return
dn
and
dn
.
parent
or
name
249
end
250 251
function
marks
.
relate
(
name
,
chain
)
252
local
dn
=
data
[
name
]
253
if
dn
and
not
dn
.
parent
then
254
if
chain
and
chain
~
=
"
"
then
255
dn
.
chain
=
chain
256
local
dc
=
data
[
chain
]
257
if
dc
then
258
local
children
=
dc
.
children
259
if
not
children
then
260
children
=
{
}
261
dc
.
children
=
children
262
end
263
children
[
#
children
+
1
]
=
name
264
end
265
elseif
trace_set
then
266
report_marks
(
"
error: invalid relation, name %a, chain %a
"
,
name
,
chain
)
267
end
268
end
269
end
270 271
local
function
resetchildren
(
new
,
name
)
272
local
dn
=
data
[
name
]
273
if
dn
and
not
dn
.
parent
then
274
local
children
=
dn
.
children
275
if
children
then
276
for
i
=
1
,
#
children
do
277
local
ci
=
children
[
i
]
278
new
[
ci
]
=
false
279
if
trace_set
then
280
report_marks
(
"
action %a, parent %a, child %a
"
,
"
reset
"
,
name
,
ci
)
281
end
282
resetchildren
(
new
,
ci
)
283
end
284
end
285
end
286
end
287 288
function
marks
.
set
(
name
,
value
)
289
local
dn
=
data
[
name
]
290
if
dn
then
291
local
child
=
name
292
local
parent
=
dn
.
parent
293
if
parent
then
294
name
=
parent
295
dn
=
data
[
name
]
296
end
297
dn
.
set
=
topofstack
298
if
not
dn
.
reset
then
299
dn
.
reset
=
0
-- in case of selfdefined
300
end
301
local
top
=
stack
[
topofstack
]
302
local
new
=
{
}
303
if
top
then
304
for
k
,
v
in
next
,
top
do
305
local
d
=
data
[
k
]
306
local
r
=
d
.
reset
or
0
307
local
s
=
d
.
set
or
0
308
if
r
<
=
topofstack
and
s
<
r
then
309
new
[
k
]
=
false
310
else
311
new
[
k
]
=
v
312
end
313
end
314
end
315
resetchildren
(
new
,
name
)
316
new
[
name
]
=
value
317
topofstack
=
topofstack
+
1
318
stack
[
topofstack
]
=
new
319
if
trace_set
then
320
if
name
=
=
child
then
321
report_marks
(
"
action %a, name %a, index %a, value %a
"
,
"
set
"
,
name
,
topofstack
,
value
)
322
else
323
report_marks
(
"
action %a, parent %a, child %a, index %a, value %a
"
,
"
set
"
,
parent
,
child
,
topofstack
,
value
)
324
end
325
end
326
texsetattribute
(
"
global
"
,
a_marks
,
topofstack
)
327
end
328
end
329 330
local
function
reset
(
name
)
331
if
v_all
then
332
if
trace_set
then
333
report_marks
(
"
action %a
"
,
"
reset all
"
)
334
end
335
stack
=
{
}
336
for
name
,
dn
in
next
,
data
do
337
local
parent
=
dn
.
parent
338
if
parent
then
339
dn
.
reset
=
0
340
dn
.
set
=
0
341
end
342
end
343
else
344
local
dn
=
data
[
name
]
345
if
dn
then
346
local
parent
=
dn
.
parent
347
if
parent
then
348
name
=
parent
349
dn
=
data
[
name
]
350
end
351
if
trace_set
then
352
report_marks
(
"
action %a, name %a, index %a
"
,
"
reset
"
,
name
,
topofstack
)
353
end
354
dn
.
reset
=
topofstack
355
local
children
=
dn
.
children
356
if
children
then
357
for
i
=
1
,
#
children
do
358
local
ci
=
children
[
i
]
359
reset
(
ci
)
360
end
361
end
362
end
363
end
364
end
365 366
marks
.
reset
=
reset
367 368
function
marks
.
get
(
n
,
name
,
value
)
369
local
dn
=
data
[
name
]
370
if
dn
then
371
name
=
dn
.
parent
or
name
372
local
top
=
stack
[
n
]
373
if
top
then
374
context
(
top
[
name
]
)
375
end
376
end
377
end
378 379
function
marks
.
show
(
first
,
last
)
380
if
first
and
last
then
381
for
k
=
first
,
last
do
382
local
v
=
stack
[
k
]
383
if
v
then
384
report_marks
(
"
% 4i: %s
"
,
k
,
table
.
sequenced
(
v
)
)
385
end
386
end
387
else
388
for
k
,
v
in
table
.
sortedpairs
(
stack
)
do
389
report_marks
(
"
% 4i: %s
"
,
k
,
table
.
sequenced
(
v
)
)
390
end
391
end
392
end
393 394
local
function
resolve
(
name
,
first
,
last
,
strict
,
quitonfalse
,
notrace
)
395
local
dn
=
data
[
name
]
396
if
dn
then
397
local
child
=
name
398
local
parent
=
dn
.
parent
399
name
=
parent
or
child
400
dn
=
data
[
name
]
401
local
step
,
method
402
if
first
>
last
then
403
step
,
method
=
-1
,
"
bottom-up
"
404
else
405
step
,
method
=
1
,
"
top-down
"
406
end
407
if
trace_get
and
not
notrace
then
408
report_marks
(
"
action %a, strategy %a, name %a, parent %a, strict %a
"
,
"
request
"
,
method
,
child
,
parent
,
strict
or
false
)
409
end
410
if
trace_details
and
not
notrace
then
411
marks
.
show
(
first
,
last
)
412
end
413
local
r
=
dn
.
reset
414
local
s
=
dn
.
set
415
if
first
<
=
last
and
first
<
=
r
then
416
if
trace_get
and
not
notrace
then
417
report_marks
(
"
action %a, name %a, first %a, last %a, reset %a, index %a
"
,
"
reset first
"
,
name
,
first
,
last
,
r
,
first
)
418
end
419
elseif
first
>
=
last
and
last
<
=
r
then
420
if
trace_get
and
not
notrace
then
421
report_marks
(
"
action %a, name %a, first %a, last %a, reset %a, index %a
"
,
"
reset last
"
,
name
,
first
,
last
,
r
,
last
)
422
end
423
elseif
not
stack
[
first
]
or
not
stack
[
last
]
then
424
if
trace_get
and
not
notrace
then
425
-- a previous or next method can give an out of range, which is valid
426
report_marks
(
"
error: out of range, name %a, reset %a, index %a
"
,
name
,
r
,
first
)
427
end
428
elseif
strict
then
429
local
top
=
stack
[
first
]
430
local
fullchain
=
dn
.
fullchain
431
if
not
fullchain
or
#
fullchain
=
=
0
then
432
if
trace_get
and
not
notrace
then
433
report_marks
(
"
warning: no full chain, trying again, name %a, first %a, last %a
"
,
name
,
first
,
last
)
434
end
435
return
resolve
(
name
,
first
,
last
)
436
else
437
if
trace_get
and
not
notrace
then
438
report_marks
(
"
found chain [ % => T ]
"
,
fullchain
)
439
end
440
local
chaindata
=
{
}
441
local
chainlength
=
#
fullchain
442
for
i
=
1
,
chainlength
do
443
local
cname
=
fullchain
[
i
]
444
if
data
[
cname
]
.
set
>
0
then
445
local
value
=
resolve
(
cname
,
first
,
last
,
false
,
false
,
true
)
446
if
value
=
=
"
"
then
447
if
trace_get
and
not
notrace
then
448
report_marks
(
"
quitting chain, name %a, reset %a, start %a
"
,
name
,
r
,
first
)
449
end
450
return
"
"
451
else
452
chaindata
[
i
]
=
value
453
end
454
end
455
end
456
if
trace_get
and
not
notrace
then
457
report_marks
(
"
using chain [ % => T ]
"
,
chaindata
)
458
end
459
local
value
,
index
,
found
=
resolve
(
name
,
first
,
last
,
false
,
false
,
true
)
460
if
value
~
=
"
"
then
461
if
trace_get
and
not
notrace
then
462
report_marks
(
"
following chain [ % => T ]
"
,
chaindata
)
463
end
464
for
i
=
1
,
chainlength
do
465
local
cname
=
fullchain
[
i
]
466
if
data
[
cname
]
.
set
>
0
and
chaindata
[
i
]
~
=
found
[
cname
]
then
467
if
trace_get
and
not
notrace
then
468
report_marks
(
"
quiting chain, name %a, reset %a, index %a
"
,
name
,
r
,
first
)
469
end
470
return
"
"
471
end
472
end
473
if
trace_get
and
not
notrace
then
474
report_marks
(
"
found in chain, name %a, reset %a, start %a, index %a, value %a
"
,
name
,
r
,
first
,
index
,
value
)
475
end
476
return
value
,
index
,
found
477
elseif
trace_get
and
not
notrace
then
478
report_marks
(
"
not found, name %a, reset %a
"
,
name
,
r
)
479
end
480
end
481
else
482
for
i
=
first
,
last
,
step
do
483
local
current
=
stack
[
i
]
484
local
value
=
current
and
current
[
name
]
485
if
value
=
=
nil
then
486
-- search on
487
elseif
value
=
=
false
then
488
if
quitonfalse
then
489
return
"
"
490
end
491
elseif
value
=
=
true
then
492
if
trace_get
and
not
notrace
then
493
report_marks
(
"
quitting steps, name %a, reset %a, start %a, index %a
"
,
name
,
r
,
first
,
i
)
494
end
495
return
"
"
496
elseif
value
~
=
"
"
then
497
if
trace_get
and
not
notrace
then
498
report_marks
(
"
found in steps, name %a, reset %a, start %a, index %a, value %a
"
,
name
,
r
,
first
,
i
,
value
)
499
end
500
return
value
,
i
,
current
501
end
502
end
503
if
trace_get
and
not
notrace
then
504
report_marks
(
"
not found in steps, name %a, reset %a
"
,
name
,
r
)
505
end
506
end
507
end
508
return
"
"
509
end
510 511
-- todo: column:first column:last
512 513
local
methods
=
{
}
514 515
local
function
doresolve
(
name
,
rangename
,
swap
,
df
,
dl
,
strict
)
516
local
range
=
ranges
[
rangename
]
or
ranges
[
v_page
]
517
local
first
=
range
.
first
518
local
last
=
range
.
last
519
if
trace_get
then
520
report_marks
(
"
action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a
"
,
521
"
resolving
"
,
name
,
rangename
,
swap
or
false
,
first
,
last
,
df
,
dl
,
strict
or
false
)
522
end
523
if
swap
then
524
first
,
last
=
last
+
df
,
first
+
dl
525
else
526
first
,
last
=
first
+
df
,
last
+
dl
527
end
528
local
value
,
index
,
found
=
resolve
(
name
,
first
,
last
,
strict
)
529
-- maybe something more
530
return
value
,
index
,
found
531
end
532 533
-- previous : last before sync
534
-- next : first after sync
535 536
-- top : first in sync
537
-- bottom : last in sync
538 539
-- first : first not top in sync
540
-- last : last not bottom in sync
541 542
methods
[
v_previous
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
false
,
-1
,
0
,
true
)
end
-- strict
543
methods
[
v_top
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
false
,
0
,
0
,
true
)
end
-- strict
544
methods
[
v_bottom
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
true
,
0
,
0
,
true
)
end
-- strict
545
methods
[
v_next
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
true
,
0
,
1
,
true
)
end
-- strict
546 547
methods
[
v_previous_nocheck
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
false
,
-1
,
0
,
false
)
end
548
methods
[
v_top_nocheck
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
false
,
0
,
0
,
false
)
end
549
methods
[
v_bottom_nocheck
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
true
,
0
,
0
,
false
)
end
550
methods
[
v_next_nocheck
]
=
function
(
name
,
range
)
return
doresolve
(
name
,
range
,
true
,
0
,
1
,
false
)
end
551 552
local
function
do_first
(
name
,
range
,
check
)
553
if
trace_get
then
554
report_marks
(
"
action %a, name %a, range %a
"
,
"
resolving first
"
,
name
,
range
)
555
end
556
local
f_value
,
f_index
,
f_found
=
doresolve
(
name
,
range
,
false
,
0
,
0
,
check
)
557
if
f_found
then
558
if
trace_get
then
559
report_marks
(
"
action %a, name %a, range %a
"
,
"
resolving last
"
,
name
,
range
)
560
end
561
local
l_value
,
l_index
,
l_found
=
doresolve
(
name
,
range
,
true
,
0
,
0
,
check
)
562
if
l_found
and
l_index
>
f_index
then
563
local
name
=
parentname
(
name
)
564
for
i
=
f_index
,
l_index
,
1
do
565
local
si
=
stack
[
i
]
566
local
sn
=
si
[
name
]
567
if
sn
and
sn
~
=
false
and
sn
~
=
true
and
sn
~
=
"
"
and
sn
~
=
f_value
then
568
if
trace_get
then
569
report_marks
(
"
action %a, name %a, range %a, index %a, value %a
"
,
"
resolving
"
,
name
,
range
,
i
,
sn
)
570
end
571
return
sn
,
i
,
si
572
end
573
end
574
end
575
end
576
if
trace_get
then
577
report_marks
(
"
resolved, name %a, range %a, using first
"
,
name
,
range
)
578
end
579
return
f_value
,
f_index
,
f_found
580
end
581 582
local
function
do_last
(
name
,
range
,
check
)
583
if
trace_get
then
584
report_marks
(
"
action %a, name %a, range %a
"
,
"
resolving last
"
,
name
,
range
)
585
end
586
local
l_value
,
l_index
,
l_found
=
doresolve
(
name
,
range
,
true
,
0
,
0
,
check
)
587
if
l_found
then
588
if
trace_get
then
589
report_marks
(
"
action %a, name %a, range %a
"
,
"
resolving first
"
,
name
,
range
)
590
end
591
local
f_value
,
f_index
,
f_found
=
doresolve
(
name
,
range
,
false
,
0
,
0
,
check
)
592
if
f_found
and
l_index
>
f_index
then
593
local
name
=
parentname
(
name
)
594
for
i
=
l_index
,
f_index
,
-1
do
595
local
si
=
stack
[
i
]
596
local
sn
=
si
[
name
]
597
if
sn
and
sn
~
=
false
and
sn
~
=
true
and
sn
~
=
"
"
and
sn
~
=
l_value
then
598
if
trace_get
then
599
report_marks
(
"
action %a, name %a, range %a, index %a, value %a
"
,
"
resolving
"
,
name
,
range
,
i
,
sn
)
600
end
601
return
sn
,
i
,
si
602
end
603
end
604
end
605
end
606
if
trace_get
then
607
report_marks
(
"
resolved, name %a, range %a, using first
"
,
name
,
range
)
608
end
609
return
l_value
,
l_index
,
l_found
610
end
611 612
methods
[
v_first
]
=
function
(
name
,
range
)
return
do_first
(
name
,
range
,
true
)
end
613
methods
[
v_last
]
=
function
(
name
,
range
)
return
do_last
(
name
,
range
,
true
)
end
614
methods
[
v_first_nocheck
]
=
function
(
name
,
range
)
return
do_first
(
name
,
range
,
false
)
end
615
methods
[
v_last_nocheck
]
=
function
(
name
,
range
)
return
do_last
(
name
,
range
,
false
)
end
616 617
methods
[
v_current
]
=
function
(
name
,
range
)
-- range is ignored here
618
local
top
=
stack
[
topofstack
]
619
return
top
and
top
[
parentname
(
name
)
]
or
"
"
620
end
621 622
local
function
fetched
(
name
,
range
,
method
)
623
local
value
=
(
methods
[
method
]
or
methods
[
v_first
]
)
(
name
,
range
)
or
"
"
624
if
not
trace_get
then
625
-- no report
626
elseif
value
=
=
"
"
then
627
report_marks
(
"
nothing fetched, name %a, range %a, method %a
"
,
name
,
range
,
method
)
628
else
629
report_marks
(
"
marking fetched, name %a, range %a, method %a, value %a
"
,
name
,
range
,
method
,
value
)
630
end
631
return
value
or
"
"
632
end
633 634
-- can be used at the lua end:
635 636
marks
.
fetched
=
fetched
637 638
-- this will move to a separate runtime modules
639 640
marks
.
tracers
=
marks
.
tracers
or
{
}
641 642
function
marks
.
tracers
.
showtable
(
)
643
context
.
starttabulate
{
"
|l|l|l|lp|lp|
"
}
644
context
.
tabulaterowbold
(
"
name
"
,
"
parent
"
,
"
chain
"
,
"
children
"
,
"
fullchain
"
)
645
context
.
ML
(
)
646
for
k
,
v
in
table
.
sortedpairs
(
data
)
do
647
local
parent
=
v
.
parent
or
"
"
648
local
chain
=
v
.
chain
or
"
"
649
local
children
=
v
.
children
or
{
}
650
local
fullchain
=
v
.
fullchain
or
{
}
651
table
.
sort
(
children
)
-- in-place but harmless
652
context
.
tabulaterowtyp
(
k
,
parent
,
chain
,
concat
(
children
,
"
"
)
,
concat
(
fullchain
,
"
"
)
)
653
end
654
context
.
stoptabulate
(
)
655
end
656 657
-- pushing to context:
658 659
-- local separator = context.nested.markingseparator
660
-- local command = context.nested.markingcommand
661
-- local ctxconcat = context.concat
662 663
-- local function fetchonemark(name,range,method)
664
-- context(command(name,fetched(name,range,method)))
665
-- end
666 667
-- local function fetchtwomarks(name,range)
668
-- ctxconcat( {
669
-- command(name,fetched(name,range,v_first)),
670
-- command(name,fetched(name,range,v_last)),
671
-- }, separator(name))
672
-- end
673 674
-- local function fetchallmarks(name,range)
675
-- ctxconcat( {
676
-- command(name,fetched(name,range,v_previous)),
677
-- command(name,fetched(name,range,v_first)),
678
-- command(name,fetched(name,range,v_last)),
679
-- }, separator(name))
680
-- end
681 682
local
ctx_separator
=
context
.
markingseparator
683
local
ctx_command
=
context
.
markingcommand
684 685
local
function
fetchonemark
(
name
,
range
,
method
)
686
ctx_command
(
name
,
fetched
(
name
,
range
,
method
)
)
687
end
688 689
local
function
fetchtwomarks
(
name
,
range
)
690
ctx_command
(
name
,
fetched
(
name
,
range
,
v_first
)
)
691
ctx_separator
(
name
)
692
ctx_command
(
name
,
fetched
(
name
,
range
,
v_last
)
)
693
end
694 695
local
function
fetchallmarks
(
name
,
range
)
696
ctx_command
(
name
,
fetched
(
name
,
range
,
v_previous
)
)
697
ctx_separator
(
name
)
698
ctx_command
(
name
,
fetched
(
name
,
range
,
v_first
)
)
699
ctx_separator
(
name
)
700
ctx_command
(
name
,
fetched
(
name
,
range
,
v_last
)
)
701
end
702 703
function
marks
.
fetch
(
name
,
range
,
method
)
-- chapter page first | chapter column:1 first
704
if
trace_get
then
705
report_marks
(
"
marking requested, name %a, range %a, method %a
"
,
name
,
range
,
method
)
706
end
707
if
method
=
=
"
"
or
method
=
=
v_default
then
708
fetchonemark
(
name
,
range
,
v_first
)
709
elseif
method
=
=
v_both
then
710
fetchtwomarks
(
name
,
range
)
711
elseif
method
=
=
v_all
then
712
fetchallmarks
(
name
,
range
)
713
else
714
fetchonemark
(
name
,
range
,
method
)
715
end
716
end
717 718
function
marks
.
fetchonemark
(
name
,
range
,
method
)
fetchonemark
(
name
,
range
,
method
)
end
719
function
marks
.
fetchtwomarks
(
name
,
range
)
fetchtwomarks
(
name
,
range
)
end
720
function
marks
.
fetchallmarks
(
name
,
range
)
fetchallmarks
(
name
,
range
)
end
721 722
-- here we have a few helpers .. will become commands.*
723 724
local
pattern
=
lpeg
.
afterprefix
(
"
li::
"
)
725 726
function
marks
.
title
(
tag
,
n
)
727
local
listindex
=
lpegmatch
(
pattern
,
n
)
728
if
listindex
then
729
commands
.
savedlisttitle
(
tag
,
listindex
,
"
marking
"
)
730
else
731
context
(
n
)
732
end
733
end
734 735
function
marks
.
number
(
tag
,
n
)
-- no spec
736
local
listindex
=
lpegmatch
(
pattern
,
n
)
737
if
listindex
then
738
commands
.
savedlistnumber
(
tag
,
listindex
)
739
else
740
-- no prefix (as it is the prefix)
741
context
(
n
)
742
end
743
end
744 745
-- interface
746 747
implement
{
name
=
"
markingtitle
"
,
actions
=
marks
.
title
,
arguments
=
"
2 strings
"
}
748
implement
{
name
=
"
markingnumber
"
,
actions
=
marks
.
number
,
arguments
=
"
2 strings
"
}
749 750
implement
{
name
=
"
definemarking
"
,
actions
=
marks
.
define
,
arguments
=
"
2 strings
"
}
751
implement
{
name
=
"
relatemarking
"
,
actions
=
marks
.
relate
,
arguments
=
"
2 strings
"
}
752
implement
{
name
=
"
setmarking
"
,
actions
=
marks
.
set
,
arguments
=
"
2 strings
"
}
753
implement
{
name
=
"
resetmarking
"
,
actions
=
marks
.
reset
,
arguments
=
"
string
"
}
754
implement
{
name
=
"
synchronizemarking
"
,
actions
=
marks
.
synchronize
,
arguments
=
{
"
string
"
,
"
integer
"
,
"
string
"
}
}
755
implement
{
name
=
"
getmarking
"
,
actions
=
marks
.
fetch
,
arguments
=
"
3 strings
"
}
756
implement
{
name
=
"
fetchonemark
"
,
actions
=
marks
.
fetchonemark
,
arguments
=
"
3 strings
"
}
757
implement
{
name
=
"
fetchtwomarks
"
,
actions
=
marks
.
fetchtwomarks
,
arguments
=
"
2 strings
"
}
758
implement
{
name
=
"
fetchallmarks
"
,
actions
=
marks
.
fetchallmarks
,
arguments
=
"
2 strings
"
}
759 760
implement
{
name
=
"
doifelsemarking
"
,
actions
=
{
marks
.
exists
,
commands
.
doifelse
}
,
arguments
=
"
string
"
}
761