summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/hybrid/hybrid-callbacks.tex
blob: 00b3c0f3f60ff39024bc3bad23a5455b05a51bf3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
% language=uk

\startcomponent hybrid-callbacks

\environment hybrid-environment

\startchapter[title={Callbacks}]

\startsection [title={Introduction}]

Callbacks are the means to extend the basic \TEX\ engine's functionality in
\LUATEX\ and \CONTEXT\ \MKIV\ uses them extensively. Although the interface is
still in development we see users popping in their own functionality and although
there is nothing wrong with that, it can open a can of worms.

It is for this reason that from now on we protect the \MKIV\ callbacks from being
overloaded. For those who still want to add their own code some hooks are
provided. Here we will address some of these issues.

\stopsection

\startsection [title={Actions}]

There are already quite some callbacks and we use most of them. In the following
list the callbacks tagged with \type {enabled} are used and frozen, the ones
tagged \type {disabled} are blocked and never used, while the ones tagged \type
{undefined} are yet unused.

\ctxcommand{showcallbacks()}

You can be rather sure that we will eventually use all callbacks one way or the
other. Also, some callbacks are only set when certain functionality is enabled.

It may sound somewhat harsh but if users kick in their own code, we cannot
guarantee \CONTEXT's behaviour any more and support becomes a pain. If you really
need to use a callback yourself, you should use one of the hooks and make sure
that you return the right values.

The exact working of the callback handler is not something we need to bother
users with so we stick to a simple description. The next list is not definitive
and evolves. For instance we might at some point decide to add more granularity.

We only open up some of the node list related callbacks. All callbacks related to
file handling, font definition and housekeeping are frozen. Most if the
mechanisms that use these callbacks have hooks anyway.

Of course you can overload the built in functionality as this is currently not
protected, but we might do that as well once \MKIV\ is stable enough. After all,
at the time of this writing overloading can be handy when testing.

This leaves the node list manipulators. The are grouped as follows:

\starttabulate[|l|l|p|]
\FL
\NC \bf category \NC \bf callback \NC \bf usage \NC \NR
\TL
\NC \type{processors}   \NC \type{pre_linebreak_filter}  \NC called just before the paragraph is broken into lines \NC \NR
\NC                     \NC \type{hpack_filter}          \NC called just before a horizontal box is constructed \NC \NR
\NC \type{finalizers}   \NC \type{post_linebreak_filter} \NC called just after the paragraph has been broken into lines \NC \NR
\NC \type{shipouts}     \NC \type{no callback yet}       \NC applied to the box (or xform) that is to be shipped out \NC \NR
\NC \type{mvlbuilders}  \NC \type{buildpage_filter}      \NC called after some material has been added to the main vertical list \NC \NR
\NC \type{vboxbuilders} \NC \type{vpack_filter}          \NC called when some material is added to a vertical box \NC \NR
%NC \type{parbuilders}  \NC \type{linebreak_filter}      \NC called when a paragraph is to be broken into lines \NC \NR
%NC \type{pagebuilders} \NC \type{pre_output_filter}     \NC called when a page it fed into the output routing \NC \NR
\NC \type{math}         \NC \type{mlist_to_hlist}        \NC called just after the math list is created, before it is turned into an horizontal list \NC \NR
\BL
\stoptabulate

Each category has several subcategories but for users only two
make sense: \type {before} and \type {after}. Say that you want to
hook some tracing into the \type {mvlbuilder}. This is how it's
done:

\starttyping
function third.mymodule.myfunction(where)
    nodes.show_simple_list(tex.lists.contrib_head)
end

nodes.tasks.appendaction("processors", "before", "third.mymodule.myfunction")
\stoptyping

As you can see, in this case the function gets no \type {head} passed (at least
not currently). This example also assumes that you know how to access the right
items. The arguments and return values are given below. \footnote {This interface
might change a bit in future versions of \CONTEXT. Therefore we will not discuss
the few more optional arguments that are possible.}

