This is a LuaTeX node-library/ node-list question.
In the following code, I am trying to typeset a manually crafted nodelist. To add a line break, I add a penalty node, and that works fine (i.e. the line breaks at that point). But when I add a vertical glue/kern after the linebreak, it doesn't really add any vertical space. Where am I going wrong? What nodes are needed to tell the linebreak routine to add vertical space? Am expecting behavior similar to LaTeX's macros \vspace{25pt}
or \\[25pt]
.
Sidenote lua questions: 1) Is the
require
way of loading the lua file ok? I mean, what if I have alocal
variable name clash with another lua file that I load withrequire
, for instance variablelocal head
? 2) Instead of making the functions global, is there a way to call them with something likelinebreak.
prefix to avoid name clash with other lua files that have functions with same name?Update: The "Sidenote" questions above are now discussed as a separate question here, please ignore above "Sidenote lua questions" while reading this question as they are not relevant to it.
Screenshot (I expect additional 25pt or 50pt vertical space after first line):
linebreak.tex:
>>> lualatex linebreak.tex
\documentclass{article}
\directlua{require"linebreak.lua"}
\begin{document}
\raggedright
\directlua{
initialize()
addchars('H')
addchars('e')
addchars('l')
addchars('l')
addchars('o')
addchars(' ')
addchars('W')
addchars('o')
addchars('r')
addchars('l')
addchars('d')
addpenalty(1,-10000) % Add line break, works fine!
addglue(1,25*65536) % XXX: Add vertical glue, doesn't work!
addkern(1,25*65536) % XXX: Add vertical kern, doesn't work!
addchars(' ')
addchars('H')
addchars('e')
addchars('y')
writeparagraph()
}
\end{document}
linebreak.lua:
local glyph_id = node.id("glyph")
local glue_id = node.id("glue")
local kern_id = node.id("kern")
local penalty_id = node.id("penalty")
local current_font = font.current()
local font_parameters = font.getfont(current_font).parameters
local n, head, last
function addchars(c)
for s in string.utfvalues(c) do
local char = unicode.utf8.char(s)
if unicode.utf8.match(char,"%s") then
-- its a space
n = node.new(glue_id)
n.width = font_parameters.space
n.shrink = font_parameters.space_shrink
n.stretch = font_parameters.space_stretch
else -- a glyph
n = node.new(glyph_id)
n.font = current_font
n.subtype = 1
n.char = s
n.lang = tex.language
n.uchyph = 1
n.left = tex.lefthyphenmin
n.right = tex.righthyphenmin
end
last.next = n
last = n
end
return last
end
function addpenalty(s,p)
n = node.new(penalty_id)
n.subtype = s or 0
n.penalty = p or 0
last.next = n
last = n
return n
end
function addkern(s,p)
n = node.new(kern_id)
n.subtype = s or 0
n.kern = p or 0
last.next = n
last = n
return n
end
function addglue(s,a,b,c,d,e)
n = node.new(glue_id)
n.subtype = s
n.width = a or 0
n.stretch = b or 0
n.shrink = c or 0
n.stretch_order = d or 0
n.shrink_order = e or 0
last.next = n
last = n
return n
end
function initialize()
-- add parindent glue in the beginning, create head node
head = node.new("glue")
head.width = tex.parindent
last = head
end
function writeparagraph()
-- append a penalty and parfillskip glue at the end of list
addpenalty(0,10000)
addglue(15,0,tex.parfillskip.stretch,tex.parfillskip.stretch_order)
-- create prev pointers
node.slide(head)
-- hyphenate
lang.hyphenate(head)
-- take care of fonts, kerning, ligature, etc
head = nodes.simple_font_handler(head)
-- call tex linebreaking, write to pdf
tex.write(tex.linebreak(head))
-- initize pointers
head = nil
last = nil
end
\vspace
foo=require('yourfile') ... foo.myfun() ...