有没有类似 roff 的.ns
纯 TeX 功能(或者更好的功能)?例如,一条命令表示vskip
忽略紧随其后的 s,或者(附加的)一个特殊的“ vskip
”,使所有相邻的vskip
s 变为零?
答案1
LaTeX 有这个宏\addvspace
;也许这不是你真正想要的,因为它会增加比较两个连续的空格所产生的更大空间,这通常是你想要的。例如,假设一个列表前面总是有一些垂直空间;如果它跟在章节标题后面,那么章节标题后面的空间可能比列表前面的空间大。相反,如果列表跟在后面\smallskip
,那么更大的跳跃将是列表的跳跃。所以列表将以 开头,\addvspace
或者,对于我下面建议的普通 TeX 宏,以 开头\addvskip
。
% latex.ltx, line 1462:
\def\addvspace#1{%
\ifvmode
\if@minipage\else
\ifdim \lastskip =\z@
\vskip #1\relax
\else
\@tempskipb#1\relax
\@xaddvskip
\fi
\fi
\else
\@noitemerr
\fi}
补充\@xaddvskip
% latex.ltx, line 1448:
\def\@xaddvskip{%
\ifdim\lastskip<\@tempskipb
\vskip-\lastskip
\vskip\@tempskipb
\else
\ifdim\@tempskipb<\z@
\ifdim\lastskip<\z@
\else
\advance\@tempskipb\lastskip
\vskip-\lastskip
\vskip \@tempskipb
\fi
\fi
\fi}
在纯 TeX 中您不需要处理小页面,因此这可以简化。
如果未在垂直模式下调用,宏将会发出一条错误消息(错误的消息,但团队在 LaTeX2e 发布时遇到内存限制,因此他们只选择了一条可能有帮助的消息)。
它做什么?在 minipage 中什么也不做,所以让我们看看其他情况。它用于\lastskip
检索最后一个跳过的数量(如果最后一个项不是跳过,则返回零);如果返回零,则发出指定的跳过并结束其工作。否则,它会用指定的数量加载暂存跳过寄存器并调用\@xaddvskip
。
此宏依次检查是否\lastskip
小于规定金额;在这种情况下,它会发出\vskip-\lastskip
终止指令并发出所需的跳过指令。否则,它会查看规定的跳过是否为负数,如果也是\lastskip
负数,则不执行任何操作;否则,它会添加\lastskip
到规定的金额,\lastskip
像以前一样终止并发出总和。
Plain TeX 的实现如下:
\catcode`@=11
\newskip\@addvskiptemp
\def\addvskip{\afterassignment\@addvskip\@addvskiptemp=}
\def\@addvskip{%
\par % \vskip implies \par
\ifdim\lastskip=\z@
\vskip\@addvskiptemp
\else
\@addvsk@p
\fi
}
\def\@addvsk@p{%
\ifdim\lastskip<\@addvskiptemp
\vskip-\lastskip
\vskip\@addvskiptemp
\else
\ifdim\@addvskiptemp<\z@
\ifdim\lastskip<\z@
\else
\advance\@addvskiptemp\lastskip
\vskip-\lastskip
\vskip\@addvskiptemp
\fi
\fi
\fi
}
\catcode`@=12
测试文件(在开头添加上面的代码):
abc\smash{\vrule depth 2.9\baselineskip}
\vskip2\baselineskip
abc\smash{\vrule depth 2.9\baselineskip}
\vskip\baselineskip
\addvskip2\baselineskip
abc
\bye
这些规则是为了显示空间是相同的。
请注意,Plain TeX 已经有了\removelastskip
,简化版本可以是
\catcode`@=11
\newskip\@addvskiptemp
\def\addvskip{\afterassignment\@addvskip\@addvskiptemp=}
\def\@addvskip{%
\par % \vskip implies \par
\ifdim\lastskip<\@addvskiptemp
\removelastskip
\vskip\@addvskiptemp
\fi
}
\catcode`@=12
如果你不打算出现负面跳过的话。
答案2
您可以准备\vvskip
仅在第一次使用时执行 vskip 的宏(在文档中的某个位置):
\let\orivskip=\vskip
\def\vvskip{\par \ifdim\lastskip=0pt \expandafter\orivskip
\else \bgroup \afterassignment\egroup \dimen0=\fi
}
您还可以设置\let\vskip=\vvskip
以将此行为应用于所有\vskips
。但是此解决方案无法对文档中的所有 vskips 进行绝对控制,因为有许多 vskips 不是由\vskip
原始函数创建的:来自\parskip
、显示数学等。