TeX's hpack routine packages an hlist into a box. While doing that it looks at a global pointer adjust_tail and if that is not "null" it migrates some nodes to a separate list starting at adjust_head. This way material from \mark, \insert or \vadjust migrates out from the line into the enclosing vertical list during the paragraph building. Otherwise they stay inside the box.

From the luatex manual I was unable to see how this effect could be achieved using node.hpack. Luatex knows tex.lists.adjust_head and tex.lists.pre_adjust_head(whatever that is?) but I couldn't quite see if they correspond to TeX's adjust_head and adjust_tailor how to indicate that node.hpackshould do the migrating.

If it can at all (the manual has some notes on node.hpack having weird side-effects on \insert and such in some cases).

Reason I'm interested in that is to write my own paragraph builder or adapting Taco's code (that doesn't seem to work in that respect (see question Replacement(s) for TeX's paragraph builder using LuaTeX) and has a few other bugs so that it currently doesn't quite work.

Of course, if worst comes to worst, I guess I could migrate those nodes out manually prior to calling node.hpack but if possible I would use the internal and have it done for me as that is most certainly faster.


LuaTeX's adjust_head corresponds to TeX's adjust_head and setting it automatically sets adjust_tail to the end of the adjust_head list, even if it is empty(nil). So if you have a hlist and want to apply node.hpack while letting things migrate out, you first set adjust_head (and therefore also adjust_tail to an empty list:

tex.lists.adjust_head = nil
tex.lists.pre_adjust_head = nil

Then node.hpack deletes all migrateable nodes from the list and moves them into the nodelist tex.lists.adjust_head. From there you can handle them as you wish.

Here pre_adjust_head works just like adjust_head: It is used to implement the pdfTeX extension \vadjust pre{stuff} which inserts stuff before instead of after the line where \vadjust appears.

So to emulate normal TeX behavior, first the pre_adjust_head list has to be inserted into the outer vlist, than the result from hpackand finally adjust_head.

To clean up at the end of your code you might want to reset tex.lists.adjust_head and tex.lists.pre_adjust_head. Setting them to nil would just create an empty list and this would stop TeX from keeping any migrateable material in a hbox. Sadly I do not think there is a way to manually set the interal TeX values to null, so we need a trick: tex.linebreak works with this lists and resets them at the end, so you just have to call tex.linebreak. We do not actually want to break a line so we can pass an empty hlist node to avoid too much work while still triggering the side effect of cleaning up the adjust_ lists:

  • The trick you mention at the end seems to indicate that LuaTeX is missing some more decent interface in that space, doesn't it? – Frank Mittelbach Jun 14 '18 at 7:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.