node-syn.lua /size: 25 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
node-syn
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to node-ini.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
-- Because we have these fields in some node that are used by synctex, and because
10
-- some users seem to like that feature, I decided to implement a variant that might
11
-- work out better for ConTeXt. This is experimental code. I don't use it myself so
12
-- it will take a while to mature. There will be some helpers that one can use in
13
-- more complex situations like included xml files. Currently (somewhere else) we
14
-- take care of valid files, that is: we prohibit access to files in the tree
15
-- because we don't want users to mess up styles.
16
--
17
-- It is unclear how the output gets interpreted but by reverse engineering (and
18
-- stripping) the file generated by generic synctex, I got there eventually. For
19
-- instance, we only need to be able to go back to a place where text is entered,
20
-- but still we need all that redundant box wrapping. Anyway, I was able to get a
21
-- minimal output and cross my fingers that the parser used in editors is not
22
-- changed in fundamental ways.
23
--
24
-- I only tested SumatraPDF with SciTE, for which one needs to configure in the
25
-- viewer:
26
--
27
-- InverseSearchCmdLine = c:\data\system\scite\wscite\scite.exe "%f" "-goto:%l" $
28
--
29
-- In fact, a way more powerful implementation would have been not to add a library
30
-- to a viewer, but letthe viewer call an external program:
31
--
32
-- InverseSearchCmdLine = mtxrun.exe --script synctex --edit --name="%f" --line="%l" $
33
--
34
-- which would (re)launch the editor in the right spot. That way we can really
35
-- tune well to the macro package used and also avoid the fuzzy heuristics of
36
-- the library.
37
--
38
-- Unfortunately syntex always removes the files at the end and not at the start
39
-- (this happens in synctexterminate) so we need to work around that by using an
40
-- intermediate file. This is no big deal in context (which has a runner) but
41
-- definitely not nice.
42
--
43
-- The visualizer code is only needed for testing so we don't use fancy colors or
44
-- provide more detail. After all we're only interested in rendered source text
45
-- anyway. We try to play safe which sometimes means that we'd better no go
46
-- somewhere than go someplace wrong.
47
--
48
-- A previous version had a mode for exporting boxes and such but I removed that
49
-- as it made no sense. Also, collecting output in a table was not faster than
50
-- directly piping to the file, probably because the amount is not that large. We
51
-- keep some left-overs commented.
52
--
53
-- A significate reduction in file size can be realized when reusing the same
54
-- values. Actually that triggered the current approach in ConTeXt. In the latest
55
-- synctex parser vertical positions can be repeated by an "=" sign but for some
56
-- reason only for that field. It's probably trivial to do that for all of "w h d v
57
-- h" but it currently not the case so I'll delay that till all are supported. (We
58
-- could benefit a lot from such a repetition scheme but not much from a "v" alone
59
-- which -alas- indicates that synctex is still mostly a latex targeted story.)
60
--
61
-- It's kind of hard to fight the parser because it really wants to go to some file
62
-- but maybe some day I can figure it out. Some untagged text (in the pdf) somehow
63
-- gets seen as part of the last box. Anonymous content is simply not part of the
64
-- concept. Using a dummy name doesn't help either as the editor gets a signal to
65
-- open that dummy. Even an empty filename doesn't work.
66
--
67
-- We output really simple and compact code, like:
68
--
69
-- SyncTeX Version:1
70
-- Input:1:e:/tmp/oeps.tex
71
-- Input:2:c:/data/develop/context/sources/klein.tex
72
-- Output:pdf
73
-- Magnification:1000
74
-- Unit:1
75
-- X Offset:0
76
-- Y Offset:0
77
-- Content:
78
-- !160
79
-- {1
80
-- h0,0:0,0,0,0,0
81
-- v0,0:0,55380990:39158276,55380990,0
82
-- h2,1:4661756,9176901:27969941,655360,327680
83
-- h2,2:4661756,10125967:26048041,655360,327680
84
-- h2,3:30962888,10125967:1668809,655360,327680
85
-- h2,3:4661756,11075033:23142527,655360,327680
86
-- h2,4:28046650,11075033:4585047,655360,327680
87
-- h2,4:4661756,12024099:22913954,655360,327680
88
-- h2,5:27908377,12024099:4723320,655360,327680
89
-- h2,5:4661756,12973165:22918783,655360,327680
90
-- h2,6:27884864,12973165:4746833,655360,327680
91
-- h2,6:4661756,13922231:18320732,655360,327680
92
-- ]
93
-- !533
94
-- }1
95
-- Input:3:c:/data/develop/context/sources/ward.tex
96
-- !57
97
-- {2
98
-- h0,0:0,0,0,0,0
99
-- v0,0:0,55380990:39158276,55380990,0
100
-- h3,1:4661756,9176901:18813145,655360,327680
101
-- h3,2:23713999,9176901:8917698,655360,327680
102
-- h3,2:4661756,10125967:10512978,655360,327680
103
-- h3,3:15457206,10125967:17174491,655360,327680
104
-- h3,3:4661756,11075033:3571223,655360,327680
105
-- h3,4:8459505,11075033:19885281,655360,327680
106
-- h3,5:28571312,11075033:4060385,655360,327680
107
-- h3,5:4661756,12024099:15344870,655360,327680
108
-- ]
109
-- !441
110
-- }2
111
-- !8
112
-- Postamble:
113
-- Count:22
114
-- !23
115
-- Post scriptum:
116
--
117
-- But for some reason, when the pdf file has some extra content (like page numbers)
118
-- the main document is consulted. Bah. It would be nice to have a mode for *only*
119
-- looking at marked areas. It somehow works not but maybe depends on the parser.
120
--
121
-- Supporting reuseable objects makes not much sense as these are often graphics or
122
-- ornamental. They can not have hyperlinks etc (at least not without some hackery
123
-- which I'm not willing to do) so basically they are sort of useless for text.
124 125
local
type
,
rawset
=
type
,
rawset
126
local
concat
=
table
.
concat
127
local
formatters
=
string
.
formatters
128
local
replacesuffix
,
suffixonly
,
nameonly
,
collapsepath
=
file
.
replacesuffix
,
file
.
suffix
,
file
.
nameonly
,
file
.
collapsepath
129
local
openfile
,
renamefile
,
removefile
=
io
.
open
,
os
.
rename
,
os
.
remove
130 131
local
report_system
=
logs
.
reporter
(
"
system
"
)
132 133
local
tex
=
tex
134
local
texget
=
tex
.
get
135 136
local
nuts
=
nodes
.
nuts
137 138
local
getid
=
nuts
.
getid
139
local
getlist
=
nuts
.
getlist
140
local
setlist
=
nuts
.
setlist
141
local
getnext
=
nuts
.
getnext
142
local
getwhd
=
nuts
.
getwhd
143
local
getwidth
=
nuts
.
getwidth
144
local
getsubtype
=
nuts
.
getsubtype
145 146
local
nodecodes
=
nodes
.
nodecodes
147
local
kerncodes
=
nodes
.
kerncodes
148 149
local
glyph_code
=
nodecodes
.
glyph
150
local
disc_code
=
nodecodes
.
disc
151
local
glue_code
=
nodecodes
.
glue
152
local
penalty_code
=
nodecodes
.
penalty
153
local
kern_code
=
nodecodes
.
kern
154
----- rule_code = nodecodes.rule
155
local
hlist_code
=
nodecodes
.
hlist
156
local
vlist_code
=
nodecodes
.
vlist
157
local
dir_code
=
nodecodes
.
dir
158
local
fontkern_code
=
kerncodes
.
fontkern
159 160
local
cancel_code
=
nodes
.
dircodes
.
cancel
161 162
local
insertbefore
=
nuts
.
insertbefore
163
local
insertafter
=
nuts
.
insertafter
164 165
local
nodepool
=
nuts
.
pool
166
local
new_latelua
=
nodepool
.
latelua
167
local
new_rule
=
nodepool
.
rule
168
local
new_kern
=
nodepool
.
kern
169 170
local
getdimensions
=
nuts
.
dimensions
171
local
getrangedimensions
=
nuts
.
rangedimensions
172 173
local
getsynctexfields
=
nuts
.
getsynctexfields
174
local
forcesynctextag
=
tex
.
forcesynctextag
or
tex
.
force_synctex_tag
175
local
forcesynctexline
=
tex
.
forcesynctexline
or
tex
.
force_synctex_line
176
local
getsynctexline
=
tex
.
getsynctexline
or
tex
.
get_synctex_line
177
local
setsynctexmode
=
tex
.
setsynctexmode
or
tex
.
set_synctex_mode
178 179
local
foundintree
=
resolvers
.
foundintree
180 181
local
eol
=
"
\010
"
182 183
----- f_glue = formatters["g%i,%i:%i,%i\010"]
184
----- f_glyph = formatters["x%i,%i:%i,%i\010"]
185
----- f_kern = formatters["k%i,%i:%i,%i:%i\010"]
186
----- f_rule = formatters["r%i,%i:%i,%i:%i,%i,%i\010"]
187
----- f_form = formatters["f%i,%i,%i\010"]
188
local
z_hlist
=
"
[0,0:0,0:0,0,0\010
"
189
local
z_vlist
=
"
(0,0:0,0:0,0,0\010
"
190
----- z_xform = "<0,0:0,0,0\010" -- or so
191
local
s_hlist
=
"
]\010
"
192
local
s_vlist
=
"
)\010
"
193
----- s_xform = ">\010"
194
local
f_hlist_1
=
formatters
[
"
h%i,%i:%i,%i:%i,%i,%i\010
"
]
195
local
f_hlist_2
=
formatters
[
"
h%i,%i:%i,%s:%i,%i,%i\010
"
]
196
local
f_vlist_1
=
formatters
[
"
v%i,%i:%i,%i:%i,%i,%i\010
"
]
197
local
f_vlist_2
=
formatters
[
"
v%i,%i:%i,%s:%i,%i,%i\010
"
]
198 199
local
synctex
=
luatex
.
synctex
or
{
}
200
luatex
.
synctex
=
synctex
201 202
local
getpos
;
getpos
=
function
(
)
getpos
=
job
.
positions
.
getpos
return
getpos
(
)
end
203 204
-- status stuff
205 206
local
enabled
=
false
207
local
paused
=
0
208
local
used
=
false
209
local
never
=
false
210 211
-- get rid of overhead in mkiv
212 213
if
tex
.
set_synctex_no_files
then
214
tex
.
set_synctex_no_files
(
1
)
215
end
216 217
-- the file name stuff
218 219
local
noftags
=
0
220
local
stnums
=
{
}
221
local
nofblocked
=
0
222
local
blockedfilenames
=
{
}
223
local
blockedsuffixes
=
{
224
mkii
=
true
,
225
mkiv
=
true
,
226
mkvi
=
true
,
227
mkxl
=
true
,
228
mklx
=
true
,
229
mkix
=
true
,
230
mkxi
=
true
,
231
-- lfg = true,
232
}
233 234
local
sttags
=
table
.
setmetatableindex
(
function
(
t
,
fullname
)
235
local
name
=
collapsepath
(
fullname
)
236
if
blockedsuffixes
[
suffixonly
(
name
)
]
then
237
-- Just so that I don't get the ones on my development tree.
238
nofblocked
=
nofblocked
+
1
239
return
0
240
elseif
blockedfilenames
[
nameonly
(
name
)
]
then
241
-- So we can block specific files.
242
nofblocked
=
nofblocked
+
1
243
return
0
244
elseif
foundintree
(
name
)
then
245
-- One shouldn't edit styles etc this way.
246
nofblocked
=
nofblocked
+
1
247
return
0
248
else
249
noftags
=
noftags
+
1
250
t
[
name
]
=
noftags
251
if
name
~
=
fullname
then
252
t
[
fullname
]
=
noftags
253
end
254
stnums
[
noftags
]
=
name
255
return
noftags
256
end
257
end
)
258 259
function
synctex
.
blockfilename
(
name
)
260
blockedfilenames
[
nameonly
(
name
)
]
=
name
261
end
262 263
function
synctex
.
setfilename
(
name
,
line
)
264
if
paused
=
=
0
and
name
then
265
forcesynctextag
(
sttags
[
name
]
)
266
if
line
then
267
forcesynctexline
(
line
)
268
end
269
end
270
end
271 272
function
synctex
.
resetfilename
(
)
273
if
paused
=
=
0
then
274
forcesynctextag
(
0
)
275
forcesynctexline
(
0
)
276
end
277
end
278 279
do
280 281
local
nesting
=
0
282
local
ignored
=
false
283 284
function
synctex
.
pushline
(
)
285
nesting
=
nesting
+
1
286
if
nesting
=
=
1
then
287
local
l
=
getsynctexline
(
)
288
ignored
=
l
and
l
>
0
289
if
not
ignored
then
290
forcesynctexline
(
texget
(
"
inputlineno
"
)
)
291
end
292
end
293
end
294 295
function
synctex
.
popline
(
)
296
if
nesting
=
=
1
then
297
if
not
ignored
then
298
forcesynctexline
(
)
299
ignored
=
false
300
end
301
end
302
nesting
=
nesting
-
1
303
end
304 305
end
306 307
-- the node stuff
308 309
local
filehandle
=
nil
310
local
nofsheets
=
0
311
local
nofobjects
=
0
312
local
last
=
0
313
local
filesdone
=
0
314
local
tmpfile
=
false
315
local
logfile
=
false
316 317
local
function
writeanchor
(
)
318
local
size
=
filehandle
:
seek
(
"
end
"
)
319
filehandle
:
write
(
"
!
"
,
size
-
last
,
eol
)
320
last
=
size
321
end
322 323
local
function
writefiles
(
)
324
local
total
=
#
stnums
325
if
filesdone
<
total
then
326
for
i
=
filesdone
+
1
,
total
do
327
filehandle
:
write
(
"
Input:
"
,
i
,
"
:
"
,
stnums
[
i
]
,
eol
)
328
end
329
filesdone
=
total
330
end
331
end
332 333
local
function
makenames
(
)
334
logfile
=
replacesuffix
(
tex
.
jobname
,
"
synctex
"
)
335
tmpfile
=
replacesuffix
(
logfile
,
"
syncctx
"
)
336
end
337 338
local
function
flushpreamble
(
)
339
makenames
(
)
340
filehandle
=
openfile
(
tmpfile
,
"
wb
"
)
341
if
filehandle
then
342
filehandle
:
write
(
"
SyncTeX Version:1
"
,
eol
)
343
writefiles
(
)
344
filehandle
:
write
(
"
Output:pdf
"
,
eol
)
345
filehandle
:
write
(
"
Magnification:1000
"
,
eol
)
346
filehandle
:
write
(
"
Unit:1
"
,
eol
)
347
filehandle
:
write
(
"
X Offset:0
"
,
eol
)
348
filehandle
:
write
(
"
Y Offset:0
"
,
eol
)
349
filehandle
:
write
(
"
Content:
"
,
eol
)
350
flushpreamble
=
function
(
)
351
writefiles
(
)
352
return
filehandle
353
end
354
else
355
enabled
=
false
356
end
357
return
filehandle
358
end
359 360
function
synctex
.
wrapup
(
)
361
if
tmpfile
then
362
renamefile
(
tmpfile
,
logfile
)
363
tmpfile
=
nil
364
end
365
end
366 367
local
function
flushpostamble
(
)
368
if
not
filehandle
then
369
return
370
end
371
writeanchor
(
)
372
filehandle
:
write
(
"
Postamble:
"
,
eol
)
373
filehandle
:
write
(
"
Count:
"
,
nofobjects
,
eol
)
374
writeanchor
(
)
375
filehandle
:
write
(
"
Post scriptum:
"
,
eol
)
376
filehandle
:
close
(
)
377
enabled
=
false
378
end
379 380
local
getpagedimensions
getpagedimensions
=
function
(
)
381
getpagedimensions
=
backends
.
codeinjections
.
getpagedimensions
382
return
getpagedimensions
(
)
383
end
384 385
-- local function doaction(action,t,l,w,h,d)
386
-- local pagewidth, pageheight = getpagedimensions()
387
-- local x, y = getpos()
388
-- filehandle:write(action(t,l,x,pageheight-y,w,h,d))
389
-- nofobjects = nofobjects + 1
390
-- end
391
--
392
-- local function noaction(action)
393
-- filehandle:write(action)
394
-- nofobjects = nofobjects + 1
395
-- end
396
--
397
-- local function b_vlist(head,current,t,l,w,h,d)
398
-- return insertbefore(head,current,new_latelua(function() doaction(f_vlist,t,l,w,h,d) end))
399
-- end
400
--
401
-- local function b_hlist(head,current,t,l,w,h,d)
402
-- return insertbefore(head,current,new_latelua(function() doaction(f_hlist,t,l,w,h,d) end))
403
-- end
404
--
405
-- local function e_vlist(head,current)
406
-- return insertafter(head,current,new_latelua(noaction(s_vlist)))
407
-- end
408
--
409
-- local function e_hlist(head,current)
410
-- return insertafter(head,current,new_latelua(noaction(s_hlist)))
411
-- end
412
--
413
-- local function x_vlist(head,current,t,l,w,h,d)
414
-- return insertbefore(head,current,new_latelua(function() doaction(f_vlist_1,t,l,w,h,d) end))
415
-- end
416
--
417
-- local function x_hlist(head,current,t,l,w,h,d)
418
-- return insertbefore(head,current,new_latelua(function() doaction(f_hlist_1,t,l,w,h,d) end))
419
-- end
420
--
421
-- generic
422
--
423
-- local function doaction(t,l,w,h,d)
424
-- local pagewidth, pageheight = getpagedimensions()
425
-- local x, y = getpos()
426
-- filehandle:write(f_hlist_1(t,l,x,pageheight-y,w,h,d))
427
-- nofobjects = nofobjects + 1
428
-- end
429 430
local
x_hlist
do
431 432
local
function
doaction_1
(
t
,
l
,
w
,
h
,
d
)
433
local
pagewidth
,
pageheight
=
getpagedimensions
(
)
434
local
x
,
y
=
getpos
(
)
435
filehandle
:
write
(
f_hlist_1
(
t
,
l
,
x
,
pageheight
-
y
,
w
,
h
,
d
)
)
436
nofobjects
=
nofobjects
+
1
437
end
438 439
-- local lastx, lasty, lastw, lasth, lastd
440
--
441
-- local function doaction_2(t,l,w,h,d)
442
-- local pagewidth, pageheight = getpagedimensions()
443
-- local x, y = getpos()
444
-- y = pageheight-y
445
-- filehandle:write(f_hlist_2(t,l,
446
-- x == lastx and "=" or x,
447
-- y == lasty and "=" or y,
448
-- w == lastw and "=" or w,
449
-- h == lasth and "=" or h,
450
-- d == lastd and "=" or d
451
-- ))
452
-- lastx, lasty, lastw, lasth, lastd = x, y, w, h, d
453
-- nofobjects = nofobjects + 1
454
-- end
455
--
456
-- but ... only y is supported:
457 458
local
lasty
=
false
459 460
local
function
doaction_2
(
t
,
l
,
w
,
h
,
d
)
461
local
pagewidth
,
pageheight
=
getpagedimensions
(
)
462
local
x
,
y
=
getpos
(
)
463
y
=
pageheight
-
y
464
filehandle
:
write
(
f_hlist_2
(
t
,
l
,
x
,
y
=
=
lasty
and
"
=
"
or
y
,
w
,
h
,
d
)
)
465
lasty
=
y
466
nofobjects
=
nofobjects
+
1
467
end
468 469
local
doaction
=
doaction_1
470 471
x_hlist
=
function
(
head
,
current
,
t
,
l
,
w
,
h
,
d
)
472
if
filehandle
then
473
return
insertbefore
(
head
,
current
,
new_latelua
(
function
(
)
doaction
(
t
,
l
,
w
,
h
,
d
)
end
)
)
474
else
475
return
head
476
end
477
end
478 479
directives
.
register
(
"
system.synctex.compression
"
,
function
(
v
)
480
doaction
=
tonumber
(
v
)
=
=
2
and
doaction_2
or
doaction_1
481
end
)
482 483
end
484 485
-- color is already handled so no colors
486 487
local
collect
=
nil
488
local
fulltrace
=
false
489
local
trace
=
false
490
local
height
=
10
*
65536
491
local
depth
=
5
*
65536
492
local
traceheight
=
32768
493
local
tracedepth
=
32768
494 495
trackers
.
register
(
"
system.synctex.visualize
"
,
function
(
v
)
496
trace
=
v
497
fulltrace
=
v
=
=
"
real
"
498
end
)
499 500
local
function
inject
(
head
,
first
,
last
,
tag
,
line
)
501
local
w
,
h
,
d
=
getdimensions
(
first
,
getnext
(
last
)
)
502
if
h
<
height
then
503
h
=
height
504
end
505
if
d
<
depth
then
506
d
=
depth
507
end
508
if
trace
then
509
head
=
insertbefore
(
head
,
first
,
new_rule
(
w
,
fulltrace
and
h
or
traceheight
,
fulltrace
and
d
or
tracedepth
)
)
510
head
=
insertbefore
(
head
,
first
,
new_kern
(
-
w
)
)
511
end
512
head
=
x_hlist
(
head
,
first
,
tag
,
line
,
w
,
h
,
d
)
513
return
head
514
end
515 516
local
function
collect_min
(
head
)
517
local
current
=
head
518
while
current
do
519
local
id
=
getid
(
current
)
520
if
id
=
=
glyph_code
then
521
local
first
=
current
522
local
last
=
current
523
local
tag
=
0
524
local
line
=
0
525
while
true
do
526
if
id
=
=
glyph_code
then
527
local
tc
,
lc
=
getsynctexfields
(
current
)
528
if
tc
and
tc
>
0
then
529
tag
=
tc
530
line
=
lc
531
end
532
last
=
current
533
elseif
id
=
=
disc_code
or
(
id
=
=
kern_code
and
getsubtype
(
current
)
=
=
fontkern_code
)
then
534
last
=
current
535
else
536
if
tag
>
0
then
537
head
=
inject
(
head
,
first
,
last
,
tag
,
line
)
538
end
539
break
540
end
541
current
=
getnext
(
current
)
542
if
current
then
543
id
=
getid
(
current
)
544
else
545
if
tag
>
0
then
546
head
=
inject
(
head
,
first
,
last
,
tag
,
line
)
547
end
548
return
head
549
end
550
end
551
end
552
-- pick up (as id can have changed)
553
if
id
=
=
hlist_code
or
id
=
=
vlist_code
then
554
local
list
=
getlist
(
current
)
555
if
list
then
556
local
l
=
collect
(
list
)
557
if
l
~
=
list
then
558
setlist
(
current
,
l
)
559
end
560
end
561
end
562
current
=
getnext
(
current
)
563
end
564
return
head
565
end
566 567
local
function
inject
(
parent
,
head
,
first
,
last
,
tag
,
line
)
568
local
w
,
h
,
d
=
getrangedimensions
(
parent
,
first
,
getnext
(
last
)
)
569
if
h
<
height
then
570
h
=
height
571
end
572
if
d
<
depth
then
573
d
=
depth
574
end
575
if
trace
then
576
head
=
insertbefore
(
head
,
first
,
new_rule
(
w
,
fulltrace
and
h
or
traceheight
,
fulltrace
and
d
or
tracedepth
)
)
577
head
=
insertbefore
(
head
,
first
,
new_kern
(
-
w
)
)
578
end
579
head
=
x_hlist
(
head
,
first
,
tag
,
line
,
w
,
h
,
d
)
580
return
head
581
end
582 583
local
function
collect_max
(
head
,
parent
)
584
local
current
=
head
585
while
current
do
586
local
id
=
getid
(
current
)
587
if
id
=
=
glyph_code
then
588
local
first
=
current
589
local
last
=
current
590
local
tag
=
0
591
local
line
=
0
592
while
true
do
593
if
id
=
=
glyph_code
then
594
local
tc
,
lc
=
getsynctexfields
(
current
)
595
if
tc
and
tc
>
0
then
596
if
tag
>
0
and
(
tag
~
=
tc
or
line
~
=
lc
)
then
597
head
=
inject
(
parent
,
head
,
first
,
last
,
tag
,
line
)
598
first
=
current
599
end
600
tag
=
tc
601
line
=
lc
602
last
=
current
603
else
604
if
tag
>
0
then
605
head
=
inject
(
parent
,
head
,
first
,
last
,
tag
,
line
)
606
tag
=
0
607
end
608
first
=
nil
609
last
=
nil
610
end
611
elseif
id
=
=
disc_code
then
612
if
not
first
then
613
first
=
current
614
end
615
last
=
current
616
elseif
id
=
=
kern_code
and
getsubtype
(
current
)
=
=
fontkern_code
then
617
if
first
then
618
last
=
current
619
end
620
elseif
id
=
=
glue_code
then
621
if
tag
>
0
then
622
local
tc
,
lc
=
getsynctexfields
(
current
)
623
if
tc
and
tc
>
0
then
624
if
tag
~
=
tc
or
line
~
=
lc
then
625
head
=
inject
(
parent
,
head
,
first
,
last
,
tag
,
line
)
626
tag
=
0
627
break
628
end
629
else
630
head
=
inject
(
parent
,
head
,
first
,
last
,
tag
,
line
)
631
tag
=
0
632
break
633
end
634
else
635
tag
=
0
636
break
637
end
638
id
=
nil
-- so no test later on
639
elseif
id
=
=
penalty_code
then
640
-- go on (and be nice for math)
641
else
642
if
tag
>
0
then
643
head
=
inject
(
parent
,
head
,
first
,
last
,
tag
,
line
)
644
tag
=
0
645
end
646
break
647
end
648
current
=
getnext
(
current
)
649
if
current
then
650
id
=
getid
(
current
)
651 652
-- while id == dir_code do
653
-- current = getnext(current)
654
-- if current then
655
-- id = getid(current)
656
-- else
657
-- if tag > 0 then
658
-- head = inject(parent,head,first,last,tag,line)
659
-- end
660
-- return head
661
-- end
662
-- end
663 664
else
665
if
tag
>
0
then
666
head
=
inject
(
parent
,
head
,
first
,
last
,
tag
,
line
)
667
end
668
return
head
669
end
670
end
671
end
672
-- pick up (as id can have changed)
673
if
id
=
=
hlist_code
or
id
=
=
vlist_code
then
674
local
list
=
getlist
(
current
)
675
if
list
then
676
local
l
=
collect
(
list
,
current
)
677
if
l
and
l
~
=
list
then
678
setlist
(
current
,
l
)
679
end
680
end
681
end
682
current
=
getnext
(
current
)
683
end
684
return
head
685
end
686 687
collect
=
collect_max
688 689
function
synctex
.
collect
(
head
,
where
)
690
if
enabled
and
where
~
=
"
object
"
then
691
return
collect
(
head
,
head
)
692
else
693
return
head
694
end
695
end
696 697
-- also no solution for bad first file resolving in sumatra
698 699
function
synctex
.
start
(
)
700
if
enabled
then
701
nofsheets
=
nofsheets
+
1
-- could be realpageno
702
if
flushpreamble
(
)
then
703
writeanchor
(
)
704
filehandle
:
write
(
"
{
"
,
nofsheets
,
eol
)
705
-- this seems to work:
706
local
pagewidth
,
pageheight
=
getpagedimensions
(
)
707
filehandle
:
write
(
z_hlist
)
708
filehandle
:
write
(
f_vlist_1
(
0
,
0
,
0
,
pageheight
,
pagewidth
,
pageheight
,
0
)
)
709
end
710
end
711
end
712 713
function
synctex
.
stop
(
)
714
if
enabled
then
715
-- filehandle:write(s_vlist,s_hlist)
716
filehandle
:
write
(
s_hlist
)
717
writeanchor
(
)
718
filehandle
:
write
(
"
}
"
,
nofsheets
,
eol
)
719
nofobjects
=
nofobjects
+
2
720
end
721
end
722 723
local
enablers
=
{
}
724
local
disablers
=
{
}
725 726
function
synctex
.
registerenabler
(
f
)
727
enablers
[
#
enablers
+
1
]
=
f
728
end
729 730
function
synctex
.
registerdisabler
(
f
)
731
disablers
[
#
disablers
+
1
]
=
f
732
end
733 734
function
synctex
.
enable
(
)
735
if
not
never
and
not
enabled
then
736
enabled
=
true
737
setsynctexmode
(
3
)
-- we want details
738
if
not
used
then
739
nodes
.
tasks
.
enableaction
(
"
shipouts
"
,
"
luatex.synctex.collect
"
)
740
report_system
(
"
synctex functionality is enabled, expect 5-10 pct runtime overhead!
"
)
741
used
=
true
742
end
743
for
i
=
1
,
#
enablers
do
744
enablers
[
i
]
(
true
)
745
end
746
end
747
end
748 749
function
synctex
.
disable
(
)
750
if
enabled
then
751
setsynctexmode
(
0
)
752
report_system
(
"
synctex functionality is disabled!
"
)
753
enabled
=
false
754
for
i
=
1
,
#
disablers
do
755
disablers
[
i
]
(
false
)
756
end
757
end
758
end
759 760
function
synctex
.
finish
(
)
761
if
enabled
then
762
flushpostamble
(
)
763
else
764
makenames
(
)
765
removefile
(
logfile
)
766
removefile
(
tmpfile
)
767
end
768
end
769 770
local
filename
=
nil
771 772
function
synctex
.
pause
(
)
773
paused
=
paused
+
1
774
if
enabled
and
paused
=
=
1
then
775
setsynctexmode
(
0
)
776
end
777
end
778 779
function
synctex
.
resume
(
)
780
if
enabled
and
paused
=
=
1
then
781
setsynctexmode
(
3
)
782
end
783
paused
=
paused
-
1
784
end
785 786
-- not the best place
787 788
luatex
.
registerstopactions
(
synctex
.
finish
)
789 790
statistics
.
register
(
"
synctex tracing
"
,
function
(
)
791
if
used
then
792
return
string
.
format
(
"
%i referenced files, %i files ignored, %i objects flushed, logfile: %s
"
,
793
noftags
,
nofblocked
,
nofobjects
,
logfile
)
794
end
795
end
)
796 797
local
implement
=
interfaces
.
implement
798
local
variables
=
interfaces
.
variables
799 800
function
synctex
.
setup
(
t
)
801
if
t
.
state
=
=
variables
.
never
then
802
synctex
.
disable
(
)
-- just in case
803
never
=
true
804
return
805
end
806
if
t
.
method
=
=
variables
.
max
then
807
collect
=
collect_max
808
else
809
collect
=
collect_min
810
end
811
if
t
.
state
=
=
variables
.
start
then
812
synctex
.
enable
(
)
813
else
814
synctex
.
disable
(
)
815
end
816
end
817 818
implement
{
819
name
=
"
synctexblockfilename
"
,
820
arguments
=
"
string
"
,
821
actions
=
synctex
.
blockfilename
,
822
}
823 824
implement
{
825
name
=
"
synctexsetfilename
"
,
826
arguments
=
"
string
"
,
827
actions
=
synctex
.
setfilename
,
828
}
829 830
implement
{
831
name
=
"
synctexresetfilename
"
,
832
actions
=
synctex
.
resetfilename
,
833
}
834 835
implement
{
836
name
=
"
setupsynctex
"
,
837
actions
=
synctex
.
setup
,
838
arguments
=
{
839
{
840
{
"
state
"
}
,
841
{
"
method
"
}
,
842
}
,
843
}
,
844
}
845 846
implement
{
847
name
=
"
synctexpause
"
,
848
actions
=
synctex
.
pause
,
849
}
850 851
implement
{
852
name
=
"
synctexresume
"
,
853
actions
=
synctex
.
resume
,
854
}
855 856
implement
{
857
name
=
"
synctexpushline
"
,
858
actions
=
synctex
.
pushline
,
859
}
860 861
implement
{
862
name
=
"
synctexpopline
"
,
863
actions
=
synctex
.
popline
,
864
}
865 866
implement
{
867
name
=
"
synctexdisable
"
,
868
actions
=
synctex
.
disable
,
869
}
870