# How can I detect when I'm at the top of column?

I have a series of text blocks in a 2-column layout, using multicol. Each block of text is wrapped in a minipage environment to ensure that all the contained text appears in the same column. I would like to separate these minipages with a horizontal rule or other decoration, but I don't want the rule to appear if it's at the top of a column.

Clearly, I could add a parameter that would manually suppress the rule, but I'm looking for a way to detect the situation automatically and format appropriately. For the MWE below, that means the line should only appear between the final two paragraphs.

\documentclass{article}
\usepackage{multicol}
\usepackage{lipsum}

\newenvironment{segmented}{%
\begin{minipage}{\linewidth}
\hrule\bigskip
}{\bigskip
\end{minipage}}

\begin{document}
\begin{multicols}{2}
\begin{segmented}
\lipsum[1]
\end{segmented}
\begin{segmented}
\lipsum[2]
\end{segmented}
\begin{segmented}
\lipsum[3]
\end{segmented}
\end{multicols}
\end{document}

• Detection might not be easy; see Detecting current column in multicol.
– Werner
Dec 9 '17 at 1:54
• @Werner, The underlying detection certainly isn't easy, but the basic problem already seems solved in that link and folded into multicol, so thanks for pointing it out. I've put an answer below that builds on \docolaction Dec 9 '17 at 4:00

Is it what you'd like to get?

\documentclass{article}
\usepackage[latin]{babel}% for avoiding too many underfull boxes
\usepackage{multicol}
\usepackage{lipsum}

\newenvironment{segmented}
{%
\noindent\begin{minipage}{\linewidth}
}
{%
\end{minipage}\par
\bigskip
\bigskip
}

\begin{document}

\begin{multicols}{2}
\begin{segmented}
\lipsum[1]
\end{segmented}
\begin{segmented}
\lipsum[2]
\end{segmented}
\begin{segmented}
\lipsum[3]
\end{segmented}
\end{multicols}

\end{document}


• That's exactly the result I'm looking for. Can you confirm or correct my understanding of how this works? \cleaders is a TeX command that repeats the \vbox enough times to fit within \vskip0.4pt, which means that the rule won't appear at the bottom of a column, as the \vskip becomes 0 there. Dec 9 '17 at 16:29
• @KarlHagen Since the rule is 0.4pt high, there will be just one; but leaders are like glue, so they disappears at page/column breaks Dec 9 '17 at 16:34
• ah just see that @egreg did kind of the same while I was collecting screenshots. Dec 9 '17 at 16:56

There's probably a better way to do this, but @Werner's link gave me this idea. It relies on the colaction feature of multicol:

\documentclass{article}
\usepackage[colaction]{multicol}
\usepackage{etoolbox}
\usepackage{lipsum}

