对于我的论文,我正在对其进行最后的格式化,论文要求我在正文中使用双倍行距,在引用块中使用单倍行距。但这不知何故产生了一个令人讨厌的结果,即引用块前后的空格大小不一样。哦,LaTeX 专家,帮我解决这个问题吧!
示例代码:
\documentclass[11pt,oneside]{book}
\usepackage[letterpaper]{geometry}
\usepackage{setspace}
\expandafter\def\expandafter\quote\expandafter{\quote\singlespacing}
\expandafter\def\expandafter\quotation\expandafter{\quotation\singlespacing}
\doublespacing
\parskip=0pt
\usepackage{lipsum}
\begin{document}
\lipsum[1]
\begin{quotation}Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna. Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. \end{quotation}
\lipsum[1]
\end{document}
示例图片:
答案1
警告:前面的答案很长!
该setspace
软件包有着悠久的历史(可能用了不同的名称,我不记得了),可以追溯到上个世纪 80 年代末,LaTeX 2.09 和 TeX2 的鼎盛时期;开头的评论见证了setspace.sty
这一点,也见证了它漫长而并非总是线性的增量开发,在此期间,随着报告的问题和错误,临时解决方案不断被添加进来。评论还警告您,即使在最新版本中(我的版本,与 TeX Live 2015 一起分发,版权归 2011 年所有),一些问题可能仍未解决;特别是第 284-285 行
\begin{singlespace}\begin{quote}
在引用前产生错误的间距(插入了额外的粘连)。
事实上,问题中抱怨的异常行为在我看来是由于\singlespacing
命令中的一个小错误;我将尝试在这个答案中详细分析它,并提出更正建议。
详细分析
再次引用第 54 至 58 行的评论setspace.sty
:
\vskip
定义中的额外内容\singlespacing
似乎使从多倍行距到单倍行距的过渡更加清晰。这些似乎没有道理 [原文如此] 以进行其他尺寸更改。
这是怎么回事?显然,通过增加行距可以实现多重间距,即 (牛津英语词典(如 Mac OS X 的词典应用程序所呈现的那样)“从一行文字的底部到下一行文字的底部的距离”。现在,(La)TeX 应用了相同的不仅指定段落的所有行的行距,还指定该段落第一行和前一个段落最后一行之间的行距。这意味着,当两个连续的段落使用不同的行距排版时,第一段最后一行和第二段第一行之间的行距将始终与第二段行距相同。当您将较小的行距更改为较大的行距时,这看起来是正确的,但反过来却不是(想想看):在后一种情况下,似乎两个段落之间也应该使用较大的行距。
为了弥补这一点,该\singlespacing
命令添加了一个额外的空白行,新的(单行)内容位于其上方和下方:
\newcommand{\singlespacing}{%
\setstretch {\setspace@singlespace}% normally 1
\vskip \baselineskip % Correction for coming into singlespace
}
但是,只有当“旧”门廊的高度恰好是“新”门廊高度的两倍时,才会产生预期的效果;所以:
显然如此不是从 变为 时有效
\onehalfspacing
,\singlespacing
正如第 54-58 行的注释所暗示的那样;\doublespacing
即使从改为 也不起作用\singlespacing
,因为前一种样式的行距根本不是后一种样式的行距的两倍。
实际上,通常所认为的“双倍行距”是指文本基线之间的垂直间距是文本基线的两倍。字体大小;例如,对于问题中的 11 点字体大小,基线应相隔 22 点。但
\singlespacing
条件中的行距已设置为字体大小的 120%—125%,例如,对于 11 点大小,则为 13.6 点:将行距设置为两倍将导致行距为 27.2 点,即几乎是“两行半间距”。出于这个原因,该setspace
包\doublespace
通过将行距的乘数设置为实际上小于二的值来实现:
\newcommand{\doublespacing}{%
\setstretch {1.667}% default
\ifcase \@ptsize \relax % 10pt
\setstretch {1.667}%
\or % 11pt
\setstretch {1.618}%
\or % 12pt
\setstretch {1.655}%
\fi
}
如您所见,11pt
使用 1.618 的乘数(让人想起黄金比例?),产生 1.618 * 13.6pt = 22,0048pt 的有效行距,也就是说,几乎是字体大小的两倍,正如预期的那样。总而言之,命令\vskip \baselineskip
发出的\singlespacing
结果被证明是过度补偿,这正是所问到的额外空间的来源。
我们可以通过编译 OP 的 MWE 的稍微修改版本来轻松确认这一点:
\documentclass[11pt,oneside]{book}
\usepackage[letterpaper]{geometry}
\usepackage{setspace}
\expandafter\def\expandafter\quote\expandafter{\quote\singlespacing}
\expandafter\def\expandafter\quotation\expandafter{\quotation\singlespacing}
\doublespacing
\parskip=0pt
\usepackage{lipsum}
\begin{document}
\lipsum[1]
\begin{quotation}
Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget,
consectetuer id, vulputate a, magna. Donec vehicula augue eu neque.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames
ac turpis egestas.
\end{quotation}
\lipsum[2]
\singlespacing
\lipsum[3]
\showboxbreadth = 1000
\showboxdepth = 10
\showlists
\end{document}
此代码产生以下输出:
代码末尾包含的跟踪命令将有关行间空格的详细信息(以及其他信息)写入转录文件。此诊断跟踪的开头内容如下:
### vertical mode entered at line 0
### current page:
\write-{}
\glue(\topskip) 3.39584
\hbox(7.60416+2.12917)x430.00462, glue set - 0.16643
.\hbox(0.0+0.0)x17.0
.\OT1/cmr/m/n/10.95 L
.\OT1/cmr/m/n/10.95 o
.\OT1/cmr/m/n/10.95 r
.\OT1/cmr/m/n/10.95 e
.\OT1/cmr/m/n/10.95 m
.\glue 3.65 plus 1.825 minus 1.21666
…省略 96 行…
.\glue(\rightskip) 0.0
\penalty 150
\glue(\baselineskip) 12.27142
\hbox(7.60416+2.12917)x430.00462, glue set 0.52057
.\OT1/cmr/m/n/10.95 p
.\OT1/cmr/m/n/10.95 l
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 c
从第五行开始\hbox
的 是第一段的第一个排版行,它.\glue(\rightskip) 0.0
在下面大约一百行处结束;我们可以看到这一行的深度是 2.12917(点)。\penalty 150
接下来是一个来自 的A \clubpenalty
,然后是一个 12.27142 点的“行间粘合”(\glue(\baselineskip) 12.27142
),这正是 TeX 在两个排版行之间插入的垂直空间,以确保它们各自的基线尽可能分开。由于下一个排版行以 开头,其
\hbox(7.60416+2.12917)x430.00462...
高度为 7.60416 点,我们看到 TeX 假设行距为 2.12917 + 12.27142 + 7.60416 = 22,00475 点,正如上面所述(在舍入误差范围内)。
现在让我们看一下与环境开始相对应的摘录quotation
:
\hbox(7.60416+2.12917)x430.00462, glue set 115.40472fil
.\OT1/cmr/m/n/10.95 s
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 g
.\OT1/cmr/m/n/10.95 i
.\OT1/cmr/m/n/10.95 t
…省略 60 行…
.\glue 3.65 plus 1.825 minus 1.21666
.\OT1/cmr/m/n/10.95 r
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 t
.\OT1/cmr/m/n/10.95 r
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 m
.\OT1/cmr/m/n/10.95 .
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
\penalty -51
\glue 12.0 plus 4.0 minus 6.0
\glue 13.6
\glue(\parskip) 0.0 plus 1.0
\glue(\baselineskip) 3.86668
\hbox(7.60416+2.12917)x375.2545, glue set 0.4625, shifted 27.37506
内容\hbox
以五个字符“sagit”开头,以“rutrum”+其他内容+结尾的
.\glue(\rightskip) 0.0
是第一段的最后一行,位于引文上方;我们也报告了这一行,因为我们需要知道它的深度(再次)是 2.12917 点。在这个框之后我们发现:
\penalty -51
(在报价前打破页面有奖励);\glue 12.0 plus 4.0 minus 6.0
(引文上方插入垂直空格);\glue 13.6
\singlespacing
,这是命令为间距变化而插入的(过度)补偿;\glue(\parskip) 0.0 plus 1.0
(段落之间插入垂直空格);\glue(\baselineskip) 3.86668
(见下文);\hbox(7.60416+2.12917)x375.2545...
,这是包含引文第一行排版的框的开头;请注意,它的高度为 7.60416(点)。
如果我们将前一行的深度和行间粘连添加到此高度,我们可以检查后者已计算为达到 7.60416 + 2.12917 + 3.86668 = 13.60001(始终为点)的行距,也就是说,在舍入误差范围内,“正常”(对于 11 点字体)行距为 13.6 点。前一段最后一行的基线与引文第一行的基线之间的总距离为 13.60001 + 13.6 + 12.0 ≈ 39.2 点(忽略拉伸和收缩部分);但最好是 22.0048 + 12.0 ≈ 34.0 点,即 [“双倍行距”行距] + [引文上方的空格]。请注意,差异约为 1.83 毫米,足以清晰察觉。
为了确认距离确实如声称的一样大,请考虑环境末端发生的事情的记录quotation
:
\hbox(7.60416+2.12917)x375.2545, glue set - 0.66791, shifted 27.37506
.\OT1/cmr/m/n/10.95 h
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 b
.\OT1/cmr/m/n/10.95 i
…省略 85 行…
.\OT1/cmr/m/n/10.95 t
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 s
.\OT1/cmr/m/n/10.95 .
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
\penalty -51
\glue 12.0 plus 4.0 minus 6.0
\glue(\parskip) 0.0
\glue(\baselineskip) 12.27142
\hbox(7.60416+2.12917)x430.00462, glue set - 0.10161
.\OT1/cmr/m/n/10.95 N
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 m
.\glue 3.65 plus 1.825 minus 1.21666
.\OT1/cmr/m/n/10.95 d
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 i
.\glue 3.65 plus 1.825 minus 1.21666
.\OT1/cmr/m/n/10.95 l
.\OT1/cmr/m/n/10.95 i
.\OT1/cmr/m/n/10.95 g
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 l
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 ,
再次,抄本从引文最后一行的开头(“habi-…”)开始,因此您可以看到它的深度(再次)为 2.12917 点,并结束报告引文后段落第一行的开头(“Nam [空格] dui [空格] ligula [逗号]…”,其高度(也是)7.60416 点。按照上面给出的思路分析这个抄本,我们可以检查到,行距
\glue(\baselineskip) 12.27142
已计算为 2.12917 + 12.27142 + 7.60416 = 22,00475 点,与 有效时排版的段落中任何两行之间的行距完全相同
\doublespacing
(见上文)。因此,引文最后一行基线与下一段落第一行基线之间的总距离为 22.00475 + 12.0 ≈ 34.0 点(而不是我们在报价上方发现了39.2点)。
您还可以类似地检查最后一段之前是否有相同数量的多余空间(过度补偿),其中只发生从到\doublespacing
的切换\singlespacing
,而无需输入复杂的quotation
环境。在最后一段第一行之前插入的行间粘连产生了 13.00001 点的行距,此外还有通常的(有缺陷的)垂直空间 13.6 点;再次,总数是(大约)27.2 点,而不是 22.0048 点,因为它应该是复制前一段最后两行之间的行距。无论如何,这个多余空间在打印输出中清晰可见。
建议修正
我们提出的修正是对\singlespacing
命令进行修补;之后,可以使用通常的quote
andquotation
环境,得到正确的结果。在下面的代码中,这个对的修补\singlespacing
正是由\makeatletter
and分隔的段\makeatother
。
\documentclass[11pt,oneside]{book}
\usepackage[letterpaper]{geometry}
\usepackage{setspace}
\usepackage{lipsum}
\makeatletter
\renewcommand*\singlespacing{%
\par % ensure vertical mode
\null % add fake line with previous leading still in force
\setstretch {\setspace@singlespace}% change leading
\nobreak
\vskip -\baselineskip % compensate for the fake line we added, but with
% the new leading
\vskip \z@skip % tell "\addvspace" and "\addpenalty" _not_ to remove the
% above correction
}
\makeatother
% I’d go for different names, anyway; or follow advice given in other answers to
% patch up the standard environments.
\newenvironment*{JoeMquote}{%
\singlespacing
\quote
}{\endquote}
\newenvironment*{JoeMquotation}{%
\singlespacing
\quotation
}{\endquotation}
\doublespacing
\setlength{\parskip}{0pt}
\begin{document}
\lipsum[1]
\begin{JoeMquotation}
Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget,
consectetuer id, vulputate a, magna. Donec vehicula augue eu neque.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames
ac turpis egestas.
\end{JoeMquotation}
\lipsum[2]
\singlespacing
\lipsum[3]
\showboxbreadth = 1000
\showboxdepth = 10
\showlists
\end{document}
请注意,我们倾向于定义两个新环境,而不是更改默认环境。事实上,这个答案是关于找到精确的补偿会在报价的上方和下方产生相同的垂直空间,而不是如何将这种修正纳入标准环境:其他答案已经解释了这一点。
该代码生成的打印输出如下所示:您可以立即检查,这次的间距看起来是正确的。
写入记录文件的跟踪确认间距确实与缩放点正确。这是环境的开始quotation
,包括其上方的最后一行:
\hbox(7.60416+2.12917)x430.00462, glue set 115.40472fil
.\OT1/cmr/m/n/10.95 s
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 g
.\OT1/cmr/m/n/10.95 i
.\OT1/cmr/m/n/10.95 t
…省略 60 行…
.\glue 3.65 plus 1.825 minus 1.21666
.\OT1/cmr/m/n/10.95 r
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 t
.\OT1/cmr/m/n/10.95 r
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 m
.\OT1/cmr/m/n/10.95 .
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
\glue(\baselineskip) 19.87558
\hbox(0.0+0.0)x0.0
\penalty 10000
\glue -13.6
\glue 0.0
\penalty -51
\glue 12.0 plus 4.0 minus 6.0
\glue(\parskip) 0.0 plus 1.0
\glue(\baselineskip) 5.99585
\hbox(7.60416+2.12917)x375.2545, glue set 0.4625, shifted 27.37506
上一段最后一行基线与引文第一行基线之间的距离为 2.12917 + 19.87558 - 13.6 + 12.0 + 5.99585 + 7.60416 = 34.00476,在舍入误差范围内,与预期值 [“双倍行距”前导] + [引文上方的空格] = 22.00475 + 12.0 = 34.00475 完全对应。另一方面,在引文的末尾,我们发现
\hbox(7.60416+2.12917)x375.2545, glue set - 0.66791, shifted 27.37506
.\OT1/cmr/m/n/10.95 h
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 b
.\OT1/cmr/m/n/10.95 i
…省略 85 行…
.\OT1/cmr/m/n/10.95 t
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 s
.\OT1/cmr/m/n/10.95 .
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
\penalty -51
\glue 12.0 plus 4.0 minus 6.0
\glue(\parskip) 0.0
\glue(\baselineskip) 12.27142
\hbox(7.60416+2.12917)x430.00462, glue set - 0.10161
(照例,也显示了下一段第一行的开头)。这里两个基线之间的距离是 2.12917 + 12.0 + 7.60416 + 12.27142 = 34.00475, 确切地与上面的报价相同(一如既往,在四舍五入误差范围内)。
\glue 12.0 plus 4.0 minus 6.0
在\singlespacing
最后一段之前的更改处也发生了同样的事情(但没有),您可以自己检查一下:
\hbox(7.31305+0.0)x430.00462, glue set 394.62999fil
.\OT1/cmr/m/n/10.95 m
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 r
.\OT1/cmr/m/n/10.95 i
.\OT1/cmr/m/n/10.95 s
.\OT1/cmr/m/n/10.95 .
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
\glue(\baselineskip) 22.00475
\hbox(0.0+0.0)x0.0
\penalty 10000
\glue -13.6
\glue 0.0
\glue(\parskip) 0.0
\glue(\baselineskip) 5.99585
\hbox(7.60416+2.12917)x430.00462, glue set 0.28633
.\hbox(0.0+0.0)x17.0
.\OT1/cmr/m/n/10.95 N
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 l
.\OT1/cmr/m/n/10.95 l
.\OT1/cmr/m/n/10.95 a
.\glue 3.65 plus 1.825 minus 1.21666
.\OT1/cmr/m/n/10.95 m
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 l
.\OT1/cmr/m/n/10.95 e
.\OT1/cmr/m/n/10.95 s
.\OT1/cmr/m/n/10.95 u
.\OT1/cmr/m/n/10.95 a
.\OT1/cmr/m/n/10.95 d
.\OT1/cmr/m/n/10.95 a
.\glue 3.65 plus 1.825 minus 1.21666
最后要说的是:修正应该而且可以以更通用的级别实施,涵盖所有可能的间距变化情况。通用算法不应该将零散的框和粘连添加到垂直列表中,而应该简单地计算旧行距和新行距之间的差值(旧行距减去新行距),如果差值为正,则添加与该值完全相同的垂直间距。
答案2
使用 提供的修补命令会更容易etoolbox
,特别是\AtBeginEnvironment
和\AfterEndEnvironment
。例如如下:
\documentclass[11pt,oneside]{book}
\usepackage[letterpaper]{geometry}
\usepackage{setspace,etoolbox}
\AtBeginEnvironment{quote}{\addvspace{\baselineskip}\singlespacing}
\AfterEndEnvironment{quote}{\addvspace{1.5\baselineskip}}
\AtBeginEnvironment{quotation}{\addvspace{\baselineskip}\singlespacing}
\AfterEndEnvironment{quotation}{\addvspace{1.5\baselineskip}}
\doublespacing
\parskip=0pt
\usepackage{lipsum}
\begin{document}
\lipsum[1]
\begin{quotation}Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna. Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. \end{quotation}
\lipsum[1]
\end{document}
quote
和的定义quotation
由 documentclass 提供,在本例中为book.cls
。texdoc book
在您的系统上尝试,这将引导您找到它们的文档。有关定义的详细信息,也在环境引用和报价有什么区别?\singlespacing
。如您所见,其中涉及多个参数。此外, from的定义setspace.sty
包含一个显式\vskip\baselineskip
如果您想要上面的负空间,请使用\vspace{-myamount}
,而不是\addvspace
。我建议使用 的倍数\baselineskip
或一定数量的数量ex
。这样,尺寸是根据文档特征计算出来的,而不是绝对的。
答案3
我认为您只需在整个文档中调整 \vskip。为此,您可以定义一个宏,该宏执行包含正确垂直跳过量的引用。
\documentclass[11pt,oneside]{book}
\usepackage[letterpaper]{geometry}
\usepackage{setspace}
\doublespacing
\parskip=0pt
\usepackage{lipsum}
%%To change the space after the quote adjust the \vskip below%%
%%Adjust the \hsize to change the width of the quote%%
\def\Quote#1{\hfil\vtop{\hsize=4.5in \singlespacing #1}%
\hfil\vskip.4in\par\doublespacing}
\begin{document}
\lipsum[1]
\Quote{Painting the roses red;We're painting the roses red;%
We dare not stop;Or waste a drop;So let the paint be spread;%
We're painting the roses red;We're painting the roses red;%
Oh, painting the roses red;And many a tear we shed; Because we know;%
They'll cease to grow;In fact, they'll soon be dead;And yet we go ahead;%
Painting the roses red;Painting the roses red;We're painting the roses
red; Oh, pardon me;But Mister Three; Why must you paint them red?}
\lipsum[1]
\end{document}
答案4
谢谢大家的建议。我已经用以下代码尽可能接近了:
\expandafter\def\expandafter\quote\expandafter{\quote\vskip-1.8mm\singlespacing}
在我弄清楚如何添加负的 vskip 之后,只需对值进行修改,直到它产生尽可能接近均匀间距的结果。我更喜欢一个不那么黑客的解决方案,它产生了相同的垂直间距,但我对 LaTeX 不够了解,无法定义一个全新的引号环境,而不需要做很多额外的工作。所以这样就行了。
剩下的一个问题:对 vskip 的调整适用于前引用,但我不知道如何应用它后(因此我只能在之前缩小较大的空间,而不是在之后扩大较小的空间;不知道我更喜欢哪种,但这是我唯一的选择)。有什么建议吗?我真的不知道用 \expandafter 做什么,所以我只是业余地瞎折腾。