# LuaTeX node insert_before in left margin

After playing with the answer the question here, I noticed some differences in insert_after and insert_before. node.insert_after adds contents to right margin, node.insert_before doesn't seem to add to left margin. Seems like they both grow as if the contents were placed starting at left margin. The question is how to grow the contents of the hlist n into the left margin (using luatex node library) instead of pushing the main box in right margin.

A not in left margin:

A in right margin:

In the following code, I have commented 3 different insert recipes. Uncomment them one by one to see the effect. Interestingly Append-2 recipe (insert_before) doesn't produce any result, even though its definition in luatex manual looks like Append-1 recipe (insert_after)


\documentclass{article}
\usepackage{lua-visual-debug}

\directlua{
%
function my_post_lb_filter(h,c)
local cntr=0

for n in node.traverse(h) do
% pull out the boxes and add A
if n.id==0 then
local  newn= node.new(node.id("glyph"))
newn.font=font.current()
newn.char=65 % this is a single character box, for A

% Append-1 works fine, A goes in margin:
% node.insert_after(n.list,node.tail(n.list),newn)

% Append-2 produces no result:

% Append-3 instead of putting A in margin makes text violate right margin

end
%
end
return h
end
}

\begin{document}

Vivamus pharetra posuere sapien. Nam consectetuer.
Sed aliquam, nunc eget euismod ullamcorper, lectus nunc
ullamcorper orci, fermentum bibendum enim nibh eget ipsum.
Donec porttitor ligula eu
dolor. Maecenas
vitae nulla consequat libero cursus venenatis.

\end{document}



Both insert_before and insert_after return the new head node as first return value. Technically, this return value is only relevant if the head node changes. (If the head doesn't change, you do not have to change references to the head node in other nodes. If the head node changes, you do.) Given that the head node is the first node of the token list and insert_after inserts a node after another one, insert_after in most cases does not change the head. (There is one exception: If the list was empty, node.insert_after changes the head) On the other hand, if node.insert_before is used to insert something before the head node, the new node will always become the new head and therefore the head will change. So either you always think carefully when using these functions if you might change the head, or you follow a basic rule:

Never ignore the return value of insert_before/insert_after.

So while your Append-1 seems to work fine, it is good practice to change it to

n.head = node.insert_after(n.list, node.tail(n.list), newn)


This avoids ever dealing the issue you had with Append-2.

\documentclass{article}
\usepackage{lua-visual-debug}

\directlua{
%
function my_post_lb_filter(h,c)
local cntr=0

for n in node.traverse(h) do
% pull out the boxes and add A
if n.id==0 then
local newn= node.new("glyph")
newn.font=font.current()
newn.char=65 % this is a single character box, for A
local newk = node.new("kern")
newk.kern = -newn.width % A kern which "hides" the width of newn

end
%
end
return h
end
}

\begin{document}

Vivamus pharetra posuere sapien. Nam consectetuer.
Sed aliquam, nunc eget euismod ullamcorper, lectus nunc
ullamcorper orci, fermentum bibendum enim nibh eget ipsum.
Donec porttitor ligula eu
dolor. Maecenas
vitae nulla consequat libero cursus venenatis.

\end{document}


• Thanks, this makes things very clear. I wonder when would one need to capture the second return value of insert_before, insert_after? Can these operations really modify the new node that we would have a need to recapture it? From the documentation: <node> head, new = node.insert_after(<node> head, <node> current, <node> new). Also what is the difference between head and current? I see that you specify n.head in place of current, and n.list in place of head. Is it described somewhere in the document? Apr 17, 2020 at 10:31
• @reportaman Using n.head and n.list like this has just been copied from your code, both names are aliases. head is always the head, so e.g. n.head if we are currently inside of n, while current is the node before/after which we insert the new node. So insert_before(n.head, n.head, newn) inserts in the beginning, while insert_before(n.head, m, newn) inserts before m (where m` should already be part of the list) Apr 17, 2020 at 10:43
• @reportaman You never need to capture the second return value, but sometimes you get to situations where having this return value makes code a bit nicer. (E.g. to overwrite the variable you used as second parameter) Apr 17, 2020 at 10:45