智能宏可生成节

智能宏可生成节

我想用 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为了让问题更有趣,假设我借用了\@ifnextcharLaTeX 的定义,然后定义

\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,但您可以根据自己的喜好(或缺乏喜好)进行调整。

相关内容