1if not modules then modules = { } end modules ['trac-log'] = {
2 version = 1.001,
3 comment = "companion to trac-log.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
12
13
14
15
16
17local next, type, select, print = next, type, select, print
18local format, gmatch, find = string.format, string.gmatch, string.find
19local concat, insert, remove = table.concat, table.insert, table.remove
20local topattern = string.topattern
21local utfchar = utf.char
22local datetime = os.date
23local openfile = io.open
24
25local write_nl = print
26local write = io.write
27
28local setmetatableindex = table.setmetatableindex
29local formatters = string.formatters
30local settings_to_hash = utilities.parsers.settings_to_hash
31local sortedkeys = table.sortedkeys
32
33local variant = "default"
34
35
36logs = logs or { }
37local logs = logs
38
39local moreinfo = [[
40More information about ConTeXt and the tools that come with it can be found at:
41]] .. "\n" .. [[
42maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
43webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
44wiki : http://contextgarden.net
45]]
46
47formatters.add (
48 formatters, "unichr",
49 [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
50)
51
52formatters.add (
53 formatters, "chruni",
54 [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
55)
56
57
58
59local function ignore() end
60
61setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
62
63local report, subreport, status, settarget, setformats, settranslations
64
65local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline
66
67
68
69
70
71local function ansisupported(specification)
72 if specification ~= "ansi" and specification ~= "ansilog" then
73 return false
74 elseif os and os.enableansi then
75 return os.enableansi()
76 else
77 return false
78 end
79end
80
81do
82
83 local report_yes, subreport_yes, status_yes
84 local report_nop, subreport_nop, status_nop
85
86 local variants = {
87 default = {
88 formats = {
89 report_yes = formatters["%-15s | %s"],
90 report_nop = formatters["%-15s |"],
91 subreport_yes = formatters["%-15s | %s | %s"],
92 subreport_nop = formatters["%-15s | %s |"],
93 status_yes = formatters["%-15s : %s\n"],
94 status_nop = formatters["%-15s :\n"],
95 },
96 },
97 ansi = {
98 formats = {
99 report_yes = formatters["[0;32m%-15s [0;1m|[0m %s"],
100 report_nop = formatters["[0;32m%-15s [0;1m|[0m"],
101 subreport_yes = formatters["[0;32m%-15s [0;1m|[0;31m %s [0;1m|[0m %s"],
102 subreport_nop = formatters["[0;32m%-15s [0;1m|[0;31m %s [0;1m|[0m"],
103 status_yes = formatters["[0;32m%-15s [0;1m:[0m %s\n"],
104 status_nop = formatters["[0;32m%-15s [0;1m:[0m\n"],
105 },
106 },
107 }
108
109 logs.flush = ignore
110
111 writer = function(s)
112 write_nl(s)
113 end
114
115 newline = function()
116 write_nl("\n")
117 end
118
119 report = function(a,b,c,...)
120 if c then
121 write_nl(report_yes(a,formatters[b](c,...)))
122 elseif b then
123 write_nl(report_yes(a,b))
124 elseif a then
125 write_nl(report_nop(a))
126 else
127 write_nl("")
128 end
129 end
130
131 subreport = function(a,sub,b,c,...)
132 if c then
133 write_nl(subreport_yes(a,sub,formatters[b](c,...)))
134 elseif b then
135 write_nl(subreport_yes(a,sub,b))
136 elseif a then
137 write_nl(subreport_nop(a,sub))
138 else
139 write_nl("")
140 end
141 end
142
143 status = function(a,b,c,...)
144 if c then
145 write_nl(status_yes(a,formatters[b](c,...)))
146 elseif b then
147 write_nl(status_yes(a,b))
148 elseif a then
149 write_nl(status_nop(a))
150 else
151 write_nl("\n")
152 end
153 end
154
155 direct = ignore
156 subdirect = ignore
157
158 settarget = ignore
159 pushtarget = ignore
160 poptarget = ignore
161 setformats = ignore
162 settranslations = ignore
163
164 setprocessor = function(f)
165 local writeline = write_nl
166 write_nl = function(s)
167 writeline(f(s))
168 end
169 end
170
171 setformatters = function(specification)
172 local f = nil
173 local d = variants.default
174 if specification then
175 if type(specification) == "table" then
176 f = specification.formats or specification
177 else
178 if not ansisupported(specification) then
179 specification = "default"
180 end
181 local v = variants[specification]
182 if v then
183 f = v.formats
184 end
185 end
186 end
187 if f then
188 d = d.formats
189 else
190 f = d.formats
191 d = f
192 end
193 setmetatableindex(f,d)
194 report_yes = f.report_yes
195 report_nop = f.report_nop
196 subreport_yes = f.subreport_yes
197 subreport_nop = f.subreport_nop
198 status_yes = f.status_yes
199 status_nop = f.status_nop
200 end
201
202 setformatters(variant)
203
204 setlogfile = function(name,keepopen)
205 if name and name ~= "" then
206 local localtime = os.localtime
207 local writeline = write_nl
208 if keepopen then
209 local f = io.open(name,"ab")
210 write_nl = function(s)
211 writeline(s)
212 f:write(localtime()," | ",s,"\n")
213 end
214 else
215 write_nl = function(s)
216 writeline(s)
217 local f = io.open(name,"ab")
218 f:write(localtime()," | ",s,"\n")
219 f:close()
220 end
221 end
222 end
223 setlogfile = ignore
224 end
225
226 settimedlog = function()
227 local localtime = os.localtime
228 local writeline = write_nl
229 write_nl = function(s)
230 writeline(localtime() .. " | " .. s)
231 end
232 settimedlog = ignore
233 end
234
235end
236
237logs.report = report
238logs.subreport = subreport
239logs.status = status
240logs.settarget = settarget
241logs.pushtarget = pushtarget
242logs.poptarget = poptarget
243logs.setformats = setformats
244logs.settranslations = settranslations
245
246logs.setlogfile = setlogfile
247logs.settimedlog = settimedlog
248logs.setprocessor = setprocessor
249logs.setformatters = setformatters
250
251logs.direct = direct
252logs.subdirect = subdirect
253logs.writer = writer
254logs.newline = newline
255
256
257
258
259
260local data = { }
261local states = nil
262local force = false
263
264function logs.reporter(category,subcategory)
265 local logger = data[category]
266 if not logger then
267 local state = states == true
268 if not state and type(states) == "table" then
269 for c, _ in next, states do
270 if find(category,c) then
271 state = true
272 break
273 end
274 end
275 end
276 logger = {
277 reporters = { },
278 state = state,
279 }
280 data[category] = logger
281 end
282 local reporter = logger.reporters[subcategory or "default"]
283 if not reporter then
284 if subcategory then
285 reporter = function(...)
286 if force or not logger.state then
287 subreport(category,subcategory,...)
288 end
289 end
290 logger.reporters[subcategory] = reporter
291 else
292 local tag = category
293 reporter = function(...)
294 if force or not logger.state then
295 report(category,...)
296 end
297 end
298 logger.reporters.default = reporter
299 end
300 end
301 return reporter
302end
303
304logs.new = logs.reporter
305
306
307
308local ctxreport = logs.writer
309
310function logs.setmessenger(m)
311 ctxreport = m
312end
313
314function logs.messenger(category,subcategory)
315
316 if subcategory then
317 return function(...)
318 ctxreport(subdirect(category,subcategory,...))
319 end
320 else
321 return function(...)
322 ctxreport(direct(category,...))
323 end
324 end
325end
326
327
328
329local function setblocked(category,value)
330 if category == true or category == "all" then
331
332 category, value = "*", true
333 elseif category == false then
334
335 category, value = "*", false
336 elseif value == nil then
337
338 value = true
339 end
340 if category == "*" then
341 states = value
342 for k, v in next, data do
343 v.state = value
344 end
345 else
346 alllocked = false
347 states = settings_to_hash(category,type(states)=="table" and states or nil)
348 for c in next, states do
349 local v = data[c]
350 if v then
351 v.state = value
352 else
353 c = topattern(c,true,true)
354 for k, v in next, data do
355 if find(k,c) then
356 v.state = value
357 end
358 end
359 end
360 end
361 end
362end
363
364function logs.disable(category,value)
365 setblocked(category,value == nil and true or value)
366end
367
368function logs.enable(category)
369 setblocked(category,false)
370end
371
372function logs.categories()
373 return sortedkeys(data)
374end
375
376function logs.show()
377 local n, c, s, max = 0, 0, 0, 0
378 for category, v in table.sortedpairs(data) do
379 n = n + 1
380 local state = v.state
381 local reporters = v.reporters
382 local nc = #category
383 if nc > c then
384 c = nc
385 end
386 for subcategory, _ in next, reporters do
387 local ns = #subcategory
388 if ns > c then
389 s = ns
390 end
391 local m = nc + ns
392 if m > max then
393 max = m
394 end
395 end
396 local subcategories = concat(sortedkeys(reporters),", ")
397 if state == true then
398 state = "disabled"
399 elseif state == false then
400 state = "enabled"
401 else
402 state = "unknown"
403 end
404
405 report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
406 end
407 report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
408end
409
410local delayed_reporters = { }
411
412setmetatableindex(delayed_reporters,function(t,k)
413 local v = logs.reporter(k.name)
414 t[k] = v
415 return v
416end)
417
418function utilities.setters.report(setter,...)
419 delayed_reporters[setter](...)
420end
421
422directives.register("logs.blocked", function(v)
423 setblocked(v,true)
424end)
425
426directives.register("logs.target", function(v)
427 settarget(v)
428end)
429
430
431
432
433local nesting = 0
434local verbose = false
435local hasscheme = url.hasscheme
436
437
438
439local simple = logs.reporter("comment")
440
441logs.simple = simple
442logs.simpleline = simple
443
444
445
446logs.setprogram = ignore
447logs.extendbanner = ignore
448logs.reportlines = ignore
449logs.reportbanner = ignore
450logs.reportline = ignore
451logs.simplelines = ignore
452logs.help = ignore
453
454
455
456local Carg, C, lpegmatch = lpeg.Carg, lpeg.C, lpeg.match
457local p_newline = lpeg.patterns.newline
458
459local linewise = (
460 Carg(1) * C((1-p_newline)^1) / function(t,s) t.report(s) end
461 + Carg(1) * p_newline^2 / function(t) t.report() end
462 + p_newline
463)^1
464
465local function reportlines(t,str)
466 if str then
467 lpegmatch(linewise,str,1,t)
468 end
469end
470
471local function reportbanner(t)
472 local banner = t.banner
473 if banner then
474 t.report(banner)
475 t.report()
476 end
477end
478
479local function reportversion(t)
480 local banner = t.banner
481 if banner then
482 t.report(banner)
483 end
484end
485
486local function reporthelp(t,...)
487 local helpinfo = t.helpinfo
488 if type(helpinfo) == "string" then
489 reportlines(t,helpinfo)
490 elseif type(helpinfo) == "table" then
491 for i=1,select("#",...) do
492 reportlines(t,t.helpinfo[select(i,...)])
493 if i < n then
494 t.report()
495 end
496 end
497 end
498end
499
500local function reportinfo(t)
501 t.report()
502 reportlines(t,t.moreinfo)
503end
504
505local function reportexport(t,method)
506 report(t.helpinfo)
507end
508
509local reporters = {
510 lines = reportlines,
511 banner = reportbanner,
512 version = reportversion,
513 help = reporthelp,
514 info = reportinfo,
515 export = reportexport,
516}
517
518local exporters = {
519
520}
521
522logs.reporters = reporters
523logs.exporters = exporters
524
525function logs.application(t)
526
527 local arguments = environment and environment.arguments
528 if arguments then
529 local ansi = arguments.ansi or arguments.ansilog
530 if ansi then
531 logs.setformatters(arguments.ansi and "ansi" or "ansilog")
532 end
533 end
534
535 t.name = t.name or "unknown"
536 t.banner = t.banner
537 t.moreinfo = moreinfo
538 t.report = logs.reporter(t.name)
539 t.help = function(...)
540 reporters.banner(t)
541 reporters.help(t,...)
542 reporters.info(t)
543 end
544 t.export = function(...)
545 reporters.export(t,...)
546 end
547 t.identify = function()
548 reporters.banner(t)
549 end
550 t.version = function()
551 reporters.version(t)
552 end
553 return t
554end
555
556
557
558
559
560
561
562
563
564
565
566local f_syslog = formatters["%s %s => %s => %s => %s\r"]
567
568function logs.system(whereto,process,jobname,category,fmt,arg,...)
569 local message = f_syslog(datetime("%d/%m/%y %H:%m:%S"),process,jobname,category,arg == nil and fmt or format(fmt,arg,...))
570 for i=1,10 do
571 local f = openfile(whereto,"a")
572 if f then
573 f:write(message)
574 f:close()
575 break
576 else
577 sleep(0.1)
578 end
579 end
580end
581
582local report_system = logs.reporter("system","logs")
583
584if utilities then
585 utilities.report = report_system
586end
587
588
589
590
591
592
593
594
595
596
597if package.helpers.report then
598 package.helpers.report = logs.reporter("package loader")
599end
600 |