You can perform a string substitution with Lua code using gsub (see this answer).
With \AtBeginDocument you can limit the scope of the function to the document. But is it also possible to have the function applied only to the text and not to commands, so that the following example would work?
% !TEX TS-program = lualatex
\documentclass{article}
\newcommand*{\dark}[1]{\textbf{#1}}
\usepackage{luacode}
\begin{luacode}
function replace_dark_with_bright ( s )
s = s:gsub ( "dark", "bright" )
return s
end
\end{luacode}
\AtBeginDocument{%
\directlua{luatexbase.add_to_callback (
"process_input_buffer", replace_dark_with_bright, "replace_dark_with_bright" )}}
\begin{document}
Always look on the dark side of life.
To \dark{emphasize} a word.
\end{document}
Is it possible to replace entire strings with other strings using the font feature functionality, or does it always have to be a single glyph in at least one direction (as with ligature and multiple)?
As a font feature substitution is only applied to the text (and not to commands), this would be a solution.
EDIT
To be more specific about what I am trying to do:
The idea is to use Lua string manipulations to implement automatic breaking of certain ligatures without affecting kerning or hyphenation points.
Such a type of solution, as exemplified in the following code, seems to work in principle:
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{fontspec}
\usepackage{luacode}
\begin{luacode}
fonts.handlers.otf.addfeature{
name = "ligkern",
type = "kern",
data = {
["f_f"] = { ["l"] = 50 },
["f"] = { ["l"] = 50 },
},
}
function lig_parse ( s )
function no_fl_lig ( text )
s = s:gsub ( text, text:gsub ( "fl", "fL" ) )
end
function keep_fl_lig ( text )
s = s:gsub ( text:gsub ( "fl", "fL" ), text )
end
local c = [===[\char]===]
local ffl = c .. "64260"
local fl = c .. "64258"
local ff = c .. "64256"
no_fl_lig ( "flich" )
keep_fl_lig ( "flicht" )
no_fl_lig ( "öpflicht" )
no_fl_lig ( "griffl" )
s = s:gsub ( "ffl", ffl )
s = s:gsub ( "fl", fl )
s = s:gsub ( "fL", "fl" )
s = s:gsub ( "ff", ff )
return s
end
\end{luacode}
\setmainfont{Latin Modern Roman}[
Ligatures = {NoCommon, NoDiscretionary},
RawFeature =+ ligkern
]
\AtBeginDocument{%
\directlua{luatexbase.add_to_callback
("process_input_buffer", lig_parse, "make and break ligatures")}%
}
\begin{document}
\noindent Die vortrefflichen Pflichten\
des begrifflosen Knoepfflers\
sind unerschöpflichtief.
\end{document}
However, if there is (for example) an \sffamily in the document, this, of course, causes an issue..
Of course, one could add such commands to the substitutions. But I think it would be a much cleaner solution if the substitutions were only applied to the text in the first place.


def\chickenize{ \directlua{luatexbase.add_to_callback("pre_linebreak_filter",chickenize,"chickenize")it is usingpre_linebreak_filterso working at the level of typeset character nodes notprocess_input_bufferwhich is working on the source text lines. – David Carlisle Mar 25 '22 at 08:27