\starttabulate[|l|l|p|]
\FL
\NC \bf category \NC \bf arguments \NC \bf return value \NC \NR
\TL
\NC \type{processors}   \NC \type{head, ...} \NC \type{head, done} \NC \NR
\NC \type{finalizers}   \NC \type{head, ...} \NC \type{head, done} \NC \NR
\NC \type{shipouts}     \NC \type{head}      \NC \type{head, done} \NC \NR
\NC \type{mvlbuilders}  \NC                  \NC \type{done}       \NC \NR
\NC \type{vboxbuilders} \NC \type{head, ...} \NC \type{head, done} \NC \NR
%NC \type{parbuilders}  \NC \type{head, ...} \NC \type{head, done} \NC \NR
%NC \type{pagebuilders} \NC \type{head, ...} \NC \type{head, done} \NC \NR
\NC \type{math}         \NC \type{head, ...} \NC \type{head, done} \NC \NR
\LL
\stoptabulate

\stopsection

\startsection [title={Tasks}]

In the previous section we already saw that the actions are in fact tasks and
that we can append (and therefore also prepend) to a list of tasks. The \type
{before} and \type {after} task lists are valid hooks for users contrary to the
other tasks that can make up an action. However, the task builder is generic
enough for users to be used for individual tasks that are plugged into the user
hooks.

Of course at some point, too many nested tasks bring a performance penalty with
them. At the end of a run \MKIV\ reports some statistics and timings and these
can give you an idea how much time is spent in \LUA. Of course this is a rough
estimate only.

The following tables list all the registered tasks for the processors actions:

\ctxlua{nodes.tasks.table("processors")}

Some of these do have subtasks and some of these even more, so you can imagine
that quite some action is going on there.

The finalizer tasks are:

\ctxlua{nodes.tasks.table("finalizers")}

Shipouts concern:

\ctxlua{nodes.tasks.table("shipouts")}

There are not that many mvlbuilder tasks currently:

\ctxlua{nodes.tasks.table("mvlbuilders")}

The vboxbuilder perform similar tasks:

\ctxlua{nodes.tasks.table("vboxbuilders")}

% In the future we expect to have more parbuilder tasks. Here again
% there are subtasks that depend on the current typesetting environment, so
% this is the right spot for language specific treatments.
%
% \ctxlua{nodes.tasks.table("parbuilders")}

% The following actions are applied just before the list is
% passed on the the output routine. The return value is a vlist.
%
% \ctxlua{nodes.tasks.table("pagebuilders")}

Finally, we have tasks related to the math list:

\ctxlua{nodes.tasks.table("math")}

As \MKIV\ is developed in sync with \LUATEX\ and code changes from experimental
to more final and reverse, you should not be too surprised if the registered
function names change.

You can create your own task list with:

\starttyping
nodes.tasks.new("mytasks",{ "one", "two" })
\stoptyping

After that you can register functions. You can append as well as prepend them
either or not at a specific position.

\starttyping
nodes.tasks.appendaction ("mytask","one","bla.alpha")
nodes.tasks.appendaction ("mytask","one","bla.beta")

nodes.tasks.prependaction("mytask","two","bla.gamma")
nodes.tasks.prependaction("mytask","two","bla.delta")

nodes.tasks.appendaction ("mytask","one","bla.whatever","bla.alpha")
\stoptyping

Functions can also be removed:

\starttyping
nodes.tasks.removeaction("mytask","one","bla.whatever")
\stoptyping

As removal is somewhat drastic, it is also possible to enable and disable
functions. From the fact that with these two functions you don't specify a
category (like \type {one} or \type {two}) you can conclude that the function
names need to be unique within the task list or else all with the same name
within this task will be disabled.

\starttyping
nodes.tasks.enableaction ("mytask","bla.whatever")
nodes.tasks.disableaction("mytask","bla.whatever")
\stoptyping

The same can be done with a complete category:

\starttyping
nodes.tasks.enablegroup ("mytask","one")
nodes.tasks.disablegroup("mytask","one")
\stoptyping

There is one function left:

\starttyping
nodes.tasks.actions("mytask",2)
\stoptyping

This function returns a function that when called will perform the tasks. In this
case the function takes two extra arguments in addition to \type {head}.
\footnote {Specifying this number permits for some optimization but is not really
needed}

Tasks themselves are implemented on top of sequences but we won't discuss them
here.

\stopsection

\startsection [title={Paragraph and page builders}]

Building paragraphs and pages is implemented differently and has no user hooks.
There is a mechanism for plugins but the interface is quite experimental.

\stopsection

\stopchapter

\stopcomponent