Difference between revisions of "T wo T r:utils.lua"
From LuaTeXWiki
(Created page with " <nowiki> --- Copyright (c) 2021 by Toadstone Enterprises. --- ISC-type license, see License.txt for details. -------------------------------------------------------------...") |
(No difference)
|
Latest revision as of 18:30, 22 February 2021
--- Copyright (c) 2021 by Toadstone Enterprises.
--- ISC-type license, see License.txt for details.
-----------------------------------------------------------------
local reader = require("reader")
local read_value = reader.read_value
-----------------------------------------------------------------
local sp_to_p = function(sp)
-- Convert scaled points to points.
return sp/65536
end
local sp_to_in = function(sp)
-- Convert scaled points to inches.
return sp_to_p(sp)/72.27
end
local node_type = function(x)
-- Return the type of a node as a string.
return node.types()[x.id]
end
local node_subtype = function(x)
-- Return the subtype of a node as a string.
local type = node_type(x)
return node.subtypes(type)[x.subtype]
end
local link_nodes = function(...)
-- Link the nodes, setting both the next and prev fields.
local arg = {...}
for i = 1, (#arg - 1) do
arg[i].next = arg[i+1]
arg[i+1].prev = arg[i]
end
end
local make_glyph = function(value, fnt, lang, lefthyphenmin, righthyphenmin)
local n = node.new("glyph")
n.font = fnt or font.current()
n.subtype = 1
n.char = value
n.lang = lang or tex.language
n.uchyph = 1
n.left = lefthyphenmin or tex.lefthyphenmin
n.right = righthyphenmin or tex.righthyphenmin
return n
end
local make_glue = function(subtype,
width,
stretch, shrink,
stretch_order, shrink_order)
local n = node.new("glue", subtype)
node.setglue(n, width or 0,
stretch or 0,
shrink or 0,
stretch_order or 0,
shrink_order or 0)
return n
end
local make_glue_spec = function(width,
stretch, shrink,
stretch_order, shrink_order)
local n = node.new("glue_spec")
n.width = width or 0
n.stretch = stretch or 0
n.shrink = shrink or 0
n.stretch_order = stretch_order or 0
n.shrink_order = shrink_order or 0
return n
end
local make_rule = function(subtype, width, height, depth, dir)
local n = node.new("rule", subtype or 0)
n.width = width or 0
n.height = height or 0
n.depth = depth or 0
n.dir = dir or "TLT"
return n
end
local make_penalty = function(penalty)
local n = node.new("penalty")
n.penalty = penalty
return n
end
local fil = function()
-- Return a "fil" glue_spec.
return make_glue_spec(0, tex.sp("1pt"), 0, 1, 0)
end
local fill = function()
-- Return a "fill" glue_spec.
return make_glue_spec(0, tex.sp("1pt"), 0, 2, 0)
end
local filll = function()
-- Return a "filll" glue_spec.
return make_glue_spec(0, tex.sp("1pt"), 0, 3, 0)
end
-----------------------------------------------------------------
local read_string = function()
-- We return a regular (not exploded or anything) string.
local ans = ""
local value = read_value()
-- Should we be eat any white space before the string?
while is_whitespace(value) do
value = read_value()
end
if ((value ~= unicode.utf8.byte('"')) and
(value ~= unicode.utf8.byte("'"))) then
error("Not a string. No opening quoteation mark.")
end
-- So we can look only for the matching quote
local delimiter = value
value = read_value()
while (value and (value ~= delimiter)) do
-- We want to return a regular string.
ans = ans .. unicode.utf8.char(value)
value = read_value()
end
if (not value) then -- eof
error("Not a string. No closing quotation mark.")
end
return ans
end
local read_group = function(eat_the_white)
-- We read a group, (delimited by matching "{", "}" or "[", "]")
-- possibly eating any white space within the group.
-- We return a regular (not exploded or anything) string.
local ans = ""
local value = read_value()
-- Should we eat any white space before the group?
while is_whitespace(value) do
value = read_value()
end
-- So we can look only for the matching delimiter
local delimiter
if (value == unicode.utf8.byte("{")) then
delimiter = unicode.utf8.byte("}")
elseif (value == unicode.utf8.byte("[")) then
delimiter = unicode.utf8.byte("]")
else
error("Not a group. No opening group delimiter.")
end
value = read_value()
while (value and (value ~= delimiter)) do
if ((not eat_the_white) or (not is_whitespace(value))) then
ans = ans .. unicode.utf8.char(value)
end
value = read_value()
end
if (not value) then -- eof
error("Not a group. No closing group delimiter.")
end
return ans
end
local read_line = function()
-- Read to the end of the current line (and throw away the result).
local value = read_value()
while (not is_linefeed(value)) do
value = read_value()
end
end
-----------------------------------------------------------------
local copy_table = function(tbl)
-- Make a deep copy of the table.
-- We do not copy the keys.
local result = {}
if type(tbl) == "table" then
for k,v in pairs(tbl) do
result[k] = copy_table(v)
end
else
result = tbl
end
return result
end
-----------------------------------------------------------------
--- Character categories
local whitespace = {[0x0009] = true, -- Tab
[0x000A] = true, -- LF -- Line Break
[0x000B] = true, -- Line Tab -- Line Break
[0x000C] = true, -- Form Feed -- Line Break
[0x000D] = true, -- CR -- Line Break
[0x0020] = true, -- Space
[0x0085] = true, -- Next Line -- Line Break
[0x00A0] = true, -- NB Space -- No Break
[0x1680] = true, -- Ogham Space Mark
[0x2000] = true, -- EN Quad
[0x2001] = true, -- EM Quad
[0x2002] = true, -- EN Space
[0x2003] = true, -- EM Space
[0x2004] = true, -- Three per EM Space
[0x2005] = true, -- Four per EM Space
[0x2006] = true, -- Six per Em Space
[0x2007] = true, -- Figure Space -- No Break
[0x2008] = true, -- Punctuation Space
[0x2009] = true, -- Thin Space
[0x200A] = true, -- Hair Space
[0x2028] = true, -- Line Separator -- Line Break
[0x2029] = true, -- Paragraph Separator -- Line Break
[0x202F] = true, -- Narrow NB Space -- No Break
[0x205F] = true, -- Medium Mathematical Space
[0x3000] = true -- Ideographic Space
}
local is_whitespace = function(value)
return whitespace[value]
end
local linefeed = {[0x000A] = true, -- LF -- Line Break
[0x000B] = true, -- Line Tab -- Line Break
[0x000C] = true, -- Form Feed -- Line Break
[0x000D] = true, -- CR -- Line Break
[0x0085] = true, -- Next Line -- Line Break
[0x2028] = true, -- Line Separator -- Line Break
[0x2029] = true -- Paragraph Separator -- Line Break
}
local is_linefeed = function(value)
return linefeed[value]
end
local nobreak = {[0x00A0] = true, -- NB Space -- No Break
[0x2007] = true, -- Figure Space -- No Break
[0x202F] = true, -- Narrow NB Space -- No Break
}
local is_nobreak = function(value)
return nobreak[value]
end
local command_terminator = {[unicode.utf8.byte("{")] = true,
[unicode.utf8.byte("[")] = true,
-- But we want to terminate on
-- whitespace in general
-- [unicode.utf8.byte(" ")] = true
}
local is_command_terminator = function(value)
return (command_terminator[value] or is_whitespace(value))
end
-----------------------------------------------------------------
--- Functions for exploring the state of nodes and tables.
--- With this schema, if you are in the REPL and discover that
--- a node you wish to show is not yet supported, for a node of
--- type xxx, define a function (in the REPL):
--- util.show_node_functions.show_xxx_node(n)
--- If you can't remember the correct name of the table,
--- walk_table(util)
--- will remind you.
local show_node_functions = {}
show_node_functions.show_hlist_node = function(n)
local id = node_type(n)
local subtype = node.subtypes(tostring(id))[n.subtype]
print("id: " .. id)
print("subtype: " .. subtype)
print("width: " .. sp_to_in(n.width) .. "in")
print("height: " .. sp_to_p(n.height) .. "p")
print("depth: " .. sp_to_p(n.depth) .. "p")
print()
end
show_node_functions.show_vlist_node = function(n)
local id = node_type(n)
local subtype = node_subtype(n)
print("id: " .. id)
print("subtype: " .. subtype)
print("width: " .. sp_to_in(n.width) .. "in")
print("height: " .. sp_to_in(n.height) .. "in")
print("depth: " .. sp_to_in(n.depth) .. "in")
print()
end
show_node_functions.show_glyph_node = function(n)
local id = node_type(n)
local subtype = node_subtype(n)
print("id: " .. id)
-- sometimes a glyph node will not have a subtype?
if subtype then print("subtype: " .. subtype) end
print("char: " .. unicode.utf8.char(n.char))
print("font: " .. n.font)
print("lang: " .. n.lang)
print()
end
show_node_functions.show_glue_node = function(n)
local id = node_type(n)
local subtype = node_subtype(n)
print("id: " .. id)
print("subtype: " .. subtype)
print("width: " .. sp_to_p(n.width) .. "p")
print("stretch: " .. sp_to_p(n.stretch) .. "p")
print("shrink: " .. sp_to_p(n.stretch) .. "p")
print()
end
show_node_functions.show_disc_node = function(n)
local id = node_type(n)
local subtype = node_subtype(n)
print("id: " .. id)
print("subtype: " .. subtype)
-- pre
-- post
-- repl
print()
end
show_node_functions.show_penalty_node = function(n)
local id = node_type(n)
local subtype = node_subtype(n)
print("id: " .. id)
print("subtype: " .. subtype)
print("penalty: " .. n.penalty)
print()
end
show_node_functions.show_kern_node = function(n)
local id = node_type(n)
local subtype = node_subtype(n)
print("id: " .. id)
print("subtype: " .. subtype)
print("kern: " .. sp_to_p(n.kern) .. "p")
print("expansion_factor: " .. n.expansion_factor)
print()
end
show_node_functions.show_rule_node = function(n)
local id = node_type(n)
local subtype = node_subtype(n)
print("id: " .. id)
print("subtype: " .. subtype)
print("width: " .. sp_to_in(n.width) .. "in")
print("height: " .. sp_to_p(n.height) .. "p")
print("depth: " .. sp_to_p(n.depth) .. "p")
print("dir: " .. n.dir)
print()
end
local show_node = function(n)
local id = node_type(n)
local show_function_name = "show_" .. id .. "_node"
local show_function = show_node_functions[show_function_name]
if show_function then
show_function(n)
else
print("I don't know how to show a " .. id .. " node.")
print()
end
end
local walk_list = function(l)
-- Walk down a list of nodes, showing them as we go.
for n in node.traverse(l) do
show_node(n)
end
end
local walk_table = function(t)
-- Walk through a table, showing the key/value pairs.
local k, v
for k,v in pairs(t) do
print(k,v)
end
end
util = {
sp_to_p = sp_to_p,
sp_to_in = sp_to_in,
node_type = node_type,
node_subtype = node_subtype,
link_nodes = link_nodes,
make_glyph = make_glyph,
make_glue = make_glue,
make_glue_spec = make_glue_spec,
make_rule = make_rule,
make_penalty = make_penalty,
fil = fil,
fill = fill,
filll = filll,
read_string = read_string,
read_group = read_group,
read_line = read_line,
copy_table = copy_table,
is_whitespace = is_whitespace,
is_linefeed = is_linefeed,
is_nobreak = is_nobreak,
is_command_terminator = is_command_terminator,
show_node = show_node,
walk_list = walk_list,
walk_table = walk_table,
}
return util