global node
The node library contains functions that facilitate dealing with (lists of) nodes and their values. They allow you to create, alter, copy, delete, and insert LuaTEX node objects, the core objects within the typesetter.
LuaTEX nodes are represented in Lua as userdata with the metadata type luatex.node.
The
various parts within a node can be accessed using named fields.
Each node has at least the three fields next, id, and subtype:
- The next field returns the userdata object for the next node in a linked list of nodes, or nil, if there is no next node.
- The id indicates TEX’s ‘node type’. The field id has a numeric value for efficiency reasons, but some of the library functions also accept a string value instead of id.
- The subtype is another number. It often gives further information about a node of a particular id, but it is most important when dealing with ‘whatsits’, because they are differentiated solely based on their subtype.
The other available fields depend on the id (and for ‘whatsits’, the subtype) of the node.
Support for unset (alignment) nodes is partial: they can be queried and modified from Lua code, but not created.
Nodes can be compared to each other, but: you are actually comparing indices into the node memory. This means that equality tests can only be trusted under very limited conditions. It will not work correctly in any situation where one of the two nodes has been freed and/or reallocated: in that case, there will be false positives.
At the moment, memory management of nodes should still be done explicitly by the user. Nodes are not ‘seen’ by the Lua garbage collector, so you have to call the node freeing functions yourself when you are no longer in need of a node (list). Nodes form linked lists without reference counting, so you have to be careful that when control returns back to LuaTEX itself, you have not deleted nodes that are still referenced from a next pointer elsewhere, and that you did not create nodes that are referenced more than once. Normally the setters and getters handle this for you.
There are statistics available with regards to the allocated node memory, which can be handy for tracing.
😱 Types incomplete or incorrect? 🙏 Please contribute!
methods
node.effective_glue
function node.effective_glue(
glue: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
parent: (HlistNode|VlistNode),
round: boolean?
) -> (number|integer)?
round
- When you pass true as third argument the value will be rounded.
Return the effective width of a glue node.
Reference:
- Corresponding C source code: lnodelib.c#L8473-L8503
node.uses_font
function node.uses_font(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
font: integer
) -> boolean
Return true
when a glyph or disc node references that font.
Reference:
- Corresponding C source code: lnodelib.c#L7639-L7655
node.is_node
Return a number (the internal index of the node) if the argument is a userdata
object of type node
and false
when no node is passed.
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1199-L1211 - Corresponding C source code: lnodelib.c#L8295-L8303
node.types
Return a table that maps node id numbers to node type strings, providing an
overview of the possible top-level id
types.
Example:
assert.same(
node.types(),
{
[0] = "hlist",
[1] = "vlist",
[2] = "rule",
[3] = "ins",
[4] = "mark",
[5] = "adjust",
[6] = "boundary",
[7] = "disc",
[8] = "whatsit",
[9] = "local_par",
[10] = "dir",
[11] = "math",
[12] = "glue",
[13] = "kern",
[14] = "penalty",
[15] = "unset",
[16] = "style",
[17] = "choice",
[18] = "noad",
[19] = "radical",
[20] = "fraction",
[21] = "accent",
[22] = "fence",
[23] = "math_char",
[24] = "sub_box",
[25] = "sub_mlist",
[26] = "math_text_char",
[27] = "delim",
[28] = "margin_kern",
[29] = "glyph",
[30] = "align_record",
[31] = "pseudo_file",
[32] = "pseudo_line",
[33] = "page_insert",
[34] = "split_insert",
[35] = "expr_stack",
[36] = "nested_list",
[37] = "span",
[38] = "attribute",
[39] = "glue_spec",
[40] = "attribute_list",
[41] = "temp",
[42] = "align_stack",
[43] = "movement_stack",
[44] = "if_stack",
[45] = "unhyphenated",
[46] = "hyphenated",
[47] = "delta",
[48] = "passive",
[49] = "shape",
}
)
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1218-L1224 - Corresponding C source code: lnodelib.c#L3066-L3069
node.whatsits
Provides a table of subtype mappings.
TeX’s ‘whatsits’ all have the same id. The various subtypes are defined by their subtype fields.
Example:
assert.same(node.whatsits(), {
[0] = "open",
[1] = "write",
[2] = "close",
[3] = "special",
[4] = "late_special",
[7] = "save_pos",
[8] = "late_lua",
[9] = "user_defined",
[16] = "pdf_literal",
[17] = "pdf_late_literal",
[18] = "pdf_refobj",
[19] = "pdf_annot",
[20] = "pdf_start_link",
[21] = "pdf_end_link",
[22] = "pdf_dest",
[23] = "pdf_action",
[24] = "pdf_thread",
[25] = "pdf_start_thread",
[26] = "pdf_end_thread",
[27] = "pdf_thread_data",
[28] = "pdf_link_data",
[29] = "pdf_colorstack",
[30] = "pdf_setmatrix",
[31] = "pdf_save",
[32] = "pdf_restore",
[33] = "pdf_link_state",
})
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1226-L1233 - Corresponding C source code: lnodelib.c#L3073-L3076
node.id
Convert a single type name to its internal numeric representation.
Example:
local function equals(name, id)
assert.equals(node.id(name), id)
end
equals("hlist", 0)
equals("vlist", 1)
equals("rule", 2)
equals("ins", 3)
equals("mark", 4)
equals("adjust", 5)
equals("boundary", 6)
equals("disc", 7)
equals("whatsit", 8)
equals("local_par", 9)
equals("dir", 10)
equals("math", 11)
equals("glue", 12)
equals("kern", 13)
equals("penalty", 14)
equals("unset", 15)
equals("style", 16)
equals("choice", 17)
equals("noad", 18)
equals("radical", 19)
equals("fraction", 20)
equals("accent", 21)
equals("fence", 22)
equals("math_char", 23)
equals("sub_box", 24)
equals("sub_mlist", 25)
equals("math_text_char", 26)
equals("delim", 27)
equals("margin_kern", 28)
equals("glyph", 29)
equals("align_record", 30)
equals("pseudo_file", 31)
equals("pseudo_line", 32)
equals("page_insert", 33)
equals("split_insert", 34)
equals("expr_stack", 35)
equals("nested_list", 36)
equals("span", 37)
equals("attribute", 38)
equals("glue_spec", 39)
equals("attribute_list", 40)
equals("temp", 41)
equals("align_stack", 42)
equals("movement_stack", 43)
equals("if_stack", 44)
equals("unhyphenated", 45)
equals("hyphenated", 46)
equals("delta", 47)
equals("passive", 48)
equals("shape", 49)
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1235-L1244 - Corresponding C source code: lnodelib.c#L470-L483
node.type
@param
n
- The numeric node type id.
Convert an internal numeric node type representation to an external node type string.
If the argument is a number, then the type function converts an
internal numeric representation to an external string representation.
Otherwise, it will return the string node
if the object
represents a node, and nil
otherwise.
assert.equals(node.type(29), "glyph")
assert.equals(node.type(node.id("glyph")), "glyph")
assert.is_nil(node.type("xxx"))
Reference:
- Corresponding C source code: lnodelib.c#L1993-L2009
node.subtype
Convert a single whatsit
name to its internal numeric representation (subtype).
Example:
local function equals(name, id)
assert.equals(node.subtype(name), id)
end
equals("open", 0)
equals("write", 1)
equals("close", 2)
equals("special", 3)
equals("late_special", 4)
equals("save_pos", 7)
equals("late_lua", 8)
equals("user_defined", 9)
equals("pdf_literal", 16)
equals("pdf_late_literal", 17)
equals("pdf_refobj", 18)
equals("pdf_annot", 19)
equals("pdf_start_link", 20)
equals("pdf_end_link", 21)
equals("pdf_dest", 22)
equals("pdf_action", 23)
equals("pdf_thread", 24)
equals("pdf_start_thread", 25)
equals("pdf_end_thread", 26)
equals("pdf_thread_data", 27)
equals("pdf_link_data", 28)
equals("pdf_colorstack", 29)
equals("pdf_setmatrix", 30)
equals("pdf_save", 31)
equals("pdf_restore", 32)
equals("pdf_link_state", 33)
Reference:
- Corresponding C source code: lnodelib.c#L1976-L1989
node.fields
Return an array of valid field names for a particular type of node.
Example:
local types = {}
for type_id, type in pairs(node.types()) do
if type_id ~= 8 then
types[type] = {}
for field_id, field in pairs(node.fields(type_id)) do
types[type][field_id] = field
end
end
end
assert.same(types, {
accent = {
"id",
"subtype",
"attr",
"nucleus",
"sub",
"sup",
"accent",
"bot_accent",
"top_accent",
"overlay_accent",
"fraction",
[-1] = "prev",
[0] = "next",
},
adjust = {
"id",
"subtype",
"attr",
"head",
[-1] = "prev",
[0] = "next",
},
align_record = { "id", "subtype", [-1] = "prev", [0] = "next" },
align_stack = { "id", "subtype", [-1] = "prev", [0] = "next" },
attribute = { "id", "number", "value", [0] = "next" },
attribute_list = { "id", [0] = "next" },
boundary = {
"id",
"subtype",
"attr",
"value",
[-1] = "prev",
[0] = "next",
},
choice = {
"id",
"subtype",
"attr",
"display",
"text",
"script",
"scriptscript",
[-1] = "prev",
[0] = "next",
},
delim = {
"id",
"subtype",
"attr",
"small_fam",
"small_char",
"large_fam",
"large_char",
[-1] = "prev",
[0] = "next",
},
delta = { "id", "subtype", [-1] = "prev", [0] = "next" },
dir = {
"id",
"subtype",
"attr",
"dir",
"level",
[-1] = "prev",
[0] = "next",
},
disc = {
"id",
"subtype",
"attr",
"pre",
"post",
"replace",
"penalty",
[-1] = "prev",
[0] = "next",
},
expr_stack = { "id", "subtype", [-1] = "prev", [0] = "next" },
fence = {
"id",
"subtype",
"attr",
"delim",
"italic",
"height",
"depth",
"options",
"class",
[-1] = "prev",
[0] = "next",
},
fraction = {
"id",
"subtype",
"attr",
"width",
"num",
"denom",
"left",
"right",
"middle",
"fam",
"options",
[-1] = "prev",
[0] = "next",
},
glue = {
"id",
"subtype",
"attr",
"leader",
"width",
"stretch",
"shrink",
"stretch_order",
"shrink_order",
[-1] = "prev",
[0] = "next",
},
glue_spec = {
"id",
"width",
"stretch",
"shrink",
"stretch_order",
"shrink_order",
[0] = "next",
},
glyph = {
"id",
"subtype",
"attr",
"char",
"font",
"lang",
"left",
"right",
"uchyph",
"components",
"xoffset",
"yoffset",
"width",
"height",
"depth",
"expansion_factor",
"data",
[-1] = "prev",
[0] = "next",
},
hlist = {
"id",
"subtype",
"attr",
"width",
"depth",
"height",
"dir",
"shift",
"glue_order",
"glue_sign",
"glue_set",
"head",
[-1] = "prev",
[0] = "next",
},
hyphenated = { "id", "subtype", [-1] = "prev", [0] = "next" },
if_stack = { "id", "subtype", [-1] = "prev", [0] = "next" },
ins = {
"id",
"subtype",
"attr",
"cost",
"depth",
"height",
"spec",
"head",
[-1] = "prev",
[0] = "next",
},
kern = {
"id",
"subtype",
"attr",
"kern",
"expansion_factor",
[-1] = "prev",
[0] = "next",
},
local_par = {
"id",
"subtype",
"attr",
"pen_inter",
"pen_broken",
"dir",
"box_left",
"box_left_width",
"box_right",
"box_right_width",
[-1] = "prev",
[0] = "next",
},
margin_kern = {
"id",
"subtype",
"attr",
"width",
"glyph",
[-1] = "prev",
[0] = "next",
},
mark = {
"id",
"subtype",
"attr",
"class",
"mark",
[-1] = "prev",
[0] = "next",
},
math = {
"id",
"subtype",
"attr",
"surround",
"width",
"stretch",
"shrink",
"stretch_order",
"shrink_order",
[-1] = "prev",
[0] = "next",
},
math_char = {
"id",
"subtype",
"attr",
"fam",
"char",
[-1] = "prev",
[0] = "next",
},
math_text_char = {
"id",
"subtype",
"attr",
"fam",
"char",
[-1] = "prev",
[0] = "next",
},
movement_stack = { "id", "subtype", [-1] = "prev", [0] = "next" },
nested_list = { "id", "subtype", [-1] = "prev", [0] = "next" },
noad = {
"id",
"subtype",
"attr",
"nucleus",
"sub",
"sup",
[-1] = "prev",
[0] = "next",
},
page_insert = {
"id",
"subtype",
"height",
"last_ins_ptr",
"best_ins_ptr",
"width",
"stretch",
"shrink",
"stretch_order",
"shrink_order",
[-1] = "prev",
[0] = "next",
},
passive = { "id", "subtype", [-1] = "prev", [0] = "next" },
penalty = {
"id",
"subtype",
"attr",
"penalty",
[-1] = "prev",
[0] = "next",
},
pseudo_file = { "id", "subtype", [-1] = "prev", [0] = "next" },
pseudo_line = { "id", "subtype", [-1] = "prev", [0] = "next" },
radical = {
"id",
"subtype",
"attr",
"nucleus",
"sub",
"sup",
"left",
"degree",
"width",
"options",
[-1] = "prev",
[0] = "next",
},
rule = {
"id",
"subtype",
"attr",
"width",
"depth",
"height",
"dir",
"index",
"left",
"right",
[-1] = "prev",
[0] = "next",
},
shape = { "id", "subtype", [-1] = "prev", [0] = "next" },
span = { "id", "subtype", [-1] = "prev", [0] = "next" },
split_insert = {
"id",
"subtype",
"height",
"last_ins_ptr",
"best_ins_ptr",
"broken_ptr",
"broken_ins",
[-1] = "prev",
[0] = "next",
},
style = {
"id",
"subtype",
"attr",
"style",
[-1] = "prev",
[0] = "next",
},
sub_box = {
"id",
"subtype",
"attr",
"head",
[-1] = "prev",
[0] = "next",
},
sub_mlist = {
"id",
"subtype",
"attr",
"head",
[-1] = "prev",
[0] = "next",
},
temp = { "id", "subtype", [-1] = "prev", [0] = "next" },
unhyphenated = { "id", "subtype", [-1] = "prev", [0] = "next" },
unset = {
"id",
"subtype",
"attr",
"width",
"depth",
"height",
"dir",
"shrink",
"glue_order",
"glue_sign",
"stretch",
"span",
"head",
[-1] = "prev",
[0] = "next",
},
vlist = {
"id",
"subtype",
"attr",
"width",
"depth",
"height",
"dir",
"shift",
"glue_order",
"glue_sign",
"glue_set",
"head",
[-1] = "prev",
[0] = "next",
},
})
If you want to get the valid fields for a “whatsit”, you have to supply the second argument also. In other cases, any given second argument will be silently ignored.
Reference:
- Corresponding C source code: lnodelib.c#L3080-L3115
node.has_field
function node.has_field(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
field: string
) -> t boolean
Return a boolean that is only true
if n
is actually a node, and it has the field.
Example:
local glyph = node.new("glyph")
for _, field in ipairs({
"prev",
"next",
"id",
"subtype",
"attr",
"char",
"font",
"lang",
"left",
"right",
"uchyph",
"components",
"xoffset",
"yoffset",
"width",
"height",
"depth",
"expansion_factor",
"data",
}) do
assert.is_true(node.has_field(glyph, field))
end
assert.is_false(node.has_field(glyph, "xxx"))
Reference:
- Corresponding C source code: lnodelib.c#L2993-L3000
@see node.direct.has_field
node.new
function node.new(
id: (integer|NodeTypeName),
subtype: (integer|string)?
) -> Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Create a new node.
All its fields are initialized to
either zero or nil
except for id
and subtype
. Instead of
numbers you can also use strings (names). If you create a new whatsit
node
the second argument is required. As with all node functions, this function
creates a node at the TeX level.
Example:
for type_id, node_type in pairs(node.types()) do
if node_type == "whatsit" then
for subtype_id, subtype in pairs(node.whatsits()) do
local n = node.new(node_type, subtype)
assert.equals(n.id, type_id)
assert.equals(n.subtype, subtype_id)
end
else
local n = node.new(node_type)
assert.equals(n.id, type_id)
end
end
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1299-L1314 - Corresponding C source code: lnodelib.c#L2055-L2060
@see node.direct.new
node.free
function node.free(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> next Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Free the TeX memory allocated for node n
and return the next field of the
freed node.
Be careful: no checks are done on whether this node is still pointed to from
a register or some next
field: it is up to you to make sure that the
internal data structures remain correct.
Example:
local n1 = node.new("glyph")
local n2 = node.new("glyph")
n1.next = n2
assert.equals(node.free(n1), n2)
Reference:
- Corresponding C source code: lnodelib.c#L2073-L2090
node.flush_node
function node.flush_node(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
Free the TeX memory allocated for the specified node and return nothing.
Reference:
- Corresponding C source code: lnodelib.c#L2113-L2122
node.flush_list
function node.flush_list(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
Free the TeX memory allocated for a list of nodes.
Be
careful: no checks are done on whether any of these nodes is still pointed to
from a register or some next
field: it is up to you to make sure that the
internal data structures remain correct.
Reference:
- Corresponding C source code: lnodelib.c#L2137-L2146
node.copy
function node.copy(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> m Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Create a deep copy of node n
, including all nested lists as in the case
of a hlist
or vlist
node. Only the next
field is not copied.
Reference:
- Corresponding C source code: lnodelib.c#L2476-L2485
node.copy_list
function node.copy_list(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
m: Node?
) -> m Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Create a deep copy of the node list that starts at node n
.
If
m
is also given, the copy stops just before node m
.
Note that you cannot copy attribute lists this way. However, there is normally no
need to copy attribute lists as when you do assignments to the attr
field
or make changes to specific attributes, the needed copying and freeing takes
place automatically.
Reference:
- Corresponding C source code: lnodelib.c#L2440-L2452
node.prev
function node.prev(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> m Node?
Return the node preceding the given node, or nil
if
there is no such node.
Reference:
- Corresponding C source code: lnodelib.c#L379-L388
node.next
function node.next(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> m Node?
Return the node following the given node, or nil
if
there is no such node.
Reference:
- Corresponding C source code: lnodelib.c#L390-L399
node.current_attr
Return the currently active list of attributes, if there is one.
The intended usage of current_attr
is as follows:
local x1 = node.new("glyph")
x1.attr = node.current_attr()
local x2 = node.new("glyph")
x2.attr = node.current_attr()
or:
local x1 = node.new("glyph")
local x2 = node.new("glyph")
local ca = node.current_attr()
x1.attr = ca
x2.attr = ca
The attribute lists are ref counted and the assignment takes care of incrementing
the refcount. You cannot expect the value ca
to be valid any more when
you assign attributes (using tex.setattribute
) or when control has been
passed back to TeX.
Note: this function is somewhat experimental, and it returns the actual attribute list, not a copy thereof. Therefore, changing any of the attributes in the list will change these values for all nodes that have the current attribute list assigned to them.
Reference:
- Corresponding C source code: lnodelib.c#L6511-L6532
node.hpack
function node.hpack(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
width: integer?,
info: string?,
dir: string?
)
-> n Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> badness integer
Create a new hlist
by packaging the list that begins at node n
into a horizontal box.
With only a single argument, this box is created using
the natural width of its components. In the three argument form, info
must be either additional
or exactly
, and width
is the
additional (\hbox spread
) or exact (\hbox to
) width to be used.
The second return value is the badness of the generated box.
Caveat: there can be unexpected side-effects to this function, like updating
some of the marks
and \inserts
. Also note that the content of
h
is the original node list n
: if you call node.free(h)
you will also free the node list itself, unless you explicitly set the list
field to nil
beforehand. And in a similar way, calling node.free(n)
will invalidate h
as well!
Reference:
- Corresponding C source code: lnodelib.c#L2576-L2619
node.vpack
function node.vpack(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
height: integer?,
info: ("additional"|"exactly")?,
dir: (DirectionSpecifier|DirectionSpecifierId)?
)
-> new_head Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> badness integer
height
- The additional (\vbox spread
) or exact (\vbox to
) height to be used.
@param info
- Must be either additional
(\vbox spread
) or exactly
(\vbox to
).
@return badness
- The second return value is the badness of the generated box.
😱 Types incomplete or incorrect? 🙏 Please contribute!
Create a new vlist
by packaging the list that begins at node head
into a vertical box.
With only a single argument, this box is created using the natural height of its components.
Caveat: there can be unexpected side-effects to this function, like updating
some of the marks
and \inserts
. Also note that the content of
new_head
is the original node list head
: if you call node.free(new_head)
you will also free the node list itself, unless you explicitly set the list
field to nil
beforehand. And in a similar way, calling node.free(head)
will invalidate new_head
as well!
Reference:
- Corresponding C source code: lnodelib.c#L2673-L2716
node.prepend_prevdepth
function node.prepend_prevdepth(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
prevdepth: integer
) -> new_prevdepth integer
n
- vlist or hlist
Add the interlinespace to a line keeping the baselineskip and lineskip into account.
Reference:
- Corresponding C source code: lnodelib.c#L8763-L8801
node.dimensions
function node.dimensions(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
dir: DirectionSpecifier?
)
-> width integer
-> height integer
-> depth integer
@return width
- scaled points
@return height
- scaled points
@return depth
- scaled points
😱 Types incomplete or incorrect? 🙏 Please contribute!
Calculate the natural in-line dimensions of the end of the node list starting
at node n
.
The return values are scaled points.
You need to keep in mind that this is one of the few places in TeX where floats
are used, which means that you can get small differences in rounding when you
compare the width reported by hpack
with dimensions
.
Reference:
Source: luatex-nodes.tex#L1490-L1546 * Corresponding C source code: lnodelib.c#L2767-L2812
node.dimensions
function node.dimensions(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
t: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
dir: DirectionSpecifier?
)
-> width integer
-> height integer
-> depth integer
t
- terminating node
@return width
- scaled points
@return height
- scaled points
@return depth
- scaled points
😱 Types incomplete or incorrect? 🙏 Please contribute!
Calculate the natural in-line dimensions of the node list starting
at node n
and terminating just before node t
.
Reference:
Source: luatex-nodes.tex#L1490-L1546 * Corresponding C source code: lnodelib.c#L2767-L2812
node.dimensions
function node.dimensions(
glue_set: integer,
glue_sign: integer,
glue_order: integer,
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
dir: DirectionSpecifier?
)
-> width integer
-> height integer
-> depth integer
@return width
- scaled points
@return height
- scaled points
@return depth
- scaled points
😱 Types incomplete or incorrect? 🙏 Please contribute!
Calculates the natural in-line dimensions of the end of the node list starting
at node n
.
This is an alternative format that starts with glue parameters as the first three arguments.
This calling method takes glue settings into account and is especially useful for
finding the actual width of a sublist of nodes that are already boxed, for
example in code like this, which prints the width of the space in between the
a
and b
as it would be if \box0
was used as-is:
\setbox0 = \hbox to 20pt {a b}
\directlua{print (node.dimensions(
tex.box[0].glue_set,
tex.box[0].glue_sign,
tex.box[0].glue_order,
tex.box[0].head.next,
node.tail(tex.box[0].head)
)) }
Reference:
Source: luatex-nodes.tex#L1490-L1546 * Corresponding C source code: lnodelib.c#L2838-L2880
node.dimensions
function node.dimensions(
glue_set: integer,
glue_sign: integer,
glue_order: integer,
d: integer,
t: integer,
dir: DirectionSpecifier?
)
-> width integer
-> height integer
-> depth integer
d
- The index number of the node in the memory table for direct access.
@param t
- terminating node
@return width
- scaled points
@return height
- scaled points
@return depth
- scaled points
😱 Types incomplete or incorrect? 🙏 Please contribute!
Calculate the natural in-line dimensions of the node list starting
at node n
and terminating just before node t
.
This is an alternative format that starts with glue parameters as the first three arguments.
Reference:
Source: luatex-nodes.tex#L1490-L1546 * Corresponding C source code: lnodelib.c#L2767-L2812
node.rangedimensions
function node.rangedimensions(
parent: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
first: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
last: Node?
)
-> width integer
-> height integer
-> depth integer
@return width
- scaled points
@return height
- scaled points
@return depth
- scaled points
😱 Types incomplete or incorrect? 🙏 Please contribute!
Calculate the natural in-line dimensions of the node list parent
starting
at node first
and terminating just before node last
.
This functions saves a few lookups in comparison to node.dimensions()
and can be more convenient in some
cases.
Reference:
- Corresponding C source code: lnodelib.c#L2814-L2834
node.mlist_to_hlist
function node.mlist_to_hlist(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
display_type: string,
penalties: boolean
) -> h Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Run the internal mlist
to hlist
conversion, converting the math list in
n
into the horizontal list h
.
The interface is exactly the same
as for the callback mlist_to_hlist
.
Reference:
- Corresponding C source code: lnodelib.c#L2906-L2918
node.tail
function node.tail(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> m Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Return the last node of the node list that starts at n
.
Reference:
- Corresponding C source code: lnodelib.c#L3262-L3274
node.length
function node.length(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
m: Node?
) -> i integer
Return the number of nodes contained in the node list that starts at n
.
If m
is also supplied it stops at m
instead of at the end of the
list. The node m
is not counted.
Reference:
- Corresponding C source code: lnodelib.c#L4374-L4386
node.count
function node.count(
id: (integer|string),
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
m: Node?
) -> i integer
Return the number of nodes contained in the node list that starts at n
that have a matching id
field.
If m
is also supplied, counting
stops at m
instead of at the end of the list. The node m
is not
counted. This function also accept string id
’s.
Reference:
- Corresponding C source code: lnodelib.c#L4388-L4401
node.is_char
function node.is_char(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
font: integer?
)
-> (boolean|integer)?
-> integer?
Signal if the glyph is already turned into a character reference or not by examining the subtype.
Example:
assert.equals(node.is_char(node.new("glyph")), 0)
assert.equals(node.is_char(node.new("hlist")), nil)
Reference:
- Corresponding C source code: lnodelib.c#L3004-3024
node.is_glyph
function node.is_glyph(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
-> character (boolean|integer)
-> font integer
Signal if the glyph is already turned into a character reference or not by examining the subtype.
Example:
local character, font = node.is_glyph(node.new("glyph"))
assert.equals(character, 0)
assert.equals(font, 0)
assert.is_false(node.is_glyph(node.new("hlist")))
Reference:
- Corresponding C source code: lnodelib.c#L3026-L3037
node.traverse
function node.traverse(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> fun() -> (Node,integer,integer)
Return a Lua iterator that loops over the node list that starts at n
.
Example:
callback.register("post_linebreak_filter", function(head)
for n, type, subtype in node.traverse(head.head) do
assert.is_type(n, "userdata")
assert.is_type(type, "number")
assert.is_type(subtype, "number")
end
return head
end)
It should be clear from the definition of the function f
that even though
it is possible to add or remove nodes from the node list while traversing, you
have to take great care to make sure all the next
(and prev
)
pointers remain valid.
Reference:
- Corresponding C source code: lnodelib.c#L4156-L4168
node.traverse_id
function node.traverse_id(
id: integer,
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
) -> fun() -> (Node,integer)
Return an iterator that loops over all the nodes in the list that starts at
n
that have a matching id
field.
Reference:
- Corresponding C source code: lnodelib.c#L4196-L4209
node.traverse_char
function node.traverse_char(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> fun() -> (Node,integer,integer)
Loop over the glyph
nodes in a list.
Only nodes with a subtype less than 256 are seen.
Reference:
- Corresponding C source code: lnodelib.c#L4237-L4249
node.traverse_glyph
function node.traverse_glyph(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> fun() -> (Node,integer,integer)
Loop over a list and return the list and filter all glyphs.
Reference:
- Corresponding C source code: lnodelib.c#L4277-L4289
node.traverse_list
function node.traverse_list(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> fun() -> (Node,integer,integer,Node)
Loop over the hlist
and vlist
nodes in a list.
The four return values can save some time compared to fetching these fields.
Reference:
- Corresponding C source code: lnodelib.c#L4318-L4330
node.has_glyph
function node.has_glyph(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> n Node?
Return the first glyph
or disc
node in the given list.
Reference:
- Corresponding C source code: lnodelib.c#L6368-L6382
node.end_of_math
function node.end_of_math(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> t Node?
Look for and return the next math
node following the start node n
.
If
the given node is a math end node this helper returns that node, else it follows
the list and returns the next math endnote. If no such node is found nil
is
returned.
Reference:
- Corresponding C source code: lnodelib.c#L3293-L3313
node.remove
function node.remove(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
current: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
)
-> head Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> current Node?
current
- A node following the list head
.
@return head
- The new head
@return current
- The node following the current
in the calling
argument.
😱 Types incomplete or incorrect? 🙏 Please contribute!
Remove the node current
from the list following head
.
It is your responsibility to make sure it is really part of that list.
The return values are the new head
and current
nodes. The
returned current
is the node following the current
in the calling
argument, and is only passed back as a convenience (or nil
, if there is
no such node). The returned head
is more important, because if the
function is called with current
equal to head
, it will be
changed.
Example:
local g1 = node.new("glyph")
local g2 = node.new("glyph")
local g3 = node.new("glyph")
g1.next = g2
g2.next = g3
assert.equals(g1.next, g2)
local head, current = node.remove(g1, g2)
assert.equals(g1.next, g3)
assert.equals(head, g1)
assert.equals(current, g3)
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1778-1794 - Corresponding C source code: lnodelib.c#L2176-L2215
node.insert_before
function node.insert_before(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
current: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
new: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
)
-> head Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> new Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Insert the node new
before current
into the list
following head
.
It is your responsibility to make sure that current
is really part of that list. The return values are the (potentially
mutated) head
and the node new
, set up to be part of the list
(with correct next
field). If head
is initially nil
, it
will become new
.
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1793-L1807 - Corresponding C source code: lnodelib.c#L2271-L2315
node.insert_after
function node.insert_after(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
current: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
new: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
)
-> head Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> new Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Insert the node new
after current
into the list
following head
.
It is your responsibility to make sure that current
is really part of that list. The return values are the head
and
the node new
, set up to be part of the list (with correct next
field). If head
is initially nil
, it will become new
.
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L1809-L1822 - Corresponding C source code: lnodelib.c#L2361-L2395
node.first_glyph
function node.first_glyph(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
m: Node?
)
-> n Node?
-> success boolean
Return the first node in the list starting at n
that is a glyph node
with a subtype indicating it is a glyph, or nil
.
If m
is given,
processing stops at (but including) that node, otherwise processing stops at the
end of the list.
Reference:
- Corresponding C source code: lnodelib.c#L6312-L6337
node.ligaturing
function node.ligaturing(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
tail: Node?
)
-> head Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> tail Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> success boolean
@return head
- the new head
@return tail
- the new tail (both head
and tail
can change into a new ligature)
Apply TeX-style ligaturing to the specified nodelist.
Reference:
- Corresponding C source code: lnodelib.c#L5945-L5984
node.kerning
function node.kerning(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
tail: Node?
)
-> head Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> tail Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> success boolean
@return head
- the new head (can be an inserted kern node, because special kernings with word boundaries are possible).
@return tail
- the new tail (can be an inserted kern node, because special kernings with word boundaries are possible).
Apply TeX-style kerning to the specified node list.
Reference:
- Corresponding C source code: lnodelib.c#L6021-L6060
node.unprotect_glyph
function node.unprotect_glyph(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
Convert from characters
to glyphs
during node
processing by subtracting 256
from all glyph node subtypes.
Reference:
- Corresponding C source code: lnodelib.c#L6217-L6223
node.unprotect_glyphs
function node.unprotect_glyphs(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
tail: Node?
)
Convert from characters
to glyphs
during node
processing by subtracting 256
from the glyph node subtype.
Reference:
- Corresponding C source code: lnodelib.c#L6243-L6259
node.protect_glyph
function node.protect_glyph(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
Add 256
to the glyph
node subtype
except that if the value is 1
, add only 255
.
The special handling of 1
means
that characters
will become glyphs
after subtraction of 256
.
Reference:
- Corresponding C source code: lnodelib.c#L6209-L6215
node.protect_glyphs
function node.protect_glyphs(
head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
tail: Node?
)
Add 256
to all glyph
node subtypes in the node list starting at head
,
except that if the value is 1
, add only 255
.
The special handling of 1
means
that characters
will become glyphs
after subtraction of 256
.
Reference:
- Corresponding C source code: lnodelib.c#L6225-L6241
node.last_node
Pop the last node from TeX's “current list”.
Reference:
- Corresponding C source code: lnodelib.c#L2556-L2563
node.write
function node.write(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
Append a node list to TeX's “current list”.
The node list is not deep-copied! There is no error checking either! You mignt need to enforce horizontal mode in order for this to work as expected.
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L2518-L2521, luatex-nodes.tex#L1913-L1923 - Corresponding C source code: lnodelib.c#L2505-L2525
node.protrusion_skippable
function node.protrusion_skippable(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> skippable boolean
Return true
if, for the purpose of line boundary discovery when
character protrusion is active, this node can be skipped.
Reference:
- Corresponding C source code: lnodelib.c#L6488-L6493
node.setglue
function node.setglue(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
width: (integer|any),
stretch: (integer|any),
shrink: (integer|any),
stretch_order: (integer|any),
shrink_order: (integer|any)
)
Set the five properties of a glue
node in one go.
Non-numeric values are equivalent to zero and reset a property.
When you pass values, only arguments that are numbers are assigned so
will only adapt the width and shrink.
When a list node is passed, you set the glue, order and sign instead.
Reference:
- Corresponding C source code: lnodelib.c#L3862-L3883
node.getglue
function node.getglue(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
-> width_or_glue_set (integer|number)?
-> stretch_or_glue_order integer?
-> shrink_or_glue_sign integer?
-> stretch_order integer?
-> shrink_order integer?
@return width_or_glue_set
- When a list node (vlist
or hlist
) is passed, than the glue set is returned.
@return stretch_or_glue_order
- When a list node (vlist
or hlist
) is passed, than the glue order is returned.
@return shrink_or_glue_sign
- When a list node (vlist
or hlist
) is passed, than the glue sign is returned.
Return 5 values or nothing when no glue is passed.
When the second argument is false, only the width is returned (this is consistent
with tex.get
).
Reference:
- Corresponding C source code: lnodelib.c#L3840-L3860
node.is_zero_glue
function node.is_zero_glue(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> isglue boolean
Return true
when the width, stretch and shrink properties
are zero.
Reference:
- Corresponding C source code: lnodelib.c#L3885-L3899
node.has_attribute
function node.has_attribute(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
id: integer,
value: integer?
) -> value integer?
Test if a node has the attribute with number id
set.
If value
is
also supplied, also tests if the value matches value
. It returns the value,
or, if no match is found, nil
.
Reference:
- Corresponding C source code: lnodelib.c#L3339-L3353
node.get_attribute
function node.get_attribute(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
id: integer
) -> value integer?
Test if a node has an attribute with number id
set.
It returns the
value, or, if no match is found, nil
. If no id
is given then the
zero attributes is assumed.
Reference:
- Corresponding C source code: lnodelib.c#L3375-L3406
node.find_attribute
function node.find_attribute(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
id: integer
)
-> value integer?
-> n Node?
Find the first node that has attribute with number id
set.
It returns the value and the node if there is a match and otherwise nothing.
Reference:
- Corresponding C source code: lnodelib.c#L3408-L3443
node.set_attribute
function node.set_attribute(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
id: integer,
value: integer?
)
Set the attribute with number id
to the value value
.
Duplicate assignments are ignored.
Reference:
- Corresponding C source code: lnodelib.c#L3563-L3578
node.unset_attribute
function node.unset_attribute(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
id: integer,
value: integer?
) -> value integer?
Unset the attribute with the number id
.
If value
is also supplied, it
will only perform this operation if the value matches value
. Missing
attributes or attribute-value pairs are ignored.
If the attribute was actually deleted, returns its old value. Otherwise, returns
nil
.
Reference:
- Corresponding C source code: lnodelib.c#L3580-L3596
node.slide
function node.slide(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> tail Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Return the found tail node and make sure that the node lists is double linked.
After some callbacks automatic sliding takes place. This feature can be turned
off with node.fix_node_lists(false)
but you better make sure then that
you don't mess up lists. In most cases TeX itself only uses next
pointers but your other callbacks might expect proper prev
pointers too.
Future versions of LuaTeX can add more checking but this will not influence
usage.
Reference:
- Corresponding C source code: lnodelib.c#L3226-L3241
node.check_discretionaries
function node.check_discretionaries(head: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
Check all disc
nodes in the node list.
When you fool around with disc nodes you need to be aware of the fact that they have a special internal data structure. As long as you reassign the fields when you have extended the lists it’s ok because then the tail pointers get updated, but when you add to list without reassigning you might end up in trouble when the linebreak routine kicks in.
Reference:
- Corresponding C source code: lnodelib.c#L8615-L8627
node.check_discretionary
function node.check_discretionary(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
Check one disc
node only and also check if the node is a disc
node.
When you fool around with disc nodes you need to be aware of the fact that they have a special internal data structure. As long as you reassign the fields when you have extended the lists it’s ok because then the tail pointers get updated, but when you add to list without reassigning you might end up in trouble when the linebreak routine kicks in.
Reference:
- Corresponding C source code: lnodelib.c#L8629-L8638
node.flatten_discretionaries
function node.flatten_discretionaries(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
-> head Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> count integer
Remove the discretionaries in the list and inject the replace field when set.
Reference:
- Corresponding C source code: lnodelib.c#L8640-L8679
node.family_font
@param
fam
- family identifier
Return the font currently associated with the node.
You can normally also access the font with the normal font field or getter because it will resolve the family automatically for noads.
Reference:
- Corresponding C source code: lnodelib.c#L2922-L2932
node.getnext
function node.getnext(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> next Node?
Return the next node of the current node.
Example:
local n1 = node.new("glyph")
local n2 = node.new("glyph")
n1.next = n2
assert.equals(node.getnext(n1), n2)
Reference:
- Corresponding C source code: lnodelib.c#L1782-L1800
@see node.getprev node.direct.getnext
node.getprev
function node.getprev(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> prev Node?
Return the previous node of the current node.
Example:
local n1 = node.new("glyph")
local n2 = node.new("glyph")
n1.prev = n2
assert.equals(node.getprev(n1), n2)
Reference:
- Corresponding C source code: lnodelib.c#L1831-L1846
node.getboth
function node.getboth(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
})
-> prev Node?
-> next Node?
Return the previous and next pointer of a node.
Example:
local n1 = node.new("glyph")
local n2 = node.new("glyph")
local n3 = node.new("glyph")
n1.next = n2
n2.next = n3
node.slide(n1) -- to set n2.prev
local prev, next = node.getboth(n2)
assert.equals(prev, n1)
assert.equals(next, n3)
Reference:
- Corresponding C source code: lnodelib.c#L1884-L1902
@see node.direct.setboth
node.getid
function node.getid(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> id integer
Return the id
(type) of a node.
Reference:
- Corresponding C source code: lnodelib.c#L487-L496
node.getsubtype
function node.getsubtype(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> subtype integer
Return the subtype
of a node.
Example:
Reference:
- Corresponding C source code: lnodelib.c#L544-L558
node.getfont
function node.getfont(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> font integer?
Return the font identifier of a glyph
, math_char
, math_text_char
or delim
node.
Example:
Reference:
- Corresponding C source code: lnodelib.c#L636-L654
node.getchar
function node.getchar(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> char integer?
Return the character index (char
) in the font of glyph
, math_char
, math_text_char
or delim
nodes.
Example:
Reference:
- Corresponding C source code: lnodelib.c#L739-L758
@see node.direct.getchar node.direct.setchar
node.getwhd
function node.getwhd(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
get_expansion_factor: boolean?
)
-> width integer
-> height integer
-> depth integer
-> ex integer?
@return ex
- If the node is a glyph
and get_ex
is true
😱 Types incomplete or incorrect? 🙏 Please contribute!
Return the width
, height
and depth
of a list, rule or (unexpanded) glyph
as well as glue
(its spec is looked at) and unset
node.
Reference:
- Corresponding C source code: lnodelib.c#L1350-L1378
node.getdisc
function node.getdisc(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
get_tail: boolean?
)
-> pre Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> post Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> replace Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
-> pre_tail Node?
-> post_tail Node?
-> replace_tail Node?
Return the pre
, post
and replace
fields and optionally when true is passed also the tail fields.
Reference:
- Corresponding C source code: lnodelib.c#L1236-L1253
node.getlist
function node.getlist(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> list Node?
Get child node lists of parent hlist
, vlist
, sub_box
, sub_mlist
, ins
, or adjust
nodes.
Example:
local hlist = node.new("hlist")
local glyph1 = node.new("glyph")
local glyph2 = node.new("glyph")
hlist.head = glyph1
glyph1.next = glyph2
local list = node.getlist(hlist)
assert.equals(list, glyph1)
assert.equals(list.next, glyph2)
Reference:
- Corresponding C source code: lnodelib.c#L1440-L1458
node.getleader
function node.getleader(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> leaders Node?
Get the leaders of glue
nodes.
Reference:
- Corresponding C source code: lnodelib.c#L1489-L1501
node.setfield
function node.setfield(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
field: string,
value: any
)
Set the value of a generic node field.
Example:
Reference:
- Corresponding C source code: lnodelib.c#L7348-L7364
@see node.direct.setfield
node.getfield
function node.getfield(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
field: string
) -> any?
Get the value of a generic node field.
Other field names are often shared so a specific getter makes no sense.
Example:
local n = node.new("glyph") --[[@as GlyphNode]]
n.char = 123
assert.equals(node.getfield(n, "char"), 123)
Reference:
- Corresponding C source code: lnodelib.c#L5189-L5207
node.setproperty
function node.setproperty(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
value: any
)
Assign values to the properties table.
Example:
local n = node.new("glyph")
node.setproperty(n, "Some value")
assert.equals(node.getproperty(n), "Some value")
Reference:
- Source file of the
LuaTeX
manual: lnodelib.c#L8397-L8410 - Corresponding C source code: lnodelib.c#L8403-L8416
node.getproperty
function node.getproperty(node: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> value any
Each node also can have a properties table and you can get properties using the getproperty
function.
Example:
local n = node.new("glyph")
node.setproperty(n, "Some value")
assert.equals(node.getproperty(n), "Some value")
Reference:
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L2520-L2523 - Corresponding C source code: lnodelib.c#L8379-L8389
node.set_properties_mode
Enable managing properties in the node (de)allocator functions.
Managing properties in the node (de)allocator functions is disabled by default.
Reference:
- Corresponding C source code: lnodelib.c#L8351-L8360
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L2636-2683
node.flush_properties_table
Example:
local n = node.new("glyph")
node.setproperty(n, "Some properties")
assert.equals(node.get_properties_table()[n], "Some properties")
node.flush_properties_table()
assert.is_nil(node.get_properties_table()[n])
Reference:
- Corresponding C source code: lnodelib.c#L8364-L8375
😱 Types incomplete or incorrect? 🙏 Please contribute!
node.get_properties_table
Example:
local glyph1 = node.new("glyph")
node.setproperty(glyph1, "Properties of glyph 1")
local glyph2 = node.new("glyph")
node.setproperty(glyph2, "Properties of glyph 2")
assert.equals(node.get_properties_table()[glyph1], "Properties of glyph 1")
assert.equals(node.get_properties_table()[glyph2], "Properties of glyph 2")
Reference:
- Corresponding C source code: lnodelib.c#L8439-L8443
- Source file of the
LuaTeX
manual: luatex-nodes.tex#L2625-2626
node.fix_node_lists
Reference:
- Corresponding C source code: lnodelib.c#L366-L374
😱 Types incomplete or incorrect? 🙏 Please contribute!
node.hyphenating
function node.hyphenating(
n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
},
m: Node?
)
Reference:
- Corresponding C source code: lnodelib.c#L6104-L6122
node.make_extensible
function node.make_extensible(
fnt: integer,
chr: integer,
size: integer,
overlap: integer?,
horizontal: boolean?,
attlist: Node?
)
Reference:
- Corresponding C source code: lnodelib.c#L8842-L8868
node.subtypes
Example:
local subtypes = {}
for _, node_type in pairs(node.types()) do
local subtype = node.subtypes(node_type)
if subtype then
subtypes[node_type] = subtype
end
end
assert.same(subtypes, {
accent = {
"fixedtop",
"fixedbottom",
"fixedboth",
[0] = "bothflexible",
},
adjust = { "pre", [0] = "normal" },
boundary = { "user", "protrusion", "word", [0] = "cancel" },
dir = { "cancel", [0] = "normal" },
disc = {
"explicit",
"automatic",
"regular",
"first",
"second",
[0] = "discretionary",
},
fence = { "left", "middle", "right", "no", [0] = "unset" },
glue = {
"lineskip",
"baselineskip",
"parskip",
"abovedisplayskip",
"belowdisplayskip",
"abovedisplayshortskip",
"belowdisplayshortskip",
"leftskip",
"rightskip",
"topskip",
"splittopskip",
"tabskip",
"spaceskip",
"xspaceskip",
"parfillskip",
"mathskip",
"thinmuskip",
"medmuskip",
"thickmuskip",
[0] = "userskip",
[98] = "conditionalmathskip",
[99] = "muglue",
[100] = "leaders",
[101] = "cleaders",
[102] = "xleaders",
[103] = "gleaders",
},
glyph = {
"character",
"ligature",
[0] = "unset",
[4] = "ghost",
[8] = "left",
[16] = "right",
},
hlist = {
"line",
"box",
"indent",
"alignment",
"cell",
"equation",
"equationnumber",
"math",
"mathchar",
"hextensible",
"vextensible",
"hdelimiter",
"vdelimiter",
"overdelimiter",
"underdelimiter",
"numerator",
"denominator",
"limits",
"fraction",
"nucleus",
"sup",
"sub",
"degree",
"scripts",
"over",
"under",
"accent",
"radical",
[0] = "unknown",
},
kern = {
"userkern",
"accentkern",
"italiccorrection",
[0] = "fontkern",
},
math = { "endmath", [0] = "beginmath" },
noad = {
"opdisplaylimits",
"oplimits",
"opnolimits",
"bin",
"rel",
"open",
"close",
"punct",
"inner",
"under",
"over",
"vcenter",
[0] = "ord",
},
penalty = {
"linebreakpenalty",
"linepenalty",
"wordpenalty",
"finalpenalty",
"noadpenalty",
"beforedisplaypenalty",
"afterdisplaypenalty",
"equationnumberpenalty",
[0] = "userpenalty",
},
radical = {
"uradical",
"uroot",
"uunderdelimiter",
"uoverdelimiter",
"udelimiterunder",
"udelimiterover",
[0] = "radical",
},
rule = {
"box",
"image",
"empty",
"user",
"over",
"under",
"fraction",
"radical",
"outline",
[0] = "normal",
},
vlist = {
"line",
"box",
"indent",
"alignment",
"cell",
"equation",
"equationnumber",
"math",
"mathchar",
"hextensible",
"vextensible",
"hdelimiter",
"vdelimiter",
"overdelimiter",
"underdelimiter",
"numerator",
"denominator",
"limits",
"fraction",
"nucleus",
"sup",
"sub",
"degree",
"scripts",
"over",
"under",
"accent",
"radical",
[0] = "unknown",
},
})
Reference:
- Corresponding C source code: lnodelib.c#L3153-L3222
node.tostring
function node.tostring(n: Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}) -> string
@return - For example <node nil < 234 > nil : glyph 0>
😱 Types incomplete or incorrect? 🙏 Please contribute!
Example:
Reference:
- Corresponding C source code: lnodelib.c#L5913-L5918
@see node.direct.tostring
node.usedlist
function node.usedlist() -> n Node {
next = Node?,
prev = Node?,
id = integer,
subtype = integer,
head = Node?,
attr = Node,
}
Example:
Reference:
- Corresponding C source code: lnodelib.c#L6471-L6476
@see node.direct.usedlist
node.values
function node.values(type: ("dir"|"direction"|"glue"|"pdf_literal"|"pdf_action"|"pdf_window"|"color_stack"|"pagestate")) -> string[]?
Report some used values.
Valid arguments are dir
, direction
, glue
, pdf_literal
, pdf_action
, pdf_window
and color_stack
. Keep
in mind that the setters normally expect a number, but this helper gives you a
list of what numbers matter. For practical reason the pagestate
values
are also reported with this helper.
Example:
assert.same(
node.values("dir"),
{ [0] = "TLT", [1] = "TRT", [2] = "LTL", [3] = "RTT" }
)
assert.same(
node.values("direction"),
{ [0] = "TLT", [1] = "TRT", [2] = "LTL", [3] = "RTT" }
)
assert.same(
node.values("glue"),
{ [0] = "normal", [1] = "fi", [2] = "fil", [3] = "fill", [4] = "filll" }
)
assert.same(
node.values("pdf_literal"),
{
[0] = "origin",
[1] = "page",
[2] = "always",
[3] = "raw",
[4] = "text",
[5] = "font",
[6] = "special",
}
)
assert.same(
node.values("pdf_action"),
{ [0] = "page", [1] = "goto", [2] = "thread", [3] = "user" }
)
assert.same(
node.values("pdf_window"),
{ [0] = "unset", [1] = "new", [2] = "nonew" }
)
assert.same(
node.values("color_stack"),
{ [0] = "set", [1] = "push", [2] = "pop", [3] = "current" }
)
assert.same(
node.values("pagestate"),
{ [0] = "empty", [1] = "box_there", [2] = "inserts_only" }
)
Reference:
- Corresponding C source code: lnodelib.c#L3117-L3151
fields
node.direct
Deep down in TEX a node has a number which is a numeric entry in a memory table. In fact, this model, where TEX manages memory is real fast and one of the reasons why plugging in callbacks that operate on nodes is quite fast too. Each node gets a number that is in fact an index in the memory table and that number often is reported when you print node related information. You go from userdata nodes and there numeric references and back with:
The userdata model is rather robust as it is a virtual interface with some additional checking while the more direct access which uses the node numbers directly. However, even with userdata you can get into troubles when you free nodes that are no longer allocated or mess up lists. if you apply tostring to a node you see its internal (direct) number and id.
😱 Types incomplete or incorrect? 🙏 Please contribute!