1if not modules then modules = { } end modules ['node-pro'] = {
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
9local trace_callbacks = false trackers .register("nodes.callbacks", function(v) trace_callbacks = v end)
10local force_processors = false directives.register("nodes.processors.force", function(v) force_processors = v end)
11
12local report_nodes = logs.reporter("nodes","processors")
13
14local nodes = nodes
15local tasks = nodes.tasks
16local nuts = nodes.nuts
17local tonut = nodes.tonut
18
19nodes.processors = nodes.processors or { }
20local processors = nodes.processors
21
22
23
24
25local actions = tasks.actions("processors")
26
27do
28
29 local isglyph = nuts.isglyph
30 local getnext = nuts.getnext
31
32 local utfchar = utf.char
33 local concat = table.concat
34
35 local n = 0
36
37 local function reconstruct(head)
38 local t, n, h = { }, 0, head
39 while h do
40 n = n + 1
41 local char, id = isglyph(h)
42 if char then
43 t[n] = utfchar(char)
44 else
45 t[n] = "[]"
46 end
47 h = getnext(h)
48 end
49 return concat(t)
50 end
51
52 function processors.tracer(what,head,groupcode,before,after,show)
53 if not groupcode then
54 groupcode = "unknown"
55 elseif groupcode == "" then
56 groupcode = "mvl"
57 end
58 n = n + 1
59 if show then
60 report_nodes("%s: location %a, group %a, # before %a, # after %s, stream: %s",what,n,groupcode,before,after,reconstruct(head))
61 else
62 report_nodes("%s: location %a, group %a, # before %a, # after %s",what,n,groupcode,before,after)
63 end
64 end
65
66end
67
68do
69
70 local hasglyph = nodes.hasglyph
71 local count_nodes = nodes.countall
72
73 local texget = tex.get
74
75 local tracer = processors.tracer
76
77 local function pre_linebreak_filter(head,groupcode)
78 local found = force_processors or hasglyph(head)
79 if found then
80 if trace_callbacks then
81 local before = count_nodes(head,true)
82 head = actions(head,groupcode)
83 local after = count_nodes(head,true)
84 tracer("pre_linebreak",head,groupcode,before,after,true)
85 else
86 head = actions(head,groupcode)
87 end
88 elseif trace_callbacks then
89 local n = count_nodes(head,false)
90 tracer("pre_linebreak",head,groupcode,n,n)
91 end
92 return head
93 end
94
95 local function hpack_filter(head,groupcode,size,packtype,direction,attributes)
96 local found = force_processors or hasglyph(head)
97 if found then
98
99
100
101 if not direction then
102 direction = texget("textdir")
103 end
104
105 if trace_callbacks then
106 local before = count_nodes(head,true)
107 head = actions(head,groupcode,size,packtype,direction,attributes)
108 local after = count_nodes(head,true)
109 tracer("hpack",head,groupcode,before,after,true)
110 else
111 head = actions(head,groupcode,size,packtype,direction,attributes)
112 end
113 elseif trace_callbacks then
114 local n = count_nodes(head,false)
115 tracer("hpack",head,groupcode,n,n)
116 end
117 return head
118 end
119
120 processors.pre_linebreak_filter = pre_linebreak_filter
121 processors.hpack_filter = hpack_filter
122
123 do
124
125 local hpack = nodes.hpack
126
127 function nodes.fullhpack(head,...)
128 return hpack((hpack_filter(head)),...)
129 end
130
131 end
132
133 do
134
135 local hpack = nuts.hpack
136
137 function nuts.fullhpack(head,...)
138 return hpack(tonut(hpack_filter(tonode(head))),...)
139 end
140
141 end
142
143 callbacks.register('pre_linebreak_filter', pre_linebreak_filter, "horizontal manipulations (before par break)")
144 callbacks.register('hpack_filter' , hpack_filter, "horizontal manipulations (before hbox creation)")
145
146end
147
148do
149
150
151
152 local actions = tasks.actions("finalizers")
153 local count_nodes = nodes.countall
154
155 local tracer = processors.tracer
156
157 local function post_linebreak_filter(head,groupcode)
158 if trace_callbacks then
159 local before = count_nodes(head,true)
160 head = actions(head,groupcode)
161 local after = count_nodes(head,true)
162 tracer("post_linebreak",head,groupcode,before,after,true)
163 else
164 head = actions(head,groupcode)
165 end
166 return head
167 end
168
169 processors.post_linebreak_filter = post_linebreak_filter
170
171 callbacks.register("post_linebreak_filter", post_linebreak_filter,"horizontal manipulations (after par break)")
172
173end
174
175do
176
177
178 local getnest = tex.getnest
179
180 local getlist = nuts.getlist
181 local setlist = nuts.setlist
182 local getsubtype = nuts.getsubtype
183
184 local linelist_code = nodes.listcodes.line
185
186 local actions = tasks.actions("contributers")
187
188 function processors.contribute_filter(groupcode)
189 if groupcode == "box" then
190 local whatever = getnest()
191 if whatever then
192 local line = whatever.tail
193 if line then
194 line = tonut(line)
195 if getsubtype(line) == linelist_code then
196 local head = getlist(line)
197 if head then
198 local result = actions(head,groupcode,line)
199 if result and result ~= head then
200 setlist(line,result)
201 end
202 end
203 end
204 end
205 end
206 end
207 end
208
209 callbacks.register("contribute_filter", processors.contribute_filter,"things done with lines")
210
211end
212
213statistics.register("h-node processing time", function()
214 return statistics.elapsedseconds(nodes,"including kernel")
215end)
216 |