diff options
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.lmt | 417 |
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) |