1if not modules then modules = { } end modules ['node-tsk'] = {
2 version = 1.001,
3 comment = "companion to node-ini.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
13local format = string.format
14
15local trace_tasks = false trackers.register("tasks.creation", function(v) trace_tasks = v end)
16
17local report_tasks = logs.reporter("tasks")
18
19local allocate = utilities.storage.allocate
20
21local context = context
22local nodes = nodes
23
24local tasks = nodes.tasks or { }
25nodes.tasks = tasks
26
27local tasksdata = { }
28
29local sequencers = utilities.sequencers
30local compile = sequencers.compile
31local nodeprocessor = sequencers.nodeprocessor
32
33local newsequencer = sequencers.new
34
35local appendgroup = sequencers.appendgroup
36
37
38local enablegroup = sequencers.enablegroup
39local disablegroup = sequencers.disablegroup
40
41local appendaction = sequencers.appendaction
42local prependaction = sequencers.prependaction
43local replaceaction = sequencers.replaceaction
44local enableaction = sequencers.enableaction
45local disableaction = sequencers.disableaction
46
47local frozengroups = "no"
48
49function tasks.freeze(kind)
50 frozengroups = kind or "tolerant"
51end
52
53function tasks.new(specification)
54 local name = specification.name
55 local sequence = specification.sequence
56 if name and sequence then
57 local tasklist = newsequencer {
58 name = name
59
60 }
61 tasksdata[name] = {
62 name = name,
63 list = tasklist,
64 runner = false,
65 frozen = { },
66 processor = specification.processor or nodeprocessor,
67
68 arguments = specification.arguments or 0,
69 templates = specification.templates,
70 }
71 for l=1,#sequence do
72 appendgroup(tasklist,sequence[l])
73 end
74 end
75end
76
77local function valid(name)
78 local data = tasksdata[name]
79 if not data then
80 report_tasks("unknown task %a",name)
81 else
82 return data
83 end
84end
85
86local function validgroup(name,group,what)
87 local data = tasksdata[name]
88 if not data then
89 report_tasks("unknown task %a",name)
90 else
91 local frozen = data.frozen[group]
92 if frozen then
93 if frozengroup == "no" then
94
95 elseif frozengroup == "strict" then
96 report_tasks("warning: group %a of task %a is frozen, %a applied but not supported",group,name,what)
97 return
98 else
99 report_tasks("warning: group %a of task %a is frozen, %a ignored",group,name,what)
100 end
101 end
102 return data
103 end
104end
105
106function tasks.freezegroup(name,group)
107 local data = valid(name)
108 if data then
109 data.frozen[group] = true
110 end
111end
112
113function tasks.restart(name)
114 local data = valid(name)
115 if data then
116 data.runner = false
117 end
118end
119
120function tasks.enableaction(name,action)
121 local data = valid(name)
122 if data then
123 enableaction(data.list,action)
124 data.runner = false
125 end
126end
127
128function tasks.disableaction(name,action)
129 local data = valid(name)
130 if data then
131 disableaction(data.list,action)
132 data.runner = false
133 end
134end
135
136function tasks.replaceaction(name,group,oldaction,newaction)
137 local data = valid(name)
138 if data then
139 replaceaction(data.list,group,oldaction,newaction)
140 data.runner = false
141 end
142end
143
144do
145
146 local enableaction = tasks.enableaction
147 local disableaction = tasks.disableaction
148
149 function tasks.setaction(name,action,value)
150 if value then
151 enableaction(name,action)
152 else
153 disableaction(name,action)
154 end
155 end
156
157end
158
159function tasks.enablegroup(name,group)
160 local data = validgroup(name,"enable group")
161 if data then
162 enablegroup(data.list,group)
163 data.runner = false
164 end
165end
166
167function tasks.disablegroup(name,group)
168 local data = validgroup(name,"disable group")
169 if data then
170 disablegroup(data.list,group)
171 data.runner = false
172 end
173end
174
175function tasks.appendaction(name,group,action,where,kind,state)
176 local data = validgroup(name,"append action")
177 if data then
178 local list = data.list
179 appendaction(list,group,action,where,kind)
180 if state == "disabled" or (state == "production" and environment.initex) then
181 disableaction(list,action)
182 end
183 data.runner = false
184 end
185end
186
187function tasks.prependaction(name,group,action,where,kind,state)
188 local data = validgroup(name,"prepend action")
189 if data then
190 local list = data.list
191 prependaction(list,group,action,where,kind)
192 if state == "disabled" or (state == "production" and environment.initex) then
193 disableaction(list,action)
194 end
195 data.runner = false
196 end
197end
198
199function tasks.removeaction(name,group,action)
200 local data = validgroup(name,"remove action")
201 if data then
202 removeaction(data.list,group,action)
203 data.runner = false
204 end
205end
206
207function tasks.showactions(name,group,action,where,kind)
208 local data = valid(name)
209 if data then
210 report_tasks("task %a, list:\n%s",name,nodeprocessor(data.list))
211 end
212end
213
214
215
216
217
218
219local created, total = 0, 0
220
221statistics.register("node list callback tasks", function()
222 if total > 0 then
223 return format("%s unique task lists, %s instances (re)created, %s calls",table.count(tasksdata),created,total)
224 else
225 return nil
226 end
227end)
228
229local function create(data,t)
230 created = created + 1
231 local runner = compile(data.list,data.processor,t)
232 if trace_tasks then
233 report_tasks("creating runner %a, %i actions enabled",t.name,data.list.steps or 0)
234 end
235 data.runner = runner
236 return runner
237end
238
239function tasks.actions(name)
240 local data = tasksdata[name]
241 if data then
242 local t = data.templates
243 if t then
244 t.name = data.name
245 return function(...)
246 total = total + 1
247 return (data.runner or create(data,t))(...)
248 end
249 end
250 end
251 return nil
252end
253
254function tasks.table(name)
255 local tsk = tasksdata[name]
256 local lst = tsk and tsk.list
257 local HL, NC, NR, bold, type = context.HL, context.NC, context.NR, context.bold, context.type
258 if lst then
259 local list, order = lst.list, lst.order
260 if list and order then
261 context.starttabulate { "|l|l|" }
262 NC() bold("category") NC() bold("function") NC() NR()
263 for i=1,#order do
264 HL()
265 local o = order[i]
266 local l = list[o]
267 if #l == 0 then
268 NC() type(o) NC() context("unset") NC() NR()
269 else
270 local done = false
271 for k, v in table.sortedhash(l) do
272 NC() if not done then type(o) done = true end NC() type(v) NC() NR()
273 end
274 end
275 end
276 context.stoptabulate()
277 end
278 end
279end
280
281
282
283
284
285
286local templates = {
287
288default = [[
289return function(head)
290 return head
291end
292]],
293
294process = [[
295local tonut = nodes.tonut
296local tonode = nodes.nuts.tonode
297
298%localize%
299
300return function(head)
301 local nuthead = tonut(head)
302
303%actions%
304 return tonode(nuthead)
305end
306]],
307
308step = [[
309 nuthead = tonut((%action%(tonode(nuthead))))
310]],
311
312nut = [[
313 nuthead = %action%(nuthead)
314]],
315
316nohead = [[
317 %action%(tonode(nuthead))
318]],
319
320nonut = [[
321 %action%(nuthead)
322]],
323
324}
325
326tasks.new {
327 name = "shipouts",
328 processor = nodeprocessor,
329 sequence = {
330 "before",
331 "normalizers",
332 "finishers",
333 "after",
334 "wrapup",
335 },
336 templates = templates
337}
338
339tasks.new {
340 name = "everypar",
341 processor = nodeprocessor,
342 sequence = {
343 "before",
344 "normalizers",
345 "after",
346 },
347 templates = templates,
348}
349
350
351
352tasks.new {
353 name = "finalizers",
354 sequence = {
355 "before",
356 "normalizers",
357 "fonts",
358 "lists",
359 "after",
360 },
361 processor = nodeprocessor,
362 templates = {
363
364default = [[
365return function(head)
366 return head
367end
368]],
369
370process = [[
371local tonut = nodes.tonut
372local tonode = nodes.nuts.tonode
373
374%localize%
375
376return function(head,groupcode)
377 local nuthead = tonut(head)
378
379%actions%
380 return tonode(nuthead)
381end
382]],
383
384step = [[
385 nuthead = tonut((%action%(tonode(nuthead),groupcode)))
386]],
387
388nut = [[
389 nuthead = %action%(nuthead,groupcode)
390]],
391
392nohead = [[
393 %action%(tonode(nuthead),groupcode)
394]],
395
396nonut = [[
397 %action%(nuthead,groupcode)
398]],
399
400 }
401}
402
403
404
405tasks.new {
406 name = "processors",
407 processor = nodeprocessor,
408 sequence = {
409 "before",
410 "normalizers",
411 "characters",
412 "words",
413 "fonts",
414 "lists",
415 "after",
416 },
417 templates = {
418
419default = [[
420return function(head)
421 return head
422end
423]],
424
425process = [[
426local tonut = nodes.tonut
427local tonode = nodes.nuts.tonode
428
429%localize%
430
431return function(head,groupcode,size,packtype,direction,attributes)
432 local nuthead = tonut(head)
433
434%actions%
435 return tonode(nuthead)
436end
437]],
438
439step = [[
440 nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,direction,attributes)))
441]],
442
443nut = [[
444 nuthead = %action%(nuthead,groupcode,size,packtype,direction,attributes)
445]],
446
447nohead = [[
448 %action%(tonode(nuthead),groupcode,size,packtype,direction,attributes)
449]],
450
451nonut = [[
452 %action%(nuthead,groupcode,size,packtype,direction,attributes)
453]],
454
455 }
456}
457
458tasks.new {
459 name = "finalizers",
460 processor = nodeprocessor,
461 sequence = {
462 "before",
463 "normalizers",
464 "fonts",
465 "lists",
466 "after",
467 },
468 templates = {
469
470default = [[
471return function(head)
472 return head
473end
474]],
475
476process = [[
477local tonut = nodes.tonut
478local tonode = nodes.nuts.tonode
479
480%localize%
481
482return function(head)
483 local nuthead = tonut(head)
484
485%actions%
486 return tonode(nuthead)
487end
488]],
489
490step = [[
491 nuthead = tonut((%action%(tonode(nuthead))))
492]],
493
494nut = [[
495 nuthead = %action%(nuthead)
496]],
497
498nohead = [[
499 %action%(tonode(nuthead))
500]],
501
502nonut = [[
503 %action%(nuthead)
504]],
505
506 }
507}
508
509tasks.new {
510 name = "mvlbuilders",
511 processor = nodeprocessor,
512 sequence = {
513 "before",
514 "normalizers",
515 "after",
516 },
517 templates = {
518
519default = [[
520return function(head)
521 return head
522end
523]],
524
525process = [[
526local tonut = nodes.tonut
527local tonode = nodes.nuts.tonode
528
529%localize%
530
531return function(head,groupcode)
532 local nuthead = tonut(head)
533
534%actions%
535 return tonode(nuthead)
536end
537]],
538
539step = [[
540 nuthead = tonut((%action%(tonode(nuthead),groupcode)))
541]],
542
543nut = [[
544 nuthead = %action%(nuthead,groupcode)
545]],
546
547nohead = [[
548 %action%(tonode(nuthead),groupcode)
549]],
550
551nonut = [[
552 %action%(nuthead,groupcode)
553]],
554
555 }
556}
557
558tasks.new {
559 name = "vboxbuilders",
560 processor = nodeprocessor,
561 sequence = {
562 "before",
563 "normalizers",
564 "after",
565 },
566 templates = {
567
568default = [[
569return function(head)
570 return head
571end
572]],
573
574process = [[
575local tonut = nodes.tonut
576local tonode = nodes.nuts.tonode
577
578%localize%
579
580return function(head,groupcode,size,packtype,maxdepth,direction)
581 local nuthead = tonut(head)
582
583%actions%
584 return tonode(nuthead)
585end
586]],
587
588step = [[
589 nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction)))
590]],
591
592nut = [[
593 nuthead = %action%(nuthead,groupcode,size,packtype,maxdepth,direction)
594]],
595
596nohead = [[
597 %action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction)
598]],
599
600nonut = [[
601 %action%(nuthead,groupcode,size,packtype,maxdepth,direction)
602]],
603
604 }
605
606}
607
608tasks.new {
609 name = "contributers",
610 processor = nodeprocessor,
611 sequence = {
612 "before",
613 "normalizers",
614 "after",
615 },
616 templates = {
617
618default = [[
619return function(head)
620 return head
621end
622]],
623
624process = [[
625local tonut = nodes.tonut
626local tonode = nodes.nuts.tonode
627
628%localize%
629
630-- we operate exclusively on nuts
631
632return function(nuthead,groupcode,nutline)
633%actions%
634 return nuthead
635end
636]],
637
638step = [[
639 nuthead = tonut((%action%(tonode(nuthead),groupcode,line)))
640]],
641
642nut = [[
643 nuthead = %action%(nuthead,groupcode,nutline)
644]],
645
646nohead = [[
647 %action%(tonode(nuthead),groupcode,line)
648]],
649
650nonut = [[
651 %action%(nuthead,groupcode,nutline)
652]],
653
654 }
655}
656
657
658
659tasks.new {
660 name = "math",
661 processor = nodeprocessor,
662 sequence = {
663 "before",
664 "normalizers",
665 "builders",
666 "finalizers",
667 "after",
668 },
669 templates = {
670
671default = [[
672return function(head)
673 return head
674end
675]],
676
677process = [[
678local tonut = nodes.tonut
679local tonode = nodes.nuts.tonode
680
681%localize%
682
683return function(head,style,penalties)
684 local nuthead = tonut(head)
685
686%actions%
687 return tonode(nuthead)
688end
689]],
690
691step = [[
692 nuthead = tonut((%action%(tonode(nuthead),style,penalties)))
693]],
694
695nut = [[
696 nuthead = %action%(nuthead,style,penalties)
697]],
698
699nohead = [[
700 %action%(tonode(nuthead),style,penalties)
701]],
702
703nonut = [[
704 %action%(nuthead,style,penalties)
705]],
706
707 }
708}
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798 |