[luatex] Processing every letter in math
Henri Menke
henri at henrimenke.de
Tue Mar 15 20:03:30 CET 2022
On Tue, 2022-03-15 at 18:16 +0100, Javier Bezos wrote:
> How can I process every single letter in math? Processing
> glyph nodes in text is more or less trivial, and to some
> extent even in-line math (surrounded by 'math' type nodes),
> but processing math, including displays, sub/superscripts,
> fractions, radicals. etc.? From the manual I think the
> solution must be the node.mlist_to_hlist and the
> corresponding callback, and this is what I’ve achieved
> so far:
>
> -----------------------
> \directlua{
>
> function math_tweak(head, d, p)
> head = node.mlist_to_hlist(head, d, p)
> for item in node.traverse(head) do
> if item.id == node.id'glyph' then
> item.char = 88
> end
> end
> return head, d, p
> end
>
> callback.register('mlist_to_hlist', math_tweak)
>
> }
>
> $a$ ${b\over c}$ $\sqrt{d}$ $e$
>
> $$f$$
>
> \bye
> ------------------------
>
> Here, only ‘a’, ‘e’ and ‘f’ are converted to ‘X’ (= 88).
>
> With a branch for item.id == 0 calling recursively the
> function sub/superscripts are processed, but that’s not
> quite correct.
You want to process the nodes *before* converting the mlist to a hlist.
Once the conversion has been done there is lots of layouting stuff that
gets in the way of sensibly processing the formula. The mlist
representation is much more structured and easier to work with. But
also then you have to take care that you treat all nodes correctly and
descend into sublists:
\directlua{
local converters = {}
local function convert(n)
local id = n.id
local type = node.type(id)
local typeconv = converters[type]
if typeconv then
typeconv(n)
else
texio.write_nl("Warning: no conversion available for " .. type)
end
end
function converters.noad(n)
if not (n.nucleus.head or n.nucleus.char) then
% This is a thing, e.g. ${}$ is just an empty noad
return
end
convert(n.nucleus)
if n.sub then
convert(n.sub)
end
if n.sup then
convert(n.sup)
end
end
function converters.math_char(n)
n.char = utf8.codepoint("X")
end
function converters.sub_mlist(n)
for n in node.traverse(n.head) do
convert(n)
end
end
function converters.fraction(n)
convert(n.num)
convert(n.denom)
end
function converters.radical(n)
convert(n.nucleus)
if n.sub then
convert(n.sub)
end
if n.sup then
convert(n.sup)
end
end
function converters.accent(n)
convert(n.nucleus)
if n.accent then
convert(n.accent)
end
if n.bot_accent then
convert(n.bot_accent)
end
if n.sub then
convert(n.sub)
end
if n.sup then
convert(n.sup)
end
end
local function math_tweak(head, style,penalties)
for n in node.traverse(head) do
convert(n)
end
return node.mlist_to_hlist(head, style, penalties)
end
callback.register('mlist_to_hlist', math_tweak)
}
$a \left(b\right)$
$a$ ${b\over c}$ $\sqrt{d}$ $e$
$$\hat{f}$$
\bye
Cheers, Henri
>
> Javier
>
More information about the luatex
mailing list.