有时候,当我用 LaTeX 撰写演讲稿时,我希望按照\obeylines
和\obeyspaces
允许的方式格式化其中的各个部分,以便在每一行上紧凑地表达一个连贯的思想,并且行之间的关系可以用前导缩进来表达,如下所示:
One thought introduced with a coherent phrase,
followed by a subordinate phrase,
and a coordinate subordinate phrase.
Then a second thought introduced ...
我遇到的问题是,在连续行组(“段落”)之间添加额外的垂直间距,如上面最后一行之前。到目前为止,我想到最好的临时措施是定义管道符号,可以将其添加到每个组的末尾,如下所示:... coordinate subordinate phrase.|
重新定义的代码看起来像这样,我将其放入外部包中。
\catcode`|=\active
\def|{\smallskip}
这或多或少达到了预期的效果,但是整个源文本中的管道字符很烦人,显然这是一种解决方法。
因此,我一直在尝试定义一个可以实现我想要的环境,而不需要管道字符来提供额外的间距。这是我目前所拥有的……
\newenvironment{linewise}{%
\let\@oldpar=\par \let\par=\newpar \obeylines \let\par=\@oldpar}
{}
如果我朝这个方向继续,应该如何\newpar
定义?我曾尝试使用\\
,但是当它自动插入到空行末尾(\par
通常插入的位置)时,TeX 会犹豫,并且它不会结束前一段(因为字符是\active
,我猜想),而这正是我想做的。
据我所知,问题在于在两个或多个回车符处段落之间的划分发生在 TeX 的口中,我无法进行任何调整来区分我想要在有两个或多个回车符时插入的垂直空间和我想要在只有一个回车符时插入的换行符(或新段落)。
或者有更好的方法来实现这一点?
答案1
您不应该重新定义\par
,而是 之后的活动行尾\obeylines
。
\documentclass{article}
\newenvironment{linewise}
{\parindent=0pt
\obeyspaces\obeylines
\begingroup\lccode`~=`\^^M
\lowercase{\endgroup\def~}{\par\leavevmode}}
{\ignorespacesafterend}
\begin{document}
\noindent X\leaders\hrule\hfill X
\begin{linewise}
One thought introduced with a coherent phrase,
followed by a subordinate phrase,
and a coordinate subordinate phrase.
Then a second thought introduced ...
\end{linewise}
Something after
\end{document}
答案2
经过一段时间,我找到了一个更好的解决方案。它借鉴了 eTeX,它有命令\obeywhitespace
。我把需要的定义(虽然有些看起来相当复杂,但显然是有效的)放到了一个包中,可以在需要时使用。我将在下面包含相关的包内容。
请注意,最后有一个名为的命令\setblankskip
,它允许调整原始问题中所示的“段落”之间的间距。
还请注意,此行为是在名为 的环境中提供的linewise
。唯一剩下的烦恼是linewise
环境中的最后一个换行符将反映在空白输出行中。可以通过在最后一个换行符前面加上 来避免这种情况%
。
\def\makeactive#1{\catcode`#1 = \active \ignorespaces}%
\def\gobble#1{}%
\newskip\blanklineskipamount
\blanklineskipamount = -.8\baselineskip
\begingroup
\makeactive\^^M \makeactive\ % No spaces or ^^M's from here on.
\gdef\obeywhitespace{%
\makeactive\^^M\def^^M{\par\futurelet\next\@finishobeyedreturn}%
\makeactive\ \def {\ }%
\aftergroup\@removebox%
\futurelet\next\@finishobeywhitespace%
}%
\gdef\@finishobeywhitespace{{%
\ifx\next %
\aftergroup\@obeywhitespaceloop%
\else\ifx\next^^M%
\aftergroup\gobble%
\fi\fi}}%
\gdef\@finishobeyedreturn{%
\ifx\next^^M\vskip\blanklineskipamount\fi%
\indent%
}%
\endgroup
\def\@obeywhitespaceloop#1{\futurelet\next\@finishobeywhitespace}%
\def\@removebox{%
\setbox0 = \lastbox
\ifdim\wd0=\parindent
\setbox2 = \hbox{\unhbox0}%
\ifdim\wd2=0pt
\ignorespaces
\else
\box2 % Put it back: it wasn't empty.
\fi
\else
\box0 % Put it back: it wasn't the right width.
\fi
}%
\newenvironment{linewise}{\begingroup\obeywhitespace}{\endgroup}%
% By default, a blank line will result in .2\baselineskip. This allows
% other values to be set
\RequirePackage{calc}
\newcommand{\setblankskip}[1]{\setlength{\blanklineskipamount}{-\baselineskip+#1}}