4

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.

7
  • So what is your goal? To take LaTe input, leave macros and spaces intact, and replace every visible character with e? Or just (cat11) letters? – Steven B. Segletes Jul 18 '20 at 0:59
  • Yes. Replace everything by e or another character, wherever it be in the document. – user220694 Jul 18 '20 at 1:09
  • 1
    I want to solve it at glyph level, so macros are left intact, as you said. – user220694 Jul 18 '20 at 1:16
  • Your approach is correct but you have to recurse into sublists. – Henri Menke Jul 18 '20 at 1:20
  • @HenriMenke I added a loop over hlists and now TeX is replaced by "eee" with a funny lowered e but ligatures remain the same. Also \fboxes don't change. – user220694 Jul 18 '20 at 1:49
5

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*}
\newsavebox\mybox
\begin{document}
\section{This is section before \#2}

\savebox\mybox{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}
2

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}
\tokcycleenvironment\monotone
{\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}}
\newsavebox\mybox
\begin{document}
\monotone
\section{This is section before \#2}

\savebox\mybox{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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.