在这个问题几周前,我在 TeX Stack Exchange 上发布了一篇文章,其中我询问了如何自动禁用预定义单词列表中的特定连字符(例如ff
、fi
、fl
和ffl
)。我收到的答案基于 ConTeXt,它可以直接访问 lua(tex) 命令。特别是,@Aditya 提出的代码包括命令
\usemodule[translate]
\translateinput[halflife][half|*|life]
ConTeXt 命令\usemodule
类似于 LaTeX 命令\usepackage
。模块\translateinput
提供的命令translate
(包含在文件中m-translate.mkiv
)依赖于lua
函数resolvers.openers.helpers.textlineactions
,该函数挂接到用于读取文件的函数中luatex
。据@Aditya 所述,
没有人为 编写过类似的功能
lualatex
。也许,你可以将其作为一个单独的问题提出,其中一位lualatex
专家将能够回答并提供解决方案。
那么,我的问题是:有人可以提供lualatex
以下 ConTeXt 代码的等效内容吗(这可能涉及重写/调整模块translate
)lualatex
:
\usemodule[translate]
\translateinput[shelfful][shelf|*|ful]
\translateinput[selfish][self|*|ish]
\translateinput[halflife][half|*|life]
\translateinput[cufflink][cuff|*|link]
\definetextmodediscretionary * {\prewordbreak\discretionary{-}{}%
{\kern0.0pt}\prewordbreak}
\starttext
Ligatures not disabled:\\
shelfful selfish halflife cufflink
\medskip
\enableinputtranslation
Ligatures disabled:\\
shelfful selfish halflife cufflink
\stoptext
(请注意,虽然 0 字距分隔符似乎适合使用 CM 排版的单词 shelfful 和 selfish,但它并不完全适合和f-l
连ff-l
字。不过,我将如何定义允许对各种连字字母组合使用不同字距调整量的命令的问题留待以后再研究……)
答案1
这更像是一个概念验证,而不是真正的防弹风格文件,但它可以满足您的要求:
样式文件 ( filterltx.sty
)
\ProvidesPackage{filterltx}
\RequirePackage{luatexbase,luacode}
\begin{luacode*}
do
local replace = {}
local filter = function ( buf )
local start,stop,init,pos
local positions = {}
for k,v in pairs(replace) do
local init = 1
repeat
start,stop = string.find(string.lower(buf),k,init,true)
if start then
init = stop
pos = string.find(v,"|*|",1,plain)
positions[#positions + 1] = pos + start - 2
end
until start == nil
end
table.sort(positions)
for i = #positions,1,-1 do
buf = string.sub(buf,1,positions[i] ) .. [[\penalty10000\discretionary{-}{}{\kern.03em}\nobreak \hskip 0pt plus0pt minus0pt]] .. string.sub(buf, positions[i] + 1)
end
return buf
end
function enablefilter()
luatexbase.add_to_callback('process_input_buffer', filter, 'filter')
end
function disablefilter()
luatexbase.remove_from_callback('process_input_buffer', 'filter')
end
function translateinput( arg1,arg2 )
replace[arg1] = arg2
end
end
\end{luacode*}
\newcommand\enableinputtranslation{
\directlua{enablefilter()}
}
\newcommand\disableinputtranslation{
\directlua{disablefilter()}
}
\newcommand\translateinput[2]{
\directlua{translateinput("\luatexluaescapestring{#1}","\luatexluaescapestring{#2}")}
}
以及测试文档(test.tex
):
\documentclass{article}
\usepackage{filterltx}
\translateinput{shelfful}{shelf|*|ful}
\translateinput{selfish}{self|*|ish}
\translateinput{halflife}{half|*|life}
\translateinput{cufflink}{cuff|*|link}
\begin{document}
Ligatures not disabled:\\
shelfful selfish halflife cufflink
\medskip
\enableinputtranslation
Ligatures disabled:\\
shelfful selfish halflife cufflink\\
Shelfful Selfish Halflife Cufflink
\medskip
\disableinputtranslation
Ligatures not disabled:\\
shelfful selfish halflife cufflink
% to make sure the words still hyphenate:
% \showhyphens{shelfful selfish halflife cufflink}
% yields: shelf- ful self- ish half- life cuff- link
\end{document}
用 运行lualatex test
。
输出:
答案2
基本功能是 luatex 的一部分。例如,以下代码(luatex 纯格式)将“hello”更改为“hi”。
\directlua{
local gsub = string.gsub
local function translate(line)
return gsub(line, "hello", "hi")
end
callback.register("process_input_buffer", translate)
}
hello world
why say hello
\bye
ConTeXt 代码只是提供了语法糖,以便您可以轻松地定义多个翻译。我尝试将此代码翻译为,lualatex
但在 lualatex 中我收到错误
uatexbase-mcb error: function callback.register has been trapped,
(luatexbase-mcb) please use luatexbase.add_to_callback instead.
stack traceback:
[C]: in function 'error'
.../share/texmf-dist/tex/luatex/luatexbase/modutils.lua:26: in function 'modul
e_error_int'
.../share/texmf-dist/tex/luatex/luatexbase/modutils.lua:45: in function 'err'
/usr/share/texmf-dist/tex/luatex/luatexbase/mcb.lua:85: in function 'register'
<\directlua >:7: in main chunk.
\luacode@execute ...oup \luatexbase@directlua {#1}
l.11 \end{luacode}
但我无法让代码正常工作luatexbase.add_to_callback
。
上面的纯 TeX 代码显示基本功能是 luatex 的一部分,并且lualatex
也应该可以轻松访问(一旦您弄清楚了luacode
包所做的适当重命名)。