我想用 Plain 格式排版一本诗集。到目前为止,我已经能够使用以下代码让 TeX 遵循空格和行:
\def\startline{\par\noindent}
\obeylines\obeyspaces
\let^^M=\startline
\raggedright
\everypar{\hangindent=2em}
但是,宏会吞掉应该标记节间空格的双重 ^^M。
On the white sand
Of the beach of a small island
In the Eastern Sea
I, my face streaked with tears,
Am playing with a crab
– Ishikawa Takuboku
我怎样才能教 TeX 捕捉双换行符来产生所需的垂直空间?
附录
@egreg 和 @Steven 的答案几乎可以解决问题,但在简单情况下,垂直空间由 决定\baselineskip
;\par
为了让问题更有趣,假设我借用了\@ifnextchar
LaTeX 的定义,然后定义
\parindent=0em
\def\stanza{\leavevmode\vskip 1ex plus 1ex minus 1ex}
\long\def\normalpar{\expandafter\par}
\long\def\checkpar{\@ifnextchar^^M\stanza\normalpar}
\obeylines\obeyspaces
\let^^M=\checkpar%
\raggedright%
\everypar{\hangindent=2em}%
^^M
如您所见,我尝试检查的每个 处\@ifnextchar
都是另一个^^M
;如果是,则添加 中定义的节垂直空间\stanza
;否则,添加常规。我的问题是我不知道如何告诉处理器下一个要检查的标记正是换行符。这个想法是为了避免常规行上\par
假设的默认垂直空间。\baselineskip
答案1
如果要在空白行指示的位置留空行,请添加\leavevmode
到\startline
。与其\noindent
每次都发出,不如设置\parindent
为零。
此外,在开始产生效果%
后,有些功能会缺失\obeylines
;您无法看到代码中的问题,只是因为\par
垂直模式下没有任何反应。
\parindent=0pt
\def\startline{\par\leavevmode}
\obeylines\obeyspaces
\let^^M=\startline%
\raggedright%
\everypar{\hangindent=2em}%
On the white sand
Of the beach of a small island
In the Eastern Sea
I, my face streaked with tears,
Am playing with a crab
--- Ishikawa Takuboku
\bye
下一个版本需要空行真的很空,这样您还可以控制节之间的间距(以及最终的归属)。
也许也可以处理好空间问题,但这很困难,不值得付出努力。你的方法从一开始就是错误的:没有标记就意味着没有灵活性。
\obeylines\obeyspaces
\parindent=0pt%
\def\endline{%
\par%
\let\savedspaces\empty%
\futurelet\next\perhapseol%
}%
\def\perhapseol{%
\ifx\next^^M%
\let\nxt\newstanza%
\else%
\let\nxt\leavevmode%
\fi%
\nxt%
}%
\def\newstanza#1{\vskip50pt#1}% exaggerated to show the effect
\let^^M=\endline%
\raggedright%
\everypar{\hangindent=2em}%
On the white sand
Of the beach of a small island
In the Eastern Sea
I, my face streaked with tears,
Am playing with a crab
--- Ishikawa Takuboku
\catcode`\^^M=5
\bye
答案2
\hbox
这里我给添加了 null \everypar
。这样做的目的是强制将两个空行解释为\par\hbox{}\par
而不是\par\par
。在后一种情况下,TeX 会将其折叠为单个\par
,而这并不是我们想要的。
\def\startline{\par\noindent}
\obeylines\obeyspaces
\let^^M=\startline
\raggedright
\everypar{\hbox to 0pt{}\hangindent=2em}
On the white sand
Of the beach of a small island
In the Eastern Sea
I, my face streaked with tears,
Am playing with a crab
-– Ishikawa Takuboku
\bye
答案3
因此,一个相当通用的解决方案可能是,假设\@ifnextchar
从加载miniltx.tex
,
\input miniltx
\makeatletter
\parindent=0em
\def\stanzasp#1{\edef\@stanzasp{\vskip#1\relax}}
\def\normalpar{\par\leavevmode}
\obeylines\obeyspaces
\def\checkpar{\@ifnextchar^^M\@stanzasp\normalpar}%
\let^^M=\checkpar%
\raggedright%
\everypar{\hangindent=2em}%
\makeatother%
\stanzasp{2ex plus 1ex minus 1ex}
该宏\stanzasp
以维度作为参数;在此示例中,它被设置为2ex plus 1ex minus 1ex
,但您可以根据自己的喜好(或缺乏喜好)进行调整。