TransWikia.com

Replace glyphs inside boxes using LuaTeX

TeX - LaTeX Asked by user220694 on August 30, 2021

I want to use a character replacement function from Lua in LuaTeX. The following is a first attempt and an adaptation from an example in chickenize, but it doesn’t work for content inside boxes in TeX logo nor ligatures. What is the right way to implement such a replacement?

documentclass{article}
usepackage{luacode}
begin{luacode*}
local glyph_id = node.id("glyph")
function everything_is_e(head)
    for n in node.traverse(head) do
        if n.id == glyph_id then
            n.char = 101
        end
    end
    return head
end

luatexbase.add_to_callback("pre_linebreak_filter",everything_is_e,"replace every character by e")
end{luacode*}
begin{document}
textbf{input knuth}
end{document}

I made the same question with an unregistered account and I cannot access to my original question anymore so I’m asking again.

2 Answers

Here is an approach using tokcycle to cycle through the tokens in the monotone pseudo-environment. Anything catcode 11 is replaced with e. Any numerical digit is replaced with 0. Code can be escaped with balanced |...| to avoid the above substitutions, such as begin{|equation|}, otherwise it gets transliterated as begin{eeeeeeee}. Macros and spaces are passed through untouched. Arguments to macros (i.e., groups) are processed through the transliterator.

Obviously, things like section numbers and equation numbers are untouched, because they do not appear as explicit glyphs in the LaTeX input.

In the MWE, I typeset a savebox early on and then use it later in the document. As can be seen, the transliteration is applied inside the box, as well.

documentclass{article}
usepackage{tokcycle}
tokcycleenvironmentmonotone
{tctestifcatnx A##1{addcytoks{e}}%
  {tctestifcatnx 0##1{tctestifnum{`##1>`/}{tctestifnum{`##1<`:}%
    {addcytoks{0}}{addcytoks{##1}}}%
    {addcytoks{##1}}}{addcytoks{##1}}}%
}
{processtoks{##1}}
{addcytoks{##1}}
{addcytoks{##1}}
newsaveboxmybox
begin{document}
monotone
section{This is section before #2}

saveboxmybox{Box content $1^{2^3}$}

This is a test 123 $y = mx_j^2$
begin{|equation|}
  E = mc^2
end{|equation|}
Back to textit{italic}, textbf{bold}, and textsc{Small Caps} text.

usebox{mybox}
endmonotone
end{document}

enter image description here

Answered by Steven B. Segletes on August 30, 2021

You approach was on the right track but you forgot to recursively descend into sublists. Another issue is that pre_linebreak_filter runs only after hyphenate and ligaturing have already been applied, so to replace characters before they are ligatured, you have to hook into ligaturing instead. To process display math material you additionally have to hook into mlist_to_hlist. Since we are not interested in the actual math list, but only the typeset result, we may also use the post_mlist_to_hlist_filter which only receives the resulting hlist.

documentclass{article}
usepackage{luacode}
begin{luacode*}
local glyph_id = node.id("glyph")
local hlist_id = node.id("hlist")
local vlist_id = node.id("vlist")
local function everything_is_e_impl(head)
    for n in node.traverse(head) do
        if n.id == hlist_id or n.id == vlist_id then
            everything_is_e_impl(n.list)
        elseif n.id == glyph_id then
            n.char = 101
        end
    end
    return head
end

local function everything_is_e(head)
    everything_is_e_impl(head)
    -- normally you'd do
    --
    --     return node.ligaturing(head)
    --
    -- but since everything is e, applying ligatures is a bit
    -- pointless.  It also allows us to reuse this callback in
    -- post_mlist_to_hlist_filter.
    return head
end 

luatexbase.add_to_callback("ligaturing", everything_is_e, "replace every character by e")
luatexbase.add_to_callback("post_mlist_to_hlist_filter", everything_is_e, "replace every character by e")
end{luacode*}
newsaveboxmybox
begin{document}
section{This is section before #2}

saveboxmybox{Box content $1^{2^3}$}

This is a test 123 $y = mx_j^2$
begin{equation}
  E = mc^2
end{equation}
Back to textit{italic}, textbf{bold}, and textsc{Small Caps} text.

usebox{mybox}
end{document}

Answered by Henri Menke on August 30, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP