# LuaLaTeX: Find true height of multicols environment (series of vboxes) using node library

How to find the true height (and other dimensions) of contents of multicols environment in mini-page using LuaTeX node library? So far in my experiments with luatex node library, I have been able to use post_linebreak_filter to play with hlist nodes, but don't know how to access vlist nodes & query them. From the luatex manual, I see that one can query the dimensions of a node by using node.dimensions(<node> n). Though I don't know how to traverse the contents of the minipage to get to the vboxes output by the multicols environment. By traversing them I could potentially find the max height among the vboxes to determine true height.

It would be of additional help if someone can suggest if/how the nodelist visualization tool https://gist.github.com/pgundlach/556247 can be used to visualize the contents of minipage. (Note: Please excuse for external link, this seems to be a sort of standard visualization tool but is not available on ctan as a package)

Here's my test code, below that is the screenshot of output, and am looking forward to find the true dimensions of 3-column text which is different from the specified value size of minipage (4in) surrounding the multicols environment.

% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}

\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}

\begin{document}

\blindtext[1]\vspace{\baselineskip}

\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
% ENDPOINT for dimension measurement
\end{minipage}

\blindtext[1]

\end{document}


• viznodelist.lua is available as a package (with some extensions): ctan.org/pkg/nodetree Sep 9 '20 at 21:30
• It really depends what you need the dimensions of the multicols for. If it's just for tracing consider using \usepackage[debugshow]{multicol}. This will print info about column balancing to the log. Sep 9 '20 at 21:38
• @HenriMenke Thanks for pointing to nodetree package. A minor correction, nodetree is not viznodelist.lua available as ctan package, its "inspired" by it according to the documentation. The output format is different, but looks like it should do the job Sep 10 '20 at 6:57

Before discussing the node library, the much easier way to do such measurements is by just comparing the position on the page before and after:

% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}

\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}

\begin{document}
\showoutput

\blindtext[1]\vspace{\baselineskip}

\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\latelua{
assert(measurement_y == nil, "global variable already in use")
measurement_y = pdf.getvpos()
}%
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
\latelua{
texio.write_nl(string.format("\csstring\%fin measured\string\n", (measurement_y - pdf.getvpos()) / tex.sp'1in'))
measurement_y = nil
}%
% ENDPOINT for dimension measurement
\end{minipage}

\blindtext[1]

\end{document}


If you want to use the node library, I would suggest using tex.nest.top.tail to access the last node TeX inserted before some Lua command. This can be used as a start point to scan back until you find the node you are looking for. For example: (Here we are measuring the hlist containing all three vlists, this does correspond to the height of the maximal vlist.)

% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}

\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}

\begin{document}
\showoutput

\blindtext[1]\vspace{\baselineskip}

\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
\directlua{
local hlist_id = node.id'hlist' % The id we are looking for
local last_tail = tex.nest.top.tail % Start at the end of the list TeX is working on
while last_tail.id \string~= hlist_id do last_tail = last_tail.prev end % Move to the previous node until a hlist is found
texio.write_nl(string.format("\csstring\%fin measured\string\n", (last_tail.height+last_tail.depth) / tex.sp'1in'))}%
% ENDPOINT for dimension measurement
\end{minipage}

\blindtext[1]

\end{document}


From here, you can also use the .head member of the hlist to access the vlists hidden therein:

% lualatex vboxdimensions.tex
\documentclass[notitlepage,letterpaper]{article}

\usepackage{lua-visual-debug}
\usepackage[english]{babel}
\usepackage{blindtext}
\usepackage{multicol}

\begin{document}
\showoutput

\blindtext[1]\vspace{\baselineskip}

\noindent\begin{minipage}[t][4in][t]{\textwidth}%
% STARTPOINT for dimension measurement
\begin{multicols}{3}%
\blindtext[2]
\end{multicols}%
\directlua{
local hlist_id = node.id'hlist' % The id we are looking for
local last_tail = tex.nest.top.tail % Start at the end of the list TeX is working on
while last_tail.id \string~= hlist_id do last_tail = last_tail.prev end % Move to the previous node until a hlist is found
% Now last_tail is the hlist containing the vlists.
for n in node.traverse_id(node.id'vlist', last_tail.head) do
% Now n is one of the inner vlists.
texio.write_nl(string.format("Found column of height \csstring\%fin.",(n.height+n.depth)/tex.sp'1in'))
end}%
% ENDPOINT for dimension measurement
\end{minipage}

\blindtext[1]

\end{document}


You might notice that especially the first version gives a higher value. The reason for this is that multicols inserts some spacing which is included when using points and getvpos, but not included when looking at raw boxes.

• Thanks Marcel! I wish there were a small section in luatex manual that explains this tex.nest and when/where/how it could be used. The little information I found about tex.nest` isn't that clear to decipher what it is for. Sep 10 '20 at 5:23