现在有一个需求是在 section 前加一条横线,MWE 如下:
\documentclass{ctexart}
\usepackage{zhlipsum}
\ExplSyntaxOn
\cs_set_eq:NN \section:nn \section
\RenewDocumentCommand{ \section }{ m }
{
\noindent
\rule{\textwidth}{0.4pt}
\section:nn {#1}
}
\ExplSyntaxOff
\begin{document}
\section{测试}
\zhlipsum[1-2]
\section{测试}
\zhlipsum[1]
\end{document}
但是有两个问题是
问题 1 我尝试了 needspace
,暂时能解决,不知道有没有更优的方案
问题 2 我的想法如果能判断当前位置前面是否有新页面的内容,之类的,然后加一个 bool 处理就行,但是不太知道如何判断好一些。
问题 1,如果不用 needspace
或类似的方法,会有极少的概率不能正确判断是否已经分页,比如下面的第四个标题就有可能会判断失败。
看看这是不是你想要的:
\documentclass{ctexart}
\usepackage{zhlipsum}
%\usepackage{showframe}
\ExplSyntaxOn\makeatletter
\cs_set_eq:NN \section:nn \section
\cs_new_protected:Npn \__my_needspace_if_newpage:nTF #1
{
% 可以试试删掉 \begingroup 和 \endgroup 之间的内容,看看能否正确判断第四个标题
\par \penalty-100\begingroup
\setlength{\dimen@}{\dimexpr#1}
\dimen@ii\pagegoal \advance\dimen@ii-\pagetotal
\ifdim \dimen@>\dimen@ii
\ifdim\dimen@ii>\z@ \vfil\fi
\penalty-\@M
\fi\endgroup
% 上面这些是 \Needspace 的代码,可以直接用 \Needspace{\dimexpr#1} 或 \Needspace*{\dimexpr#1} 替代
\bool_lazy_or:nnTF
{ \dim_compare_p:nNn { \pagegoal } = { \c_max_dim} }
{ \int_compare_p:nNn { \lastpenalty } < { -9999 } } % -\@M = -10000
}
\RenewDocumentCommand{ \section }{ m }
{
\__my_needspace_if_newpage:nTF { 1.5cm }
{ }
{ \hrule height0.4pt depth0pt }
\section:nn {#1}
}
\ExplSyntaxOff\makeatother
\begin{document}
\section{测试}
\zhlipsum[1-2]
\section{测试}
\zhlipsum[1]
\section{测试}
\zhlipsum[3-9][name=zhufu]
\section{测试}
\zhlipsum[1]
\end{document}
是我想要的效果!非常感谢,能麻烦说一下大概的原理吗?
\lastpenalty
和\pagegoal
这两个值是决定什么的呢?@u10945
\pagegoal
是本页要放置的内容的高度(不包括浮动体和脚注等),在一个新的页,它的值是\maxdimen
,用它可以判断是不是在新的页。\lastpenalty
用于获取上一个 node,如果这个 node 是 penalty,就把这个 penalty 的值赋给\lastpenalty
,所有在垂直模式的小于等于 -10000 的 penalty 都会出发强制分页,于是可以用它判断是否分页。这个例子中应该只需要判断
\pagegoal
就足够了,再判断\lastpenalty
保险一点。@u10307 非常感谢。