diff options
Diffstat (limited to 'tex/context/base/trac-deb.lua')
-rw-r--r-- | tex/context/base/trac-deb.lua | 180 |
1 files changed, 127 insertions, 53 deletions
diff --git a/tex/context/base/trac-deb.lua b/tex/context/base/trac-deb.lua index 4cc48c4a5..d998295c1 100644 --- a/tex/context/base/trac-deb.lua +++ b/tex/context/base/trac-deb.lua @@ -9,27 +9,32 @@ if not modules then modules = { } end modules ['trac-deb'] = { local lpeg, status = lpeg, status local lpegmatch = lpeg.match -local format, concat, match = string.format, table.concat, string.match +local format, concat, match, find = string.format, table.concat, string.match, string.find local tonumber, tostring = tonumber, tostring -- maybe tracers -> tracers.tex (and tracers.lua for current debugger) -local report_system = logs.reporter("system","tex") +----- report_tex = logs.reporter("tex error") +----- report_lua = logs.reporter("lua error") +local report_nl = logs.newline +local report_str = logs.writer -tracers = tracers or { } -local tracers = tracers +tracers = tracers or { } +local tracers = tracers -tracers.lists = { } -local lists = tracers.lists +tracers.lists = { } +local lists = tracers.lists -tracers.strings = { } -local strings = tracers.strings +tracers.strings = { } +local strings = tracers.strings -local texgetdimen = tex.getdimen -local texgettoks = tex.gettoks -local texgetcount = tex.getcount +local texgetdimen = tex.getdimen +local texgettoks = tex.gettoks +local texgetcount = tex.getcount -strings.undefined = "undefined" +local implement = interfaces.implement + +strings.undefined = "undefined" lists.scratch = { 0, 2, 4, 6, 8 @@ -96,7 +101,19 @@ function tracers.knownlist(name) return l and #l > 0 end -function tracers.showlines(filename,linenumber,offset,errorstr) +local savedluaerror = nil + +local function errorreporter(luaerror) + if luaerror then + logs.enable("lua error") -- + return logs.reporter("lua error") + else + logs.enable("tex error") + return logs.reporter("tex error") + end +end + +function tracers.showlines(filename,linenumber,offset,luaerrorline) local data = io.loaddata(filename) if not data or data == "" then local hash = url.hashed(filename) @@ -109,35 +126,21 @@ function tracers.showlines(filename,linenumber,offset,errorstr) end local lines = data and string.splitlines(data) if lines and #lines > 0 then - -- This does not work completely as we cannot access the last Lua error using - -- table.print(status.list()). This is on the agenda. Eventually we will - -- have a sequence of checks here (tex, lua, mp) at this end. - -- - -- Actually, in 0.75+ the lua error message is even weirder as you can - -- get: - -- - -- LuaTeX error [string "\directlua "]:3: unexpected symbol near '1' ... - -- - -- <inserted text> \endgroup \directlua { - -- - -- So there is some work to be done in the LuaTeX engine. - -- - local what, where = match(errorstr,[[LuaTeX error <main (%a+) instance>:(%d+)]]) - or match(errorstr,[[LuaTeX error %[string "\\(.-lua) "%]:(%d+)]]) -- buglet - if where then + if luaerrorline and luaerrorline > 0 then -- lua error: linenumber points to last line local start = "\\startluacode" local stop = "\\stopluacode" - local where = tonumber(where) - if lines[linenumber] == start then - local n = linenumber - for i=n,1,-1 do - if lines[i] == start then - local n = i + where - if n <= linenumber then - linenumber = n - end + 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 @@ -159,30 +162,84 @@ function tracers.showlines(filename,linenumber,offset,errorstr) end end -function tracers.printerror(offset) - local inputstack = resolvers.inputstack - local filename = inputstack[#inputstack] or status.filename - local linenumber = tonumber(status.linenumber) or 0 +-- this will work ok in >=0.79 + +-- 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 function processerror(offset) + local inputstack = resolvers.inputstack + local filename = inputstack[#inputstack] or status.filename + local linenumber = tonumber(status.linenumber) or 0 + -- + -- print("[[ last tex error: " .. tostring(status.lasterrorstring) .. " ]]") + -- print("[[ last lua error: " .. tostring(status.lastluaerrorstring) .. " ]]") + -- print("[[ start errorcontext ]]") + -- tex.show_context() + -- print("\n[[ stop errorcontext ]]") + -- + local lasttexerror = status.lasterrorstring or "?" + local lastluaerror = status.lastluaerrorstring or lasttexerror + local luaerrorline = match(lastluaerror,[[lua%]?:.-(%d+)]]) or (lastluaerror and find(lastluaerror,"?:0:",1,true) and 0) + local report = errorreporter(luaerrorline) + tracers.printerror { + filename = filename, + linenumber = linenumber, + lasttexerror = lasttexerror, + lastluaerror = lastluaerror, + luaerrorline = luaerrorline, + offset = tonumber(offset) or 10, + } +end + +-- so one can overload the printer if (really) needed + +function tracers.printerror(specification) + local filename = specification.filename + local linenumber = specification.linenumber + local lasttexerror = specification.lasttexerror + local lastluaerror = specification.lastluaerror + local luaerrorline = specification.luaerrorline + local offset = specification.offset + local report = errorreporter(luaerrorline) if not filename then - report_system("error not related to input file: %s ...",status.lasterrorstring) + report("error not related to input file: %s ...",lasttexerror) elseif type(filename) == "number" then - report_system("error on line %s of filehandle %s: %s ...",linenumber,filename,status.lasterrorstring) + report("error on line %s of filehandle %s: %s ...",linenumber,lasttexerror) else - -- currently we still get the error message printed to the log/console so we - -- add a bit of spacing around our variant - texio.write_nl("\n") - local errorstr = status.lasterrorstring or "?" - -- inspect(status.list()) - report_system("error on line %s in file %s: %s ...\n",linenumber,filename,errorstr) -- lua error? - texio.write_nl(tracers.showlines(filename,linenumber,offset,errorstr),"\n") + report_nl() + if luaerrorline then + report("error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror) + -- report("error on line %s in file %s:\n\n%s",linenumber,filename,lasttexerror) + else + report("error on line %s in file %s: %s",linenumber,filename,lasttexerror) + if tex.show_context then + report_nl() + tex.show_context() + end + end + report_nl() + report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline))) + report_nl() end end +local nop = function() end + directives.register("system.errorcontext", function(v) + local register = callback.register if v then - callback.register('show_error_hook', function() tracers.printerror(v) end) + register('show_error_message', nop) + register('show_error_hook', function() processerror(v) end) + register('show_lua_error_hook', nop) else - callback.register('show_error_hook', nil) + register('show_error_message', nil) + register('show_error_hook', nil) + register('show_lua_error_hook', nil) end end) @@ -249,3 +306,20 @@ local function trace_calls(n) end directives.register("system.tracecalls", function(n) trace_calls(n) end) -- indirect is needed for nilling + +implement { name = "showtrackers", actions = trackers.show } +implement { name = "enabletrackers", actions = trackers.enable, arguments = "string" } +implement { name = "disabletrackers", actions = trackers.disable, arguments = "string" } +implement { name = "resettrackers", actions = trackers.reset } + +implement { name = "showdirectives", actions = directives.show } +implement { name = "enabledirectives", actions = directives.enable, arguments = "string" } +implement { name = "disabledirectives", actions = directives.disable, arguments = "string" } + +implement { name = "showexperiments", actions = experiments.show } +implement { name = "enableexperiments", actions = experiments.enable, arguments = "string" } +implement { name = "disableexperiments", actions = experiments.disable, arguments = "string" } + +implement { name = "showdebuginfo", actions = lmx.showdebuginfo } +implement { name = "overloaderror", actions = lmx.overloaderror } +implement { name = "showlogcategories", actions = logs.show } |