% language=us \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