<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.luatex.org/index.php?action=history&amp;feed=atom&amp;title=T_wo_T_r%3Autils.lua</id>
	<title>T wo T r:utils.lua - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.luatex.org/index.php?action=history&amp;feed=atom&amp;title=T_wo_T_r%3Autils.lua"/>
	<link rel="alternate" type="text/html" href="https://wiki.luatex.org/index.php?title=T_wo_T_r:utils.lua&amp;action=history"/>
	<updated>2026-05-31T15:12:28Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.31.1</generator>
	<entry>
		<id>https://wiki.luatex.org/index.php?title=T_wo_T_r:utils.lua&amp;diff=3558&amp;oldid=prev</id>
		<title>Rkrug: Created page with &quot; &lt;nowiki&gt;   --- Copyright (c) 2021 by Toadstone Enterprises. --- ISC-type license, see License.txt for details.   -------------------------------------------------------------...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.luatex.org/index.php?title=T_wo_T_r:utils.lua&amp;diff=3558&amp;oldid=prev"/>
		<updated>2021-02-22T18:30:10Z</updated>

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