summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/luat-log.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/luat-log.lmt')
-rw-r--r--tex/context/base/mkiv/luat-log.lmt739
1 files changed, 0 insertions, 739 deletions
diff --git a/tex/context/base/mkiv/luat-log.lmt b/tex/context/base/mkiv/luat-log.lmt
deleted file mode 100644
index 684b2ac8d..000000000
--- a/tex/context/base/mkiv/luat-log.lmt
+++ /dev/null
@@ -1,739 +0,0 @@
-if not modules then modules = { } end modules ['luat-log'] = {
- version = 1.001,
- comment = "companion to trac-log.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- In fact all writes could go through lua and we could write the console and
--- terminal handler in lua then. Ok, maybe it's slower then, so a no-go.
-
--- This used to be combined in trac-log but as we also split between mkiv and lmtx
--- we now have dedicated files. A side effect is a smaller format and a smaller
--- mtxrun.
---
--- We use different targets: "terminal" "logfile", "both" and have no number
--- channel.
-
-local next, type, select, print = next, type, select, print
-local format, gmatch, find = string.format, string.gmatch, string.find
-local concat, insert, remove = table.concat, table.insert, table.remove
-local topattern = string.topattern
-local utfchar = utf.char
-local datetime = os.date
-local openfile = io.open
-
-local write_nl = texio.write_nl
-local write = texio.write
-
-local setmetatableindex = table.setmetatableindex
-local formatters = string.formatters
-local settings_to_hash = utilities.parsers.settings_to_hash
-local sortedkeys = table.sortedkeys
-
--- variant is set now
-
-local variant = "default"
------ variant = "ansi"
-
-logs = logs or { }
-local logs = logs
-
--- we extend the formatters:
-
-formatters.add (
- formatters, "unichr",
- [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
-)
-
-formatters.add (
- formatters, "chruni",
- [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
-)
-
--- basic loggers
-
-local function ignore() end
-
-setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
-
-local report, subreport, status, settarget, setformats, settranslations
-
-local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline
-
--- we use formatters but best check for % then because for simple messages but
--- we don't want this overhead for single messages (not that there are that
--- many; we could have a special weak table)
-
-local function ansisupported(specification)
- if specification ~= "ansi" and specification ~= "ansilog" then
- return false
- elseif os and os.enableansi then
- return os.enableansi()
- else
- return false
- end
-end
-
-do
-
- if arg and ansisupported then
- -- we're don't have environment.arguments yet
- for k, v in next, arg do -- k can be negative !
- if v == "--ansi" or v == "--c:ansi" then
- if ansisupported("ansi") then
- variant = "ansi"
- end
- break
- elseif v == "--ansilog" or v == "--c:ansilog" then
- if ansisupported("ansilog") then
- variant = "ansilog"
- end
- break
- end
- end
- end
-
- local whereto = "both"
- local target = nil
- local targets = nil
-
- local formats = table.setmetatableindex("self")
- local translations = table.setmetatableindex("self")
-
- local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes
- local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop
-
- local variants = {
- default = {
- formats = {
- report_yes = formatters["%-15s > %s\n"],
- report_nop = formatters["%-15s >\n"],
- direct_yes = formatters["%-15s > %s"],
- direct_nop = formatters["%-15s >"],
- subreport_yes = formatters["%-15s > %s > %s\n"],
- subreport_nop = formatters["%-15s > %s >\n"],
- subdirect_yes = formatters["%-15s > %s > %s"],
- subdirect_nop = formatters["%-15s > %s >"],
- status_yes = formatters["%-15s : %s\n"],
- status_nop = formatters["%-15s :\n"],
- },
- targets = setmetatableindex( {
- logfile = "logfile",
- log = "logfile",
- file = "logfile",
- console = "terminal",
- terminal = "terminal",
- both = "terminal_and_logfile",
- }, function(t,k) t[k] = "terminal_and_logfile" end),
- },
- ansi = {
- formats = {
- report_yes = formatters["%-15s > %s\n"],
- report_nop = formatters["%-15s >\n"],
- direct_yes = formatters["%-15s > %s"],
- direct_nop = formatters["%-15s >"],
- subreport_yes = formatters["%-15s > %s > %s\n"],
- subreport_nop = formatters["%-15s > %s >\n"],
- subdirect_yes = formatters["%-15s > %s > %s"],
- subdirect_nop = formatters["%-15s > %s >"],
- status_yes = formatters["%-15s : %s\n"],
- status_nop = formatters["%-15s :\n"],
- },
- targets = setmetatableindex( {
- logfile = false,
- log = false,
- file = false,
- console = "terminal",
- terminal = "terminal",
- both = "terminal",
- }, function(t,k) t[k] = "terminal" end),
- }
- }
-
- variants.ansilog = {
- formats = variants.ansi.formats,
- targets = variants.default.targets,
- }
-
- logs.flush = io.flush
-
- writer = function(...)
- if target then
- write_nl(target,...)
- end
- end
-
- newline = function()
- if target then
- write_nl(target,"\n")
- end
- end
-
- report = function(a,b,c,...)
- if not target then
- -- ignore
- elseif c ~= nil then
- write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
- elseif b then
- write_nl(target,report_yes(translations[a],formats[b]))
- elseif a then
- write_nl(target,report_nop(translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- direct = function(a,b,c,...)
- if not target then
- return ""
- elseif c ~= nil then
- return direct_yes(translations[a],formatters[formats[b]](c,...))
- elseif b then
- return direct_yes(translations[a],formats[b])
- elseif a then
- return direct_nop(translations[a])
- else
- return ""
- end
- end
-
- subreport = function(a,s,b,c,...)
- if not target then
- -- ignore
- elseif c ~= nil then
- write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
- elseif b then
- write_nl(target,subreport_yes(translations[a],translations[s],formats[b]))
- elseif a then
- write_nl(target,subreport_nop(translations[a],translations[s]))
- else
- write_nl(target,"\n")
- end
- end
-
- subdirect = function(a,s,b,c,...)
- if not target then
- return ""
- elseif c ~= nil then
- return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
- elseif b then
- return subdirect_yes(translations[a],translations[s],formats[b])
- elseif a then
- return subdirect_nop(translations[a],translations[s])
- else
- return ""
- end
- end
-
- status = function(a,b,c,...)
- if not target then
- -- ignore
- elseif c ~= nil then
- write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
- elseif b then
- write_nl(target,status_yes(translations[a],formats[b]))
- elseif a then
- write_nl(target,status_nop(translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- settarget = function(askedwhereto)
- whereto = askedwhereto or whereto or "both"
- target = targets[whereto]
- if not target then
- whereto = "both"
- target = targets[whereto]
- end
- if target == "terminal" or target == "terminal_and_logfile" then
- logs.flush = io.flush
- else
- logs.flush = ignore
- end
- end
-
- local stack = { }
-
- pushtarget = function(newtarget)
- insert(stack,target)
- settarget(newtarget)
- end
-
- poptarget = function()
- if #stack > 0 then
- settarget(remove(stack))
- end
- end
-
- setformats = function(f)
- formats = f
- end
-
- settranslations = function(t)
- translations = t
- end
-
- setprocessor = function(f)
- local writeline = write_nl
- write_nl = function(target,...)
- if target then
- writeline(target,f(...))
- end
- end
- end
-
- setformatters = function(specification)
- local t = nil
- local f = nil
- local d = variants.default
- if not specification then
- --
- elseif type(specification) == "table" then
- t = specification.targets
- f = specification.formats or specification
- else
- if not ansisupported(specification) then
- specification = "default"
- end
- local v = variants[specification]
- if v then
- t = v.targets
- f = v.formats
- variant = specification
- end
- end
- targets = t or d.targets
- target = targets[whereto]
- if f then
- d = d.formats
- else
- f = d.formats
- d = f
- end
- setmetatableindex(f,d)
- report_yes = f.report_yes
- report_nop = f.report_nop
- subreport_yes = f.subreport_yes
- subreport_nop = f.subreport_nop
- direct_yes = f.direct_yes
- direct_nop = f.direct_nop
- subdirect_yes = f.subdirect_yes
- subdirect_nop = f.subdirect_nop
- status_yes = f.status_yes
- status_nop = f.status_nop
- settarget(whereto)
- end
-
- setformatters(variant)
-
- setlogfile = ignore
- settimedlog = ignore
-
-end
-
-logs.report = report
-logs.subreport = subreport
-logs.status = status
-logs.settarget = settarget
-logs.pushtarget = pushtarget
-logs.poptarget = poptarget
-logs.setformats = setformats
-logs.settranslations = settranslations
-
-logs.setlogfile = setlogfile
-logs.settimedlog = settimedlog
-logs.setprocessor = setprocessor
-logs.setformatters = setformatters
-
-logs.direct = direct
-logs.subdirect = subdirect
-logs.writer = writer
-logs.newline = newline
-
-local data = { }
-local states = nil
-local force = false
-
-function logs.reporter(category,subcategory)
- local logger = data[category]
- if not logger then
- local state = states == true
- if not state and type(states) == "table" then
- for c, _ in next, states do
- if find(category,c) then
- state = true
- break
- end
- end
- end
- logger = {
- reporters = { },
- state = state,
- }
- data[category] = logger
- end
- local reporter = logger.reporters[subcategory or "default"]
- if not reporter then
- if subcategory then
- reporter = function(...)
- if force or not logger.state then
- subreport(category,subcategory,...)
- end
- end
- logger.reporters[subcategory] = reporter
- else
- local tag = category
- reporter = function(...)
- if force or not logger.state then
- report(category,...)
- end
- end
- logger.reporters.default = reporter
- end
- end
- return reporter
-end
-
-logs.new = logs.reporter -- for old times sake
-
--- context specicific: this ends up in the macro stream
-
-local ctxreport = logs.writer
-
-function logs.setmessenger(m)
- ctxreport = m
-end
-
-function logs.messenger(category,subcategory)
- -- we need to avoid catcode mess (todo: fast context)
- if subcategory then
- return function(...)
- ctxreport(subdirect(category,subcategory,...))
- end
- else
- return function(...)
- ctxreport(direct(category,...))
- end
- end
-end
-
--- so far
-
-local function setblocked(category,value) -- v.state == value == true : disable
- if category == true or category == "all" then
- -- lock all
- category, value = "*", true
- elseif category == false then
- -- unlock all
- category, value = "*", false
- elseif value == nil then
- -- lock selective
- value = true
- end
- if category == "*" then
- states = value
- for k, v in next, data do
- v.state = value
- end
- else
- alllocked = false
- states = settings_to_hash(category,type(states)=="table" and states or nil)
- for c in next, states do
- local v = data[c]
- if v then
- v.state = value
- else
- c = topattern(c,true,true)
- for k, v in next, data do
- if find(k,c) then
- v.state = value
- end
- end
- end
- end
- end
-end
-
-function logs.disable(category,value)
- setblocked(category,value == nil and true or value)
-end
-
-function logs.enable(category)
- setblocked(category,false)
-end
-
-function logs.categories()
- return sortedkeys(data)
-end
-
-function logs.show()
- local n, c, s, max = 0, 0, 0, 0
- for category, v in table.sortedpairs(data) do
- n = n + 1
- local state = v.state
- local reporters = v.reporters
- local nc = #category
- if nc > c then
- c = nc
- end
- for subcategory, _ in next, reporters do
- local ns = #subcategory
- if ns > c then
- s = ns
- end
- local m = nc + ns
- if m > max then
- max = m
- end
- end
- local subcategories = concat(sortedkeys(reporters),", ")
- if state == true then
- state = "disabled"
- elseif state == false then
- state = "enabled"
- else
- state = "unknown"
- end
- -- no new here
- report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
- end
- report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
-end
-
-local delayed_reporters = { }
-
-setmetatableindex(delayed_reporters,function(t,k)
- local v = logs.reporter(k.name)
- t[k] = v
- return v
-end)
-
-function utilities.setters.report(setter,...)
- delayed_reporters[setter](...)
-end
-
-directives.register("logs.blocked", function(v)
- setblocked(v,true)
-end)
-
-directives.register("logs.target", function(v)
- settarget(v)
-end)
-
-do
-
- local report = logs.reporter("pages") -- not needed but saves checking when we grep for it
- local texgetcount = tex and tex.getcount
-
- local real, user, sub = 0, 0, 0
-
- function logs.start_page_number()
- real = texgetcount("realpageno")
- user = texgetcount("userpageno")
- sub = texgetcount("subpageno")
- end
-
- local timing = false
- local usage = false
- local lasttime = nil
-
- logs.private = {
- enablepagetiming = function()
- usage = true
- end,
- getpagetiming = function()
- return type(usage) == "table" and usage
- end,
- }
-
- trackers.register("pages.timing", function() timing = "" end)
-
- function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
- if timing or usage then
- local elapsed = statistics.currenttime(statistics)
- local average, page
- if not lasttime or real < 2 then
- average = elapsed
- page = elapsed
- else
- average = elapsed / (real - 1)
- page = elapsed - lasttime
- end
- lasttime = elapsed
- if timing then
- timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average)
- end
- if usage then
- usage = {
- page = {
- real = real,
- user = user,
- sub = sub,
- },
- time = {
- elapsed = elapsed,
- page = page,
- average = average,
- }
- }
- end
- end
- if real <= 0 then
- report("flushing page%s",timing)
- elseif user <= 0 then
- report("flushing realpage %s%s",real,timing)
- elseif sub <= 0 then
- report("flushing realpage %s, userpage %s%s",real,user,timing)
- else
- report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing)
- end
- logs.flush()
- end
-
-end
-
--- we don't have show_open and show_close callbacks yet
-
-do
- local texerror = tex and tex.error or print
- local formatters = string.formatters
-
- function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here
- texerror(first and formatters[fmt](first,...) or fmt)
- end
-
-end
-
--- this is somewhat slower but prevents out-of-order messages when print is mixed
--- with texio.write
-
--- io.stdout:setvbuf('no')
--- io.stderr:setvbuf('no')
-
--- windows: > nul 2>&1
--- unix : > null 2>&1
-
-if package.helpers.report then
- package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun
-end
-
-do
-
- local finalactions = { }
- local fatalerrors = { }
- local possiblefatal = { }
- local loggingerrors = false
-
- function logs.loggingerrors()
- return loggingerrors
- end
-
- directives.register("logs.errors",function(v)
- loggingerrors = v
- if type(v) == "string" then
- fatalerrors = settings_to_hash(v)
- else
- fatalerrors = { }
- end
- end)
-
- function logs.registerfinalactions(...)
- insert(finalactions,...) -- so we can force an order if needed
- end
-
- local what = nil
- local report = nil
- local state = nil
- local target = nil
-
- local function startlogging(t,r,w,s)
- target = t
- state = force
- force = true
- report = type(r) == "function" and r or logs.reporter(r)
- what = w
- pushtarget(target)
- newline()
- if s then
- report("start %s: %s",what,s)
- else
- report("start %s",what)
- end
- if target == "logfile" then
- newline()
- end
- return report
- end
-
- local function stoplogging()
- if target == "logfile" then
- newline()
- end
- report("stop %s",what)
- if target == "logfile" then
- newline()
- end
- poptarget()
- state = oldstate
- end
-
- function logs.startfilelogging(...)
- return startlogging("logfile", ...)
- end
-
- logs.stopfilelogging = stoplogging
-
- local done = false
-
- function logs.starterrorlogging(r,w,...)
- if not done then
- pushtarget("terminal")
- newline()
- logs.report("error logging","start possible issues")
- poptarget()
- done = true
- end
- if fatalerrors[w] then
- possiblefatal[w] = true
- end
- return startlogging("terminal",r,w,...)
- end
-
- logs.stoperrorlogging = stoplogging
-
- function logs.finalactions()
- if #finalactions > 0 then
- for i=1,#finalactions do
- finalactions[i]()
- end
- if done then
- pushtarget("terminal")
- newline()
- logs.report("error logging","stop possible issues")
- poptarget()
- end
- return next(possiblefatal) and sortedkeys(possiblefatal) or false
- end
- end
-
-end
-
--- just in case we load from context
-
-local dummy = function() end
-
-function logs.application(t)
- return {
- name = t.name or tex.jobname,
- banner = t.banner,
- report = logs.reporter(t.name),
- moreinfo = dummy,
- export = dummy,
- help = dummy,
- identify = dummy,
- version = dummy,
- }
-end