想象一下以下文档:
\documentclass{article}
\setlength{\parskip}{8pt}
\begin{document}
This is the first paragraph
This is the second paragraph
This is the third paragraph
\end{document}
我现在想修改第二段(不是第三段!!),以便第二段和第三段之间没有间距。
有很多方法可以修改第三段,使第二段和第三段之间没有空行 - 但我必须修改第二个。
不适合我的解决方案的最简单示例:
{\setlength{\parskip}{0pt}This is the third paragraph}
为什么?
此处看到的文档是所见即所得 (WYSIWYM) 编辑器 LyX 生成的 LaTeX 代码的最小示例。
在 LyX 中,我需要创建一个段落布局样式(用于第二段),以避免使用该样式的段落与任何其他样式的后续段落之间出现间距。
我只能修改第二段的输出,因为用户可以自由选择下一段的样式。所有其他段落样式都是“正常”的,并会生成 parskip,这是正常的期望行为。(除了我想要生成的特殊段落样式)
不幸的是,似乎没有办法在\n\n
不修改源代码的情况下告诉 LyX 不要在每种风格之后生成。
任何想法都值得赞赏!
更新 1:
\vspace
我发现单数长度的负数\parskip
可能会起到作用,但不确定是否会有不可预见的后果:
\documentclass{article}
\setlength{\parskip}{8pt}
\begin{document}
This is the first paragraph
This is the second paragraph\vspace{-\parskip}
This is the third paragraph
\end{document}
当我在大型自动生成的文档中在这种情况下使用负 vspace 时,会发生什么?
答案1
虽然我\noparskip
在第二段末尾显示,但它可以出现在段落的任何位置(包括最开头)并达到相同的效果。
编辑:我对使用简单负数的担心在于,在调用负数之前,\vspace
较大的 可能会人为地导致分页。这是否是 Lyx 中的问题,我没有经验来判断。不过,我认为在关闭之前发出负数可能是一个安全的选择,但我会让其他人发表评论。\parskip
\vspace
\vspace
\par
\documentclass{article}
\setlength{\parskip}{8pt}
\let\svpar\par
\edef\svparskip{\the\parskip}
\def\revertpar{\svpar\setlength\parskip{\svparskip}\let\par\svpar}
\def\noparskip{\leavevmode\setlength\parskip{0pt}%
\def\par{\svpar\let\par\revertpar}}
\begin{document}
This is the first paragraph
This is the second paragraph\noparskip
This is the third paragraph
This is the fourth paragraph
\end{document}
答案2
在@Inkane的大力帮助下,我尝试开发一个 Steven 代码版本,以便与 enumerate 和 itemize 环境更好地交互。它的使用方式与 Steven 的实现类似,但有以下变化:
- 当下一段是枚举或逐项列举时,它不会阻止 parskip。
- 它不会改变以下列表中的内部间距
\noparskip
。
实现如下:
\makeatletter
\newlength\noparskip@parskip % used to store a backup of the parskip value
\newboolean{noparskip@triggered} % flag to indicate that noparskip was run in the current paragraph
\setboolean{noparskip@triggered}{false}
\newboolean{noparskip@active} % flag to indicate that parskip should be restored after this paragraph
\setboolean{noparskip@active}{false}
\let\noparskip@par\par % store a backup of the \par command
\@setpar{% redefine \par with the means of ltpar.dtx to stay compatible to enumerate and itemize
\ifhmode% since we're counting occurrences of \par, \par\par would be a problem, so check that we are actually ending a paragraph
\ifthenelse{\boolean{noparskip@active}}{%
\setlength\parskip\noparskip@parskip% restore parskip
\setboolean{noparskip@active}{false}% remember not the restore parskip again
}{}%
\ifthenelse{\boolean{noparskip@triggered}}{%
\ifthenelse{\boolean{noparskip@active}}{}{
% we are triggering noparskip and not currently in a noparskip already
\setlength\noparskip@parskip\parskip % copy the current parskip into the backup variable
}%
\setboolean{noparskip@triggered}{false}% paragraph is ending, so noparskip is no longer triggered
\setlength\parskip{0pt}% no parskip when the next paragraph begins
\setboolean{noparskip@active}{true}% parskip must be restored by the next par
}{}%
\fi%
\noparskip@par% run the original par command
}
\def\noparskip@backout{%
\ifthenelse{\boolean{noparskip@active}}{%
% a list is beginning and parskip is currently set to zero, wich would mess up the list
\setlength\parskip{\noparskip@parskip}% restore parskip before the list begins
\setboolean{noparskip@active}{false}%
}{}%
\setboolean{noparskip@triggered}{false}% there's no sense in keeping noparskip triggered throughout a list
}
\xpretocmd\begin{%
\ifstrequal{#1}{enumerate}{\noparskip@backout}{}%
\ifstrequal{#1}{itemize}{\noparskip@backout}{}%
\ifstrequal{#1}{list}{\noparskip@backout}{}%
}{}{}
\def\noparskip{%
\leavevmode% ensure that we are within a paragraph
\setboolean{noparskip@triggered}{true}% trigger noparskip
}
\makeatother
它需要\usepackage{xpatch}
运行。