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