summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkxl/trac-deb.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkxl/trac-deb.lmt')
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/trac-deb.lmt417
1 files changed, 417 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkxl/trac-deb.lmt b/Master/texmf-dist/tex/context/base/mkxl/trac-deb.lmt
new file mode 100644
index 00000000000..8ff12410528
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/trac-deb.lmt
@@ -0,0 +1,417 @@
+if not modules then modules = { } end modules ['trac-deb'] = {
+ version = 1.001,
+ comment = "companion to trac-deb.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is an old mechanism, a result of some experiments in the early days of
+-- luatex and mkiv, but still nice anyway. I will clean it up in lmtx.
+
+local status = status
+
+local tonumber, tostring, type = tonumber, tostring, type
+local format, concat, match, find, gsub = string.format, table.concat, string.match, string.find, string.gsub
+
+local report_nl = logs.newline
+local report_str = logs.writer
+
+tracers = tracers or { }
+local tracers = tracers
+
+local implement = interfaces.implement
+
+local ioflush = io.flush
+local ioread = io.read
+local writenl = texio.write_nl
+local write = texio.write
+
+local runlocal = tex.runlocal
+local terminaldata = false
+local context = context
+
+implement {
+ name = "fetchterminaldata",
+ actions = function()
+ context(terminaldata)
+ end,
+}
+
+function texio.terminal()
+ writenl("\n" .. "entering interactive mode, use \\quit to abort reading" .."\n\n")
+ while true do
+ write(">")
+ ioflush()
+ terminaldata = ioread()
+ if terminaldata == "\\quit" then
+ terminaldata = false
+ break
+ else
+ runlocal("t_syst_terminal_data",nil,nil,true) -- obeymode
+ end
+ end
+end
+
+implement {
+ name = "readfromterminal",
+ public = true,
+ protected = true,
+ actions = texio.terminal,
+}
+
+local savedluaerror = nil
+local usescitelexer = nil
+local quitonerror = true
+
+local function errorreporter(luaerror)
+ local category = luaerror and "lua error" or "tex error"
+ local report = logs.reporter(category)
+ logs.enable(category)
+ return report
+end
+
+function tracers.showlines(filename,linenumber,offset,luaerrorline)
+ local data = io.loaddata(filename)
+ if not data or data == "" then
+ local hash = url.hashed(filename)
+ if not hash.noscheme then
+ local ok, d, n = resolvers.loaders.byscheme(hash.scheme,filename)
+ if ok and n > 0 then
+ data = d
+ end
+ end
+ end
+ local scite = usescitelexer and require("util-sci")
+ if scite then
+ return utilities.scite.tohtml(data,"tex",linenumber or true,false)
+ else
+ local lines = data and string.splitlines(data)
+ if lines and #lines > 0 then
+ if luaerrorline and luaerrorline > 0 then
+ -- lua error: linenumber points to last line
+ local start = "\\startluacode"
+ local stop = "\\stopluacode"
+ local n = linenumber
+ for i=n,1,-1 do
+ local line = lines[i]
+ if not line then
+ break
+ elseif find(line,start) then
+ n = i + luaerrorline - 1
+ if n <= linenumber then
+ linenumber = n
+ end
+ break
+ end
+ end
+ end
+ offset = tonumber(offset) or 10
+ linenumber = tonumber(linenumber) or 10
+ local start = math.max(linenumber - offset,1)
+ local stop = math.min(linenumber + offset,#lines)
+ if stop > #lines then
+ return "<linenumber past end of file>"
+ else
+ local result, fmt = { }, "%" .. #tostring(stop) .. "d %s %s"
+ for n=start,stop do
+ result[#result+1] = format(fmt,n,n == linenumber and ">>" or " ",lines[n])
+ end
+ return concat(result,"\n")
+ end
+ else
+ return "<empty file>"
+ end
+ end
+end
+
+-- todo: last tex error has ! prepended
+-- todo: some nested errors have two line numbers
+-- todo: collect errorcontext in string (after code cleanup)
+-- todo: have a separate status.lualinenumber
+-- todo: \starttext bla \blank[foo] bla \stoptext
+
+local nop = function() end
+local resetmessages = status.resetmessages or nop
+
+local function processerror(offset,errortype)
+ local readstate = status.readstate
+ local filename = readstate.filename
+ local linenumber = readstate.linenumber
+ local skiplinenumber = readstate.skiplinenumber
+ local errorstate = status.errorstate
+ local lastcontext = errorstate.errorcontext
+ local lasttexerror = errorstate.error or "?"
+ local lastluaerror = errorstate.luaerror or "?" -- lasttexerror
+ local luaerrorline = match(lastluaerror,[[lua%]?:.-(%d+)]]) or (lastluaerror and find(lastluaerror,"?:0:",1,true) and 0)
+ local lastmpserror = match(lasttexerror,[[^.-mp%serror:%s*(.*)$]])
+ resetmessages()
+ lastluaerror = gsub(lastluaerror,"%[\\directlua%]","[ctxlua]")
+ tracers.printerror {
+ filename = filename,
+ linenumber = linenumber,
+ skiplinenumber = skiplinenumber,
+ offset = tonumber(offset) or 10,
+ lasttexerror = lasttexerror,
+ lastmpserror = lastmpserror,
+ lastluaerror = lastluaerror, -- can be the same as lasttexerror
+ luaerrorline = luaerrorline,
+ lastcontext = lastcontext,
+ lasttexhelp = tex.gethelptext and tex.gethelptext() or nil,
+ errortype = errortype,
+ }
+ if job and type(job.disablesave) == "function" then
+ job.disablesave()
+ end
+end
+
+directives.register("system.quitonerror",function(v)
+ quitonerror = toboolean(v)
+end)
+
+directives.register("system.usescitelexer",function(v)
+ usescitelexer = toboolean(v)
+end)
+
+local busy = false
+
+function tracers.printerror(specification)
+ if not busy then
+ busy = true
+ local errorvalues = table.swapped(tex.geterrorvalues())
+ local filename = specification.filename
+ local linenumber = specification.linenumber
+ local lasttexerror = specification.lasttexerror
+ local lastmpserror = specification.lastmpserror
+ local lastluaerror = specification.lastluaerror
+ local lastcontext = specification.lastcontext
+ local luaerrorline = specification.luaerrorline
+ local errortype = specification.errortype
+ local offset = specification.offset
+ local endoffile = specification.endoffile
+ local report = errorreporter(luaerrorline)
+ if errortype == errorvalues.warning then
+ report("warning error: %s",lasttexerror or "-")
+ busy = false;
+ return;
+ elseif errortype == errorvalues.eof then
+ report("runaway error: %s",lasttexerror or "-")
+ if not quitonerror and texio.terminal then
+ texio.terminal() -- not well tested
+ end
+ elseif errortype == errorvalues.condition then
+ linenumber = specification.skiplinenumber
+ if linenumber > 0 then
+ report("condition error on line %s in file %s: %s",linenumber,filename,lasttexerror)
+ report_nl()
+ report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline)))
+ report_nl()
+ else
+ report("runaway condition error: %s",lasttexerror or "-")
+ end
+ quitonerror = true
+ elseif not filename then
+ report("fuzzy error:")
+ report(" tex: %s",lasttexerror or "-")
+ report(" lua: %s",lastluaerror or "-")
+ report(" mps: %s",lastmpserror or "-")
+ elseif type(filename) == "number" then
+ report("error on line %s of filehandle %s: %s ...",linenumber,lasttexerror)
+ else
+ report_nl()
+ if luaerrorline then
+ if linenumber == 0 or not filename or filename == "" then
+ print("\nfatal lua error:\n\n",lastluaerror,"\n")
+ luatex.abort()
+ return
+ else
+ report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror)
+ end
+ elseif lastmpserror then
+ report("mp error on line %s in file %s:\n\n%s",linenumber,filename,lastmpserror)
+ else
+ report("tex error on line %s in file %s: %s",linenumber,filename,lasttexerror)
+ if lastcontext then
+ report_nl()
+ report_str(lastcontext)
+ report_nl()
+ else
+ report_nl()
+ -- tex.showcontext()
+ end
+ if lastluaerror and not match(lastluaerror,"^%s*[%?]*%s*$") then
+ print("\nlua error:\n\n",lastluaerror,"\n")
+ quitonerror = true
+ end
+ end
+ report_nl()
+ report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline)))
+ report_nl()
+ end
+ local errname = file.addsuffix(tex.jobname .. "-error","log")
+ if quitonerror then
+ table.save(errname,specification)
+ local help = specification.lasttexhelp
+ if help and #help > 0 then
+ report_nl()
+ report_str(help)
+ report_nl()
+ report_nl()
+ end
+ luatex.abort()
+ end
+ busy = false
+ end
+end
+
+luatex.wrapup(function() os.remove(file.addsuffix(tex.jobname .. "-error","log")) end)
+
+local function processwarning(offset)
+ local warningstate = status.warningstate
+ local lastwarning = warningstate.warning or "?"
+ local lastlocation = warningstate.warningtag or "?"
+ resetmessages()
+ tracers.printwarning {
+ lastwarning = lastwarning,
+ lastlocation = lastlocation,
+ }
+end
+
+function tracers.printwarning(specification)
+ logs.report("luatex warning","%s: %s",specification.lastlocation,specification.lastwarning)
+end
+
+directives.register("system.errorcontext", function(v)
+ local register = callback.register
+ if v then
+ register('show_error_message', nop)
+ register('show_warning_message', function() processwarning(v) end)
+ register('intercept_lua_error', function() processerror(v) end)
+ register('intercept_tex_error', function(mode,eof) processerror(v,eof) return mode end)
+ else
+ register('show_error_message', nil)
+ register('show_warning_message', nil)
+ register('intercept_lua_error', nil)
+ register('intercept_tex_error', nil)
+ end
+end)
+
+-- this might move
+
+lmx = lmx or { }
+
+lmx.htmfile = function(name) return environment.jobname .. "-status.html" end
+lmx.lmxfile = function(name) return resolvers.findfile(name,'tex') end
+
+local function reportback(lmxname,default,variables)
+ if lmxname == false then
+ return variables
+ else
+ local name = lmx.show(type(lmxname) == "string" and lmxname or default,variables)
+ if name then
+ logs.report("context report","file: %s",name)
+ end
+ end
+end
+
+local function showerror(lmxname)
+ local readstate = status.readstate()
+ local filename = readstate.filename
+ local linenumber = tonumber(readstate.linenumber) or 0
+ local errorcontext = ""
+ if not filename then
+ filename = status.iocodes[readstate.iocode]
+ errorcontext = 'error in filename'
+ else
+ errorcontext = tracers.showlines(filename,linenumber,offset)
+ end
+ local variables = {
+ ['title'] = 'ConTeXt Error Information',
+ ['errormessage'] = status.errorstatus.error or "?",
+ ['linenumber'] = linenumber,
+ ['color-background-one'] = lmx.get('color-background-yellow'),
+ ['color-background-two'] = lmx.get('color-background-purple'),
+ ['filename'] = filename,
+ ['errorcontext'] = errorcontext,
+ }
+ reportback(lmxname,"context-error.lmx",variables)
+ luatex.abort()
+end
+
+lmx.showerror = showerror
+
+function lmx.overloaderror(v)
+ if v == "scite" then
+ usescitelexer = true
+ end
+ callback.register('show_error_message', function() showerror() end)
+ callback.register('intercept_lua_error', function() showerror() end)
+ callback.register('intercept_tex_error', function() showerror() end)
+end
+
+directives.register("system.showerror", lmx.overloaderror)
+
+-- local debugger = utilities.debugger
+--
+-- local function trace_calls(n)
+-- debugger.enable()
+-- luatex.registerstopactions(function()
+-- debugger.disable()
+-- debugger.savestats(tex.jobname .. "-luacalls.log",tonumber(n))
+-- end)
+-- trace_calls = function() end
+-- end
+--
+-- directives.register("system.tracecalls", function(n)
+-- trace_calls(n)
+-- end) -- indirect is needed for nilling
+
+-- Obsolete ... not that usefull as normally one runs from an editor and
+-- when run unattended it makes no sense either.
+
+-- local editor = [[scite "-open:%filename%" -goto:%linenumber%]]
+--
+-- directives.register("system.editor",function(v)
+-- editor = v
+-- end)
+--
+-- callback.register("call_edit",function(filename,linenumber)
+-- if editor then
+-- editor = gsub(editor,"%%s",filename)
+-- editor = gsub(editor,"%%d",linenumber)
+-- editor = gsub(editor,"%%filename%%",filename)
+-- editor = gsub(editor,"%%linenumber%%",linenumber)
+-- logs.report("system","starting editor: %s",editor)
+-- os.execute(editor)
+-- end
+-- end)
+
+implement { name = "showtrackers", public = true, protected = true, actions = trackers.show }
+implement { name = "enabletrackers", public = true, protected = true, actions = trackers.enable, arguments = "optional" }
+implement { name = "disabletrackers", public = true, protected = true, actions = trackers.disable, arguments = "optional" }
+implement { name = "resettrackers", public = true, protected = true, actions = trackers.reset }
+
+implement { name = "showdirectives", public = true, protected = true, actions = directives.show }
+implement { name = "enabledirectives", public = true, protected = true, actions = directives.enable, arguments = "optional" }
+implement { name = "disabledirectives", public = true, protected = true, actions = directives.disable, arguments = "optional" }
+
+implement { name = "showexperiments", public = true, protected = true, actions = experiments.show }
+implement { name = "enableexperiments", public = true, protected = true, actions = experiments.enable, arguments = "optional" }
+implement { name = "disableexperiments", public = true, protected = true, actions = experiments.disable, arguments = "optional" }
+
+implement { name = "overloaderror", public = true, protected = true, actions = lmx.overloaderror }
+implement { name = "showlogcategories", public = true, protected = true, actions = logs.show }
+
+local debugger = utilities.debugger
+
+directives.register("system.profile",function(n)
+ luatex.registerstopactions(function()
+ debugger.disable()
+ debugger.savestats("luatex-profile.log",tonumber(n) or 0)
+ report_nl()
+ logs.report("system","profiler stopped, log saved in %a","luatex-profile.log")
+ report_nl()
+ end)
+ logs.report("system","profiler started")
+ debugger.enable()
+end)