考虑以下 LaTeX 文档(将用 进行编译lualatex
):
\documentclass{article}
\usepackage{lipsum}
\begin{document}
\directlua{
function shouldbenoop(head, isDisplay)
return tex.linebreak(head)
end
}
% \directlua{luatexbase.add_to_callback('linebreak_filter', shouldbenoop, 'This should be same as the default?')}
\lipsum
\end{document}
无论该行是否add_to_callback
被注释掉,输出似乎都相同,那就是我们覆盖的换行过滤器,它调用tex.linebreak
,似乎执行与 TeX 默认执行相同的操作。
然而,当我们尝试使用普通的 TeX (将用 进行编译luatex
) 进行相同操作时:
\input ltluatex % For luatexbase.add_to_callback
\input plipsum
\directlua{
function shouldbenoop(head, isDisplay)
return tex.linebreak(head)
end
}
% \directlua{luatexbase.add_to_callback('linebreak_filter', shouldbenoop, 'This should be same as the default?')}
\lipsum{1-20}
\bye
并使用换行符过滤器(取消注释上面的注释行),结果看起来很糟糕,之间段落:
这些段落看起来几乎重叠,我们需要设置更高的值\parskip
才能获得“正确”的结果(当然,它们并不正确,因为它们与不使用换行过滤器的结果不同)。
问题不在于ltluatex
纯文本加载,因为结果与此相同:
\input plipsum
\directlua{
function shouldbenoop(head, isDisplay)
return tex.linebreak(head)
end
}
\directlua{callback.register('linebreak_filter', shouldbenoop)}
\lipsum{1-20}
\bye
它也与没有任何关系plipsum
,因为只需输入段落而无需加载包即可重现它。
发生了什么事?更重要的是,我们可以linebreak_filter
在纯 TeX 中编写什么来完美重现默认换行的效果(即与没有 相同linebreak_filter
)?
答案1
您需要(至少)重置\prevdepth
类似这样的内容,否则\prevdepth
将获得 -1000pt 的“列表开始”值,并且下一段之前没有空格。
\directlua{
function shouldbenoop(head, isDisplay)
h,t =tex.linebreak(head)
tex.prevdepth= t.prevdepth
return h
end
}
\directlua{callback.register('linebreak_filter', shouldbenoop)}
\hsize3cm
\parindent0pt
g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g
\showthe\prevdepth
g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
\bye
答案2
我删除此帖并非出于感情原因,而是出于知情评论和评论并从回答@FrankMittlebach 和 @DavidCarlisle 预计\prevdepth
(并且\prevgraf
) 设置必须通过回调恢复。我没有阅读手册,但从那以后似乎评论@ShreevatsaR 表示,人们还需要从其他来源收集信息。
这太长了,但这是一条注释:在 LaTeX 的情况下,也出现了问题。这是我的测试文件:
\documentclass{article}
\begin{document}
\directlua{
function shouldbenoop(head, isDisplay)
return tex.linebreak(head)
end
}
%\directlua{luatexbase.add_to_callback('linebreak_filter', shouldbenoop, 'This should be same as the default?')}
\parskip 0pt
\def\x{\rule{2cm}{5pt} }
\def\y{\x\x\x\x}
\def\z{\y\y}
\z
\z g g g
\z
\thispagestyle{empty}
\showoutput
\end{document}
当执行时,第二段g g g
中的 导致第三段向下移动\directlua
。TeX 计算的基线跳粘应该是 4.94pt,但结果却是 7pt(使得 底部g
到下一个基线的距离正好是 7pt+5pt=12pt)。
这是日志的差异,已精简到相关内容。每个部分的顶部是\directlua
执行的结果,底部是注释掉的结果。显然,前一种情况下最后一段的位置较低,这是由于字母的下行线g
:TeX 维持恒定基线的机制已损坏。
*** 84,90 ****
...\hbox(0.0+0.0)x345.0, direction TLT
..\glue 25.0
..\glue(\lineskip) 0.0
! ..\vbox(550.0+0.0)x345.0, glue set 477.88895fil, direction TLT
...\write-{}
...\glue(\topskip) 5.0
...\hbox(5.0+0.0)x345.0, glue set - 1.0, direction TLT
--- 83,89 ----
...\hbox(0.0+0.0)x345.0, direction TLT
..\glue 25.0
..\glue(\lineskip) 0.0
! ..\vbox(550.0+0.0)x345.0, glue set 479.94873fil, direction TLT
...\write-{}
...\glue(\topskip) 5.0
...\hbox(5.0+0.0)x345.0, glue set - 1.0, direction TLT
***************
*** 168,174 ****
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue(\parskip) 0.0
! ...\glue(\baselineskip) 7.0
...\hbox(5.0+0.0)x345.0, glue set - 1.0, direction TLT
....\localpar
.....\localinterlinepenalty=0
--- 167,173 ----
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\glue(\parskip) 0.0
! ...\glue(\baselineskip) 4.94
...\hbox(5.0+0.0)x345.0, glue set - 1.0, direction TLT
....\localpar
.....\localinterlinepenalty=0
***************
执行后的输出图像\directlua
:
最后一段向下移动。
并且\the\prevdepth
确实0.0pt
在 lua 过滤器的情况下和2.06pt
没有它的情况下都会产生结果。(人们期望使用 会产生附带损害\special
,就像使用 等时发生的那样\color
……但这里的\showoutput
并没有显示这样的事情,所以一定更多地是在 luatex 的内部)。