node-syn.lua /size: 25 Kb    last modification: 2021-10-28 13:50
1if 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
125local type, rawset = type, rawset
126local concat = table.concat
127local formatters = string.formatters
128local replacesuffix, suffixonly, nameonly, collapsepath = file.replacesuffix, file.suffix, file.nameonly, file.collapsepath
129local openfile, renamefile, removefile = io.open, os.rename, os.remove
130
131local report_system = logs.reporter("system")
132
133local tex                = tex
134local texget             = tex.get
135
136local nuts               = nodes.nuts
137
138local getid              = nuts.getid
139local getlist            = nuts.getlist
140local setlist            = nuts.setlist
141local getnext            = nuts.getnext
142local getwhd             = nuts.getwhd
143local getwidth           = nuts.getwidth
144local getsubtype         = nuts.getsubtype
145
146local nodecodes          = nodes.nodecodes
147local kerncodes          = nodes.kerncodes
148
149local glyph_code         = nodecodes.glyph
150local disc_code          = nodecodes.disc
151local glue_code          = nodecodes.glue
152local penalty_code       = nodecodes.penalty
153local kern_code          = nodecodes.kern
154----- rule_code          = nodecodes.rule
155local hlist_code         = nodecodes.hlist
156local vlist_code         = nodecodes.vlist
157local dir_code           = nodecodes.dir
158local fontkern_code      = kerncodes.fontkern
159
160local cancel_code        = nodes.dircodes.cancel
161
162local insertbefore       = nuts.insertbefore
163local insertafter        = nuts.insertafter
164
165local nodepool           = nuts.pool
166local new_latelua        = nodepool.latelua
167local new_rule           = nodepool.rule
168local new_kern           = nodepool.kern
169
170local getdimensions      = nuts.dimensions
171local getrangedimensions = nuts.rangedimensions
172
173local getsynctexfields   = nuts.getsynctexfields
174local forcesynctextag    = tex.forcesynctextag   or tex.force_synctex_tag
175local forcesynctexline   = tex.forcesynctexline  or tex.force_synctex_line
176local getsynctexline     = tex.getsynctexline    or tex.get_synctex_line
177local setsynctexmode     = tex.setsynctexmode    or tex.set_synctex_mode
178
179local foundintree        = resolvers.foundintree
180
181local 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"]
188local z_hlist            = "[0,0:0,0:0,0,0\010"
189local z_vlist            = "(0,0:0,0:0,0,0\010"
190----- z_xform            = "<0,0:0,0,0\010" -- or so
191local s_hlist            = "]\010"
192local s_vlist            = ")\010"
193----- s_xform            = ">\010"
194local f_hlist_1          = formatters["h%i,%i:%i,%i:%i,%i,%i\010"]
195local f_hlist_2          = formatters["h%i,%i:%i,%s:%i,%i,%i\010"]
196local f_vlist_1          = formatters["v%i,%i:%i,%i:%i,%i,%i\010"]
197local f_vlist_2          = formatters["v%i,%i:%i,%s:%i,%i,%i\010"]
198
199local synctex            = luatex.synctex or { }
200luatex.synctex           = synctex
201
202local getpos ; getpos = function() getpos = job.positions.getpos return getpos() end
203
204-- status stuff
205
206local enabled = false
207local paused  = 0
208local used    = false
209local never   = false
210
211-- get rid of overhead in mkiv
212
213if tex.set_synctex_no_files then
214    tex.set_synctex_no_files(1)
215end
216
217-- the file name stuff
218
219local noftags            = 0
220local stnums             = { }
221local nofblocked         = 0
222local blockedfilenames   = { }
223local 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
234local 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
257end)
258
259function synctex.blockfilename(name)
260    blockedfilenames[nameonly(name)] = name
261end
262
263function 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
270end
271
272function synctex.resetfilename()
273    if paused == 0 then
274        forcesynctextag(0)
275        forcesynctexline(0)
276    end
277end
278
279do
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
305end
306
307-- the node stuff
308
309local filehandle = nil
310local nofsheets  = 0
311local nofobjects = 0
312local last       = 0
313local filesdone  = 0
314local tmpfile    = false
315local logfile    = false
316
317local function writeanchor()
318    local size = filehandle:seek("end")
319    filehandle:write("!",size-last,eol)
320    last = size
321end
322
323local 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
331end
332
333local function makenames()
334    logfile = replacesuffix(tex.jobname,"synctex")
335    tmpfile = replacesuffix(logfile,"syncctx")
336end
337
338local 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
358end
359
360function synctex.wrapup()
361    if tmpfile then
362        renamefile(tmpfile,logfile)
363        tmpfile = nil
364    end
365end
366
367local 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
378end
379
380local getpagedimensions  getpagedimensions = function()
381    getpagedimensions = backends.codeinjections.getpagedimensions
382    return getpagedimensions()
383end
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
430local 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
483end
484
485-- color is already handled so no colors
486
487local collect     = nil
488local fulltrace   = false
489local trace       = false
490local height      = 10 * 65536
491local depth       =  5 * 65536
492local traceheight =      32768
493local tracedepth  =      32768
494
495trackers.register("system.synctex.visualize", function(v)
496    trace     = v
497    fulltrace = v == "real"
498end)
499
500local 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
514end
515
516local 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
565end
566
567local 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
581end
582
583local 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
685end
686
687collect = collect_max
688
689function synctex.collect(head,where)
690    if enabled and where ~= "object" then
691        return collect(head,head)
692    else
693        return head
694    end
695end
696
697-- also no solution for bad first file resolving in sumatra
698
699function 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
711end
712
713function 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
721end
722
723local enablers  = { }
724local disablers = { }
725
726function synctex.registerenabler(f)
727    enablers[#enablers+1] = f
728end
729
730function synctex.registerdisabler(f)
731    disablers[#disablers+1] = f
732end
733
734function 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
747end
748
749function 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
758end
759
760function synctex.finish()
761    if enabled then
762        flushpostamble()
763    else
764        makenames()
765        removefile(logfile)
766        removefile(tmpfile)
767    end
768end
769
770local filename = nil
771
772function synctex.pause()
773    paused = paused + 1
774    if enabled and paused == 1 then
775        setsynctexmode(0)
776    end
777end
778
779function synctex.resume()
780    if enabled and paused == 1 then
781        setsynctexmode(3)
782    end
783    paused = paused - 1
784end
785
786-- not the best place
787
788luatex.registerstopactions(synctex.finish)
789
790statistics.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
795end)
796
797local implement = interfaces.implement
798local variables = interfaces.variables
799
800function 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
816end
817
818implement {
819    name      = "synctexblockfilename",
820    arguments = "string",
821    actions   = synctex.blockfilename,
822}
823
824implement {
825    name      = "synctexsetfilename",
826    arguments = "string",
827    actions   = synctex.setfilename,
828}
829
830implement {
831    name      = "synctexresetfilename",
832    actions   = synctex.resetfilename,
833}
834
835implement {
836    name      = "setupsynctex",
837    actions   = synctex.setup,
838    arguments = {
839        {
840            { "state" },
841            { "method" },
842        },
843    },
844}
845
846implement {
847    name    = "synctexpause",
848    actions = synctex.pause,
849}
850
851implement {
852    name    = "synctexresume",
853    actions = synctex.resume,
854}
855
856implement {
857    name    = "synctexpushline",
858    actions = synctex.pushline,
859}
860
861implement {
862    name    = "synctexpopline",
863    actions = synctex.popline,
864}
865
866implement {
867    name    = "synctexdisable",
868    actions = synctex.disable,
869}
870