# Find the line number inside a vbox (at end of paragraph), and change the behavior of a macro that follows next

Edit: I have added a luatex solution as an answer to my question.

I have a \vbox in which I plan to typeset long material (long poetry), the way it is typeset is slightly unique. There is a special highlight macro that puts 3 red colored asterisks at the end of some special stanzas (which end with \par). Though if the end of a special stanza (each stanza can be different number of lines) falls at a multiple of some number (lets say 100) from the top of the poetry then we do something different (like add extra line break, or some other marker like a colored rule) instead of putting these asterisks.

The way I imagine this could work is if I can find, and pass the line number of the last line of previous paragraph to my macro that prints special marker. I have not come across any macro to know the line number within the text about to be typeset. From my fringe understanding of tex, given tex engine puts lines of paragraph on the vertical list at the end of processing a paragraph, it seems like there would be a way to know this at the beginning of next paragraph? Ideally I would like plain tex solution. If that is impossible to achieve in plain tex, then luatex solution based on line-break-filter would be great (assuming from the name it won't re-typeset the entire \vbox again?)

Corollary-1: I guess in plain tex it is not possible to get line number of the line within the paragraph while the paragraph is being typeset, though is it possible using luatex's line break filter? If it is possible in luatex, then for luatex solution it would be nice to just have a macro that works on any line, not just to know the line number of the last line of previous paragraph.

% Macro that returns line number from top of vbox
\currentlineno

% Macro that consumes this line number
\myspecialasterisk{\currentlineno} % I can write this, am looking for the definition of \currentlineno

• Plain TeX has an internal integer called \prevgraf that contains the number of lines that a paragraph contains at the end of this paragraph. So you can add up the line numbers that a text of several paragraphs has. – Udo Wermuth Apr 14 '20 at 7:24
• If they are poetry stanzas, the lines of input should match the typeset lines, so it is easy with \obeylines and a line counter. – Donald Arseneau Apr 14 '20 at 7:44
• If they really are paragraphs, typeset the text twice, using both definitions. Post-process the dual vbox contents using \lastbox or \vsplit and choose content from each list based on the line count then. – Donald Arseneau Apr 14 '20 at 7:47
• @DonaldArseneau It's not just plain poetry, lets assume there can be more than that. I just took example of poetry. When would \obeylines fail? Like what content in \vbox would mess up the count? Also in this example yes typesetting twice would not be performance issue, though I would prefer a generic solution as I think knowledge of line number can help in doing things dynamically. – reportaman Apr 14 '20 at 7:48

I don't say that it is full solution of your question, but you can start with experimenting wit this code:

\newcount\globlines

\hsize=10cm
\def\text{fghs sdsdvjd gdj dhad dhd fda dfgdfd dhd dfshk sdhsds
fghs sdsdvjd gdj dhad dhd fda dfgdfd dhd dfshk sdhsds
fghs sdsdvjd gdj dhad dhd fda dfgdfd dhd dfshk sdhsds}

\text \par \text \par
\showlines
\text \par \text \par \text\text \par
\showlines

\bye

• It doesn't work with your paragraph shaping solution, I tried all possible changes to \formatchunks that I could do think of in tex.stackexchange.com/questions/519768/… It works when I have just plain text broken across paragraphs in a \vbox. Also, it would be nice if you could give an example where things could fail with this (are you thinking of some command that redefines par?). I wonder why is there no generic solution for seemingly simple data from tex. – reportaman Apr 14 '20 at 10:23
• Two macros cannot re-define \par simultaneously, each for different reason. Use \globpar from \formatchunks macro and define \def\showlines{\vskip-\baselineskip \llap{\the\globpar\qquad}}. No generic solution does not exists because TeX is old. We need newer system with completely new concept (inspired by good concepts from TeX). But nobody is able to do it. – wipet Apr 14 '20 at 10:38
• Thanks I did some experiment, it works till the point width is specified for text using \declchunk, but the count stops incrementing from the last paragraph onwards where last \declchunk applies. The number of lines in my vbox \allchunks are more than first n lines I shape using \declchunk. As a side note I am using the \allchunks generated by formatchunks splitting it directly, so we need not worry about \getnextchunk working beyond the last point of \declchunk. Also, we need not worry about vbox appends, I think that would be easy for me to do if I serially process vboxes. – reportaman Apr 14 '20 at 19:49

Here's my luatex solution that seems to work in all of my testing.

% Post line break filter to find number of lines from a startpoint
\directlua{
% Global linecount, usage:
%     Set linecount to a start value at whatever place you want to start counting lines from (like beginning of \vbox):
%         \directlua{linecount=0}
%     Get value within luatexcode (linecount valid only after \par, gets updated upon every new \par, till then it holds previous value)
%         \directlua{tex.sprint(linecount)}
linecount=0 % global variable (change name if you think there can be conflict with other lualatex packages)
local HLIST = node.id("hlist") % node.id for a line of text in vertical list
for n in node.traverse(head) do % For every subnode within node head
if n.id==HLIST then % If n is a line, increment linecount
linecount=linecount+1
end
end