命令以回车或空行分隔

命令以回车或空行分隔

我有这个文件

\documentclass{scrartcl}

\long\def\quotenextparagraph#1

{\begin{quote}#1\end{quote}}

\begin{document}

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

\quotenextparagraph
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

\end{document}

该命令\quotenextparagraph将其参数(由空行分隔)放在环境中quote。建议使用

\long\def\quotenextparagraph#1\par{\begin{quote}#1\end{quote}}

但有了这个定义,你就失去了在论证中包含段落分隔符(没有小技巧)的能力。有了定义中的空白行,你就可以使用

\quotenextparagraph
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.\par
Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

但是……您不需要在\par标记前留空格。如果您留了空格,那么 LaTeX 会认为参数在此处被分隔。

 第一个问题:为什么呢?

现在是问题的第二部分。我感兴趣的是只用一次返回来做同样的事情(我不知道确切的词;我的意思是“空白行”=两次返回)。

\def\quotethisline#1
{\begin{quote}#1\end{quote}}

以便

\quotethisline Lorem ipsum dolor sit amet.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.

Lorem ipsum dolor sit amet.仅在引号中给出。正如我所料,它仅给出Lorem(直到第一个空格)。

 第二个问题:为什么会出现这种情况?

第三个问题:如何实现仅由一个返回值分隔的参数?(如果可能的话,最好不要触碰 catcodes)

附言:我可能知道原因,但我认为值得有一个答案来解释它。

答案1

在第一个定义中,参数由空格和\par标记分隔:

\long\def\testA#1

{\begin{quote}#1\end{quote}}

\long\def\testB#1 \par{\begin{quote}#1\end{quote}}

\ifx\testA\testB\message{EQUAL}\else\message{DIFFERENT}\fi

印刷

EQUAL

第一个行尾\testA被转换为空格标记;第二个被转换为标记\par,因为它是在 TeX 处于“跳过空白”状态时被扫描的。

定义

\def\quotethisline#1
{\begin{quote}#1\end{quote}}

完全等同于

\def\quotethisline#1 {\begin{quote}#1\end{quote}}

因为标记化将行尾转换为空格标记。

你不能只用行尾来分隔字符串,而无需进行类别代码处理,因为执行了标记化宏扩展。

此外,TeX 会读取整行并用标记化之前的符号替换操作系统记录结束分隔符\endlinechar,这会带来更多问题。

可以这样做,这对类别代码的影响很小:

\documentclass{scrartcl}

\catcode`\^^L=\active
\def^^L{\end{quote}\endlinechar=13 }
\def\quotenextline{%
  \begin{quote}
  \endlinechar`\^^L
}

\begin{document}

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
\quotenextline
Lorem ipsum dolor sit amet.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.

\end{document}

然而这只是玩物而已:绝不使用行尾作为分隔符,除非您处于非常受控制的环境中(例如,逐字模式)。

这是另一个解决方案,从 TeX 的第 11.9.4 节按主题复制而来:

\documentclass{scrartcl}

\def\quotethisline{\begingroup\catcode`\^^M=12 \xquotethisline}
{\catcode`\^^M=12 %
 \gdef\xquotethisline#1^^M{\begin{quote}#1\end{quote}\endgroup}%
}

\begin{document}

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
\quotethisline Lorem ipsum dolor sit amet.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.

\end{document}

答案2

TeX 使用多个处理器来处理其输入:

输入处理器 -> 令牌处理器 -> 扩展处理器 -> 主处理器

TeXbook 中提到了胃肠解剖学术语,但我从未使用过该术语。

输入处理器从文件中读取行,追加\endlinechar并(可能)重新编码该行,并将每行作为缓冲区输出到令牌处理器。令牌处理器读取缓冲区并生成令牌序列。令牌处理器的主要原因是(粗略地说):

  • 将每一个打包\csname成一个 token。

  • 将两个(或更多)空格合并为一个空格标记。

  • 用空格标记替换缓冲区末尾(即行尾)。

  • 生成\par标记而不是每个(视觉)空行。

  • 为每个生成的标记分配一个类别(catcode)。

有两种类型的 catcode:第一种指定给标记处理器本身(0、5\行尾、9 忽略字符、14 注释字符、15 禁用字符);第二种:其他 catcode。第一种类型的 catcode 永远不会出现在标记处理器的输出端。

扩展处理器扩展宏。这意味着宏处理仅使用来自令牌处理器的令牌序列,从这个角度看,行的原始结构是不可见的(在 catcodes 和 的默认设置下\endlinechar)。通过宏扫描行尾的任务与扫描单词之间的双倍空格的任务相当:这是不可能的,因为在这个处理级别上不存在双倍空格。

主处理器接受不可扩展的原始命令(作为扩展处理器的输出)并执行:分配或排版。

处理由主处理器控制:当主处理器需要命令(或命令参数)时,它会向扩展处理器发出请求。当扩展处理器需要来自输入流的新标记时,它会向标记处理器发出请求。当标记处理器需要新的缓冲区时,它会向输入处理器发出请求。最小数据存储在每一级处理器中。示例:

\catcode`x=14x aaa
\catcode`X=14 X bbb

第一行设置x为注释字符(如),但紧随其后的%字母具有 catcode 11(字母),因为在扫描原语的参数时,它被标记处理器触及。此时 x 的 catcode 为 11。第二行设置为注释字符。参数扫描以空格终止,原语在此之后进行赋值,并且下一个标记在 catcode 为 14时被标记处理器触及。因此可见但不可见(注释掉)。x14\catcodeX\catcodeXXaaabbb

您可以设置\endlinechar=something,但您必须考虑到此 endlinechar 首先附加到已读取行后的下一行。这就是为什么 egreg 的第一个解决方案将\quotenextline \endlinechar扫描的行。他的第二个解决方案利用了默认值为 13(即字符)的事实^^M。其 cactode 默认设置为 5(即将其替换为空格标记并停止读取当前行缓冲区),并将其替换为活动字符,该字符会执行一些工作并终止该组。

您也可以使用类似的技术\quotenextparagraph

\def\quotethisparagraph {\bgroup 
    ... do some starting work ...
    \def\par{\endgraf ... do some ending work ... \egroup}%
}

这种技术更好,因为它不会将文本扫描到参数中。因此 catcode 更改(如\verb|...|)将在此环境中起作用。您可以告诉用户(在有关 的文档中\quotethisparagraph),如果在此环境中需要更多段落,则\endgraf必须\par写入 或 空行。

答案3

以下只是一个“半概括”(expl3这只是egreg 提供的解决方案的确切地在问这个问题之前(只是接触的 catcodes^^M并使用辅助命令,受到的定义的启发\obeylines),但不幸的是,它没有用(我需要更多关于 catcodes 和组的训练,以及在哪里更改 catcodes 以及在哪里不更改)。

这不太重要,但只是使这个过程稍微自动化一些。

\documentclass{scrartcl}
\usepackage{xparse}

\ExplSyntaxOn
\group_begin:
  \char_set_catcode_other:N \^^M %
  \cs_new:Npn \cs_new_delimited_by_newline:Nn #1 #2 %
    { %
      \cs_new:Npn #1 %
        { %
          \group_begin: %
            \char_set_catcode_other:N \^^M %
            \use:c { __ \cs_to_str:N #1 } %
        } %
      \cs_new:cpn { __ \cs_to_str:N #1 } ##1 ^^M %
        { %
            #2 %
          \group_end: %
        } %
    } %
\group_end:
\cs_new_delimited_by_newline:Nn \quotethisline
  {
    \begin{quote} ``\emph{#1}'' \end{quote}
  }
\ExplSyntaxOff


\begin{document}
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
\quotethisline Lorem ipsum dolore sit amet.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
\end{document}

在此处输入图片描述

相关内容