\numdef{\columnnumber}{0}
\newcommand{\conditionalrule}[1]{
\ifnumequal{#1}{\columnnumber}{\hrule}{}
\global\numdef{\columnnumber}{#1}
}

\newenvironment{segmented}{%
\noindent\begin{minipage}{\linewidth}
\docolaction{\conditionalrule{1}}{}{\conditionalrule{2}}\bigskip
}{\bigskip
\end{minipage}}

\begin{document}
\begin{multicols}{2}
\begin{segmented}
\lipsum[1]
\end{segmented}
\begin{segmented}
\lipsum[2]
\end{segmented}
\begin{segmented}
\lipsum[3]
\end{segmented}
\end{multicols}
\end{document}


If anyone has a more elegant/efficient solution, I'd be happy to accept their answer, so I'm holding off on accepting my own answer for a little while.

• I hope you don't mind, I added an example output image to better demonstrate what your code does. Feel free to roll back the edit if you so wish.
– Troy
Dec 9 '17 at 8:19

You can let TeX determine the position (which works within or outside multicol):

\documentclass[]{article}
\usepackage{multicol,lipsum}

\usepackage{xparse}

\ExplSyntaxOn

\dim_new:N \l__condline_dim
\box_new:N \l__condline_box

% #1 skip produced
% #2 vertical correction of material
% #3 material
% #4 break penalty after (if forbidden the only place to break is before

\cs_new:Npn \condline:nn #1#2#3#4
{
\par
\hbox_set_to_wd:Nnn \l__condline_box \columnwidth {\hfil #3 \hfil}
%
\dim_set:Nn \l__condline_dim
{ \box_ht:N \l__condline_box +
\box_dp:N \l__condline_box }
%
\skip_vertical:n { #1 / 2 - \prevdepth + #2 - \l__condline_dim / 2 }
\nobreak
%
\nobreak
%
\skip_vertical:n { #1 / 2 - \parskip  - #2 - \l__condline_dim / 2 }
\penalty #4 \relax
%
\dim_set:Nn \prevdepth { 0pt }
}

% document level command
%
% \condline * < correction > [ skip ] { material }
%
% all arguments optional

\DeclareDocumentCommand\condline
{ s  D<>{3pt} O{\baselineskip} G{$*\quad*\quad*$} }
{ \IfBooleanTF #1
{ \condline:nn {#3} {#2} {#4} {10000} }
{ \condline:nn {#3} {#2} {#4} {0} }
}

\ExplSyntaxOff

\begin{document}
\begin{multicols}{3}
\lipsum[1]
\condline{...........}
line1\\  line2\\  line3\\  line4\\ line5\\
and the stars below will vanish!\\
% line9\\  line10\\
LAST LAST LAST
\condline{$* \quad * \quad *$}
\lipsum[2]
\end{multicols}

\condline<-5pt>{\hrulefill}

\begin{multicols}{2}
\lipsum[3]
\condline{\hrulefill}
\lipsum[4]
\condline[2\baselineskip]{---With star this line would vanish }
\lipsum[5]
\condline{\dotfill}
\lipsum[6]
\end{multicols}

\end{document}


(the code is a bit of a mixture of expl3 + ordinary LaTeX as expl3 doesn't yet have all tools for text processing (like handling penalties))

The result is:

And if we add 2 lines in the first multicol and use the star form of \condline in the second one we will get:

The right bottom column now appears to be too short but that is understandable as now the only break is before the \condline and the line vanishes if the break is taken there (just like the line with asterisks in the first multicol vanished at the break.

A proposal:

\documentclass{article}
\usepackage{multicol}
\usepackage{lipsum}
\usepackage{zref-savepos}%

\newcount\myy\newcount\ymax
\newcounter{myx}\setcounter{myx}{1}

\typeout{\themyx}
\newcommand\donotruleattop{%
\stepcounter{myx}
\zsaveposy{\themyx}%
\typeout{y position of \themyx: \zposy{\themyx}}
\myy=\numexpr\zposy{\themyx}\relax
\ifnum\myy>\ymax\relax\else\hrule\bigskip\fi
}%
\newcommand{\gaugeymax}{%
\stepcounter{myx}
\zsaveposy{\themyx}
\ymax=\numexpr\zposy{\themyx}-256\relax
}

\newenvironment{segmented}{%
\noindent\begin{minipage}{\linewidth}\donotruleattop
}{\bigskip
\end{minipage}}

\begin{document}\gaugeymax
\begin{multicols}{2}
\begin{segmented}
\lipsum[1]
\end{segmented}
\begin{segmented}
\lipsum[2]
\end{segmented}
\begin{segmented}
\lipsum[3]
\end{segmented}
\end{multicols}
\end{document}


There is a shortcoming: The number 256 appearing in the definition is hard-coded, and might have to be adjusted if you change the layout of the document.

Nevertheless, this might be a starting point for a smoother solution. And it is both a counter-example and confirmation of @Werner's statement, depending on what you mean by easy.

Obviously, this construction is not specific to multicolumn.