我有一系列采用 2 列布局的文本块,使用multicol
。每个文本块都包裹在一个minipage
环境中,以确保所有包含的文本都显示在同一列中。我想用水平线或其他装饰将这些小页面分开,但如果它位于列的顶部,我不希望规则出现。
显然,我可以添加一个参数来手动抑制该规则,但我正在寻找一种自动检测情况并适当格式化的方法。对于下面的 MWE,这意味着该行应该只出现在最后两段之间。
\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}
答案1
这是你想要得到的吗?
\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
\cleaders\vbox{\hrule width\linewidth}\vskip0.4pt
\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}
答案2
可能有更好的方法可以做到这一点,但是@Werner 的链接给了我这个想法。它依赖于colaction
以下功能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}
如果有人有更优雅/高效的解决方案,我很乐意接受他们的答案,所以我暂时不会接受我自己的答案。
答案3
您可以让 TeX 确定位置(在 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
%
\cleaders \copy \l__condline_box \vskip \l__condline_dim
\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\\
add two extra lines
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}
(该代码有点像 expl3 + 普通 LaTeX 的混合,因为 expl3 尚未具备所有文本处理工具(如处理处罚))
结果是:
\condline
如果我们在第一个多列中添加 2 行,并在第二个多列中使用星号形式,我们将得到:
现在,右下角的列似乎太短了,但这是可以理解的,因为现在唯一的中断是在之前,\condline
并且如果在那里中断,该线就会消失(就像第一个多列中带有星号的线在中断处消失一样)。
答案4
一份提案:
\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}
有一个缺点:定义中出现的数字256
是硬编码的,如果您更改文档的布局,可能需要进行调整。
尽管如此,这可能是一个更顺利的解决方案的起点。它既是@Werner 陈述的反例,也是对它的确认,这取决于你所说的“容易”是什么意思。
显然,这种构造并不是多列所特有的。