summaryrefslogtreecommitdiff
path: root/scripts/context/lua/mtx-synctex.lua
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/context/lua/mtx-synctex.lua')
-rw-r--r--scripts/context/lua/mtx-synctex.lua261
1 files changed, 261 insertions, 0 deletions
diff --git a/scripts/context/lua/mtx-synctex.lua b/scripts/context/lua/mtx-synctex.lua
new file mode 100644
index 000000000..3c4f6ee71
--- /dev/null
+++ b/scripts/context/lua/mtx-synctex.lua
@@ -0,0 +1,261 @@
+if not modules then modules = { } end modules ['mtx-synctex'] = {
+ version = 1.002,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- InverseSearchCmdLine = scite.exe "%f" "-goto:%l" $
+-- InverseSearchCmdLine = mtxrun.exe --script synctex --edit --name="%f" --line="%l" $
+
+local tonumber = tonumber
+local find, match, gsub = string.find, string.match, string.gsub
+local isfile = lfs.isfile
+local longtostring = string.longtostring
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-synctex</entry>
+ <entry name="detail">SyncTeX Checker</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="edit"><short>open file at line: --line=.. --editor=.. sourcefile</short></flag>
+ <flag name="list"><short>show blob: synctexfile</short></flag>
+ <flag name="goto"><short>open file at position: --page=.. --x=.. --y=.. --editor=.. synctexfile</short></flag>
+ <flag name="report"><short>show file and line: --page=.. --x=.. --y=.. --console synctexfile</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-synctex",
+ banner = "ConTeXt SyncTeX Checker 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+local editors = {
+ console = function(specification)
+ print(string.formatters["%q %i"](specification.filename,specification.linenumber or 1))
+ end,
+ scite = sandbox.registerrunner {
+ name = "scite",
+ program = {
+ windows = "scite",
+ unix = "SciTE",
+ },
+ template = longtostring [[
+ "%filename%"
+ "-goto:%linenumber%"
+ ]],
+ },
+}
+
+local function validfile(filename)
+ if not filename or not isfile(filename) then
+ report("invalid synctex log file %a",filename)
+ return false
+ else
+ return true
+ end
+end
+
+local function editfile(filename,line,editor)
+ if not validfile(filename) then
+ return
+ end
+ local runner = editors[editor or "scite"] or editors.scite
+ runner {
+ filename = filename,
+ linenumber = tonumber(line) or 1,
+ }
+end
+
+-- In context we only care about explicitly marked horizontal blobs. And this is
+-- only a check script. I know of no viewer that calls the synctex command line
+-- version. Otherwise we could provide our own simplified variant and even
+-- consider a more compact format (for instance we could use an "=" when the value
+-- of x y w h d is the same as before, which is actually often the case for y, h
+-- and d).
+
+local factor = (7200/7227)/65536 -- we assume unit 1
+local quit = true -- we only have one hit anyway
+
+local function findlocation(filename,page,xpos,ypos)
+ if not validfile(filename) then
+ return
+ elseif not page then
+ page = 1
+ elseif not xpos or not ypos then
+ report("provide x and y coordinates (unit: basepoints)")
+ return
+ end
+ local files = { }
+ local found = false
+ local skip = false
+ local dx = false
+ local dy = false
+ local px = xpos / factor
+ local py = ypos / factor
+ local fi = 0
+ local ln = 0
+ for line in io.lines(filename) do
+ if found then
+ if find(line,"^}") then
+ break
+ else
+ -- we only look at positive cases
+ local f, l, x, y, w, h, d = match(line,"^h(.-),(.-):(.-),(.-):(.-),(.-),(.-)$")
+ if f and f ~= 0 then
+ x = tonumber(x)
+ if px >= x then
+ w = tonumber(w)
+ if px <= x + w then
+ y = tonumber(y)
+ d = tonumber(d)
+ if py >= y - d then
+ h = tonumber(h)
+ if py <= y + h then
+ if quit then
+ -- we have no overlapping boxes
+ fi = f
+ ln = l
+ break
+ else
+ local lx = px - x
+ local rx = x + w - px
+ local by = py - y + d
+ local ty = y + h - py
+ mx = lx < rx and lx or rx
+ my = by < ty and by or ty
+ if not dx then
+ dx = mx
+ dy = my
+ fi = f
+ ln = l
+ else
+ if mx < dx then
+ dx = mx
+ di = f
+ ln = l
+ end
+ if my < dy then
+ dy = my
+ fi = f
+ ln = l
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ elseif skip then
+ if find(line,"^}") then
+ skip = false
+ end
+ elseif find(line,"^{(%d+)") then
+ local p = tonumber(match(line,"^{(%d+)"))
+ if p == page then
+ found = true
+ else
+ skip = true
+ end
+ elseif find(line,"^Input:") then
+ local id, name = match(line,"^Input:(.-):(.-)$")
+ if id then
+ files[id] = name
+ end
+ end
+ end
+ if fi ~= 0 then
+ return files[fi], ln
+ end
+end
+
+local function showlocation(filename)
+ if not validfile(filename) then
+ return
+ end
+ local files = { }
+ local found = false
+ local page = 0
+ for line in io.lines(filename) do
+ if found then
+ if find(line,"^}") then
+ found = false
+ report("end page: %i",page)
+ else
+ local f, l, x, y, w, h, d = match(line,"^h(.-),(.-):(.-),(.-):(.-),(.-),(.-)$")
+ if f then
+ x = tonumber(x)
+ y = tonumber(y)
+ local llx = factor * ( x )
+ local lly = factor * ( y - tonumber(d) )
+ local urx = factor * ( x + tonumber(w) )
+ local ury = factor * ( y + tonumber(h) )
+ f = files[f]
+ if f then
+ report(" [% 4r % 4r % 4r % 4r] : % 5i : %s",llx,lly,urx,ury,l,f)
+ end
+ end
+ end
+ elseif find(line,"^{(%d+)") then
+ page = tonumber(match(line,"^{(%d+)"))
+ found = true
+ report("begin page: %i",page)
+ elseif find(line,"^Input:") then
+ local id, name = match(line,"^Input:(.-):(.-)$")
+ if id then
+ files[id] = name
+ end
+ end
+ end
+end
+
+local function gotolocation(filename,page,xpos,ypos,editor)
+ if filename then
+ local target, line = findlocation(filename,tonumber(page),tonumber(xpos),tonumber(ypos))
+ if target and line then
+ if editor then
+ editfile(target,line,editor)
+ else
+ report("filename=%a linenumber=%a",target,line)
+ end
+ end
+ end
+end
+
+-- print(findlocation("oeps.synctex",4,318,348))
+-- print(findlocation("oeps.synctex",40,378,348))
+-- print(gotolocation("oeps.synctex",4,318,348,"scite"))
+-- print(showlocation("oeps.synctex"))
+
+local argument = environment.argument
+local filename = environment.files[1]
+
+if argument("edit") then
+ editfile(filename,argument("line"),argument("editor"))
+elseif argument("goto") then
+ gotolocation(filename,argument("page"),argument("x"),argument("y"),argument("editor"))
+elseif argument("report") then
+ gotolocation(filename,argument("page"),argument("x"),argument("y"),"console")
+elseif argument("list") then
+ showlocation(filename)
+elseif argument("exporthelp") then
+ application.export(argument("exporthelp"),filename)
+else
+ application.help()
+end
+