6

Consider the following LaTeX document (to be compiled with 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}

Whether or not the add_to_callback line is commented out, the output appears to be the same, that is our overridden linebreak filter, which calls tex.linebreak, appears to do the same thing that TeX does by default.

However, when we try the same with plain TeX (to be compiled with 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

and use the linebreak filter (uncomment the commented line above), the result looks bad, between paragraphs:

Paragraphs run together

The paragraphs appear to overlap almost, and we need to set a higher \parskip to get “proper” results (of course they're not proper in the sense that they differ from the result without using the linebreak filter).

The issue is not with loading ltluatex in plain, as the result is the same with this:

\input plipsum
\directlua{
  function shouldbenoop(head, isDisplay)
    return tex.linebreak(head)
  end
}
\directlua{callback.register('linebreak_filter', shouldbenoop)}

\lipsum{1-20}
\bye

It also doesn't have anything to do with plipsum, as it is reproducible by simply typing out paragraphs without loading the package.

What is going on? And more importantly, what can we write as a linebreak_filter in plain TeX, that will perfectly reproduce the effect of the default line-breaking (that is, be identical to not having a linebreak_filter)?

  • you get no space before the following paragraph as \prevdepth has the magic "start of list" value of -1000pt instead of the depth of the last line of the previous paragraph, but why it has that isn't so clear.... – David Carlisle Nov 29 '17 at 23:41
  • in the latex case the output is not exactly identical. The paragraphs are more spaced out when the luatexbase.add_to_callback gets executed. – user4686 Nov 30 '17 at 7:34
  • with latex \lipsum[1-54] will take only 10 pages without the directlua but 11 pages with the last paragraph on page 11 when using the directlua. – user4686 Nov 30 '17 at 7:42
  • @jfbu I see, thanks. So the effect is opposite in LaTeX, which makes it harder to notice. Probably prevdepth gets set to a larger value than the correct one, in LaTeX. – ShreevatsaR Nov 30 '17 at 8:07
8

You need to reset (at least) \prevdepth something like this, otherwise \prevdepth gets the "start of list" value of -1000pt and the following paragraph is set with no space before it.

\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
  • Thanks! How come it works fine in LaTeX? – ShreevatsaR Nov 30 '17 at 0:00
  • @ShreevatsaR not sure (and it's getting late here so I decided to leave that for another day:-) – David Carlisle Nov 30 '17 at 0:31
  • @ShreevatsaR \prevdepth is 0pt after \begin{document} in LaTeX but -1000pt in plain. If I remember correctly you may have to set other env variables to integrate a paragraph correctly back (I think it is documented somwhere in the luatex manual) tex.linebreak really only does the breaking but not the full integration back into th galley. – Frank Mittelbach Nov 30 '17 at 8:40
  • @FrankMittelbach Thank you. I think that must be it. I couldn't find anything more about what to do after tex.linebreak in the LuaTeX manual, but the TUGboat article LuaTeX: What it takes to make a paragraph sets prevdepth and prevgraf after (essentially) calling tex.linebreak, so I guess those are the two additional steps needed. – ShreevatsaR Nov 30 '17 at 8:57
  • @ShreevatsaR you have think about tex.linebreak acting like \unvbox in vertical mode, that also doesn't set anything just appends its material – Frank Mittelbach Nov 30 '17 at 12:55
2

I am not deleting this for sentimental reasons, but from informed comment and comment and from the answer by @FrankMittlebach and @DavidCarlisle it is expected that \prevdepth (and \prevgraf) settings must be restored by the callback. I have not read the manual but it seems from that further comment by @ShreevatsaR that one needs to gather the information from other sources as well.


This is too long but is a comment: in the LaTeX case too, something is broken. Here is my test file:

\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}

The g g g in second paragraph cause the third to move down, when the \directlua is executed. The baselineskip glue computed by TeX should be 4.94pt but turns out to be 7pt (making the distance from bottom of g to next baseline exactly 7pt+5pt=12pt).

Here is a diff of the logs, cut down to the relevant things. At top of each portion the result with the \directlua executed, at bottom, with it commented out. Clearly the last paragraph is positioned lower in former case due to the descenders of letter g: TeX's mechanism is broken for maintaining a constant base line.

*** 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
***************

Image of output with \directlua executed:

enter image description here

The last paragraph is moved down.


And \the\prevdepth indeed produces 0.0pt in the lua filter case and 2.06pt without it. (the kind of things one expects as collateral damage from using a \special, like happens with using \color etc... but here the \showoutput does not show such a thing, so must be more in the innards of luatex).

  • as I note in my answer you need to set \prevdepth in the callback – David Carlisle Nov 30 '17 at 12:10
  • @DavidCarlisle as you know I am a no-ob in luatex; so if I get you right, this is documented expected fact that a callback must reset \prevdepth ? – user4686 Nov 30 '17 at 13:18
  • 2
    the luatex manual inherits some qualities of the texbook that once you know the answer you can convince yourself that the answer is there, just not quite where you'd expect:-) – David Carlisle Nov 30 '17 at 15:34
  • @DavidCarlisle abiding by authoritative tradition is indeed important :-) – user4686 Nov 30 '17 at 16:45

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.