环境singlepar
应该包含一个段落。这意味着它包装的代码中不能有段落中断:
\begin{singlepar}
Right.
\end{singlepar}
\begin{singlepar}
Wrong.
Wrong!
\end{singlepar}
我目前的方法是:
% \usepackage{xparse}
\NewDocumentEnvironment{singlepar}{}
{%
% Ensure that this environment starts a new paragraph
\par%
% Save normal \par for later use
\let\oldparforprivateuse\par%
% Use of \par should abort the typesetting process
\def\par{\typeout{DISALLOWED}\QUIT}%
\ignorespaces%
}
{%
% Issue a paragraph break
\oldparforprivateuse%
}
但是,感觉不对。至于实际原因,我感觉这个 hack 不能处理所有情况。我相信仍然可能存在段落中断;例如,通过在环境之前使用\let
alias的定义:\par
\let\takethis\par
\begin{singlepar}
I'm gonna stab you in the back.
\takethis
Take this!
\end{singlepar}
我已经检查过xparse
文档并且似乎没有办法像使用宏参数那样抑制段落中断(宏参数中不允许使用段落中断,除非+
在宏声明中段落中断前面有)。
如何才能在代码的某一部分中完全禁止段落中断?
编辑:我说的“禁止”是指他们中止编译,以便人们注意到它。这更多是为了诊断我自己在输入文本时的错误。
答案1
我不认为你想参与\par
其中结尾第一段中你真正想要允许的,对于一个段落环境来说,很自然地允许
\begin{singlepar}
aaa
\end{singlepar}
如果你犯了错误,这是不允许的\par
。
你不想允许的是第二段开始这就是\everypar
对于事物(重新)定义仍然存在一些担忧,\everypar
但这将捕获许多情况,并允许上述示例。
\documentclass{article}
%\newenvironment{singlepar}
%{\def\par{\PackageError{pkg}{par DISALLOWED}{}\ignorespaces}}%
%{}
\newenvironment{singlepar}
{\everypar{\everypar{\PackageError{pkg}{par DISALLOWED}{}}}\ignorespaces}%
{}
\begin{document}
\begin{singlepar}
aaa
\end{singlepar}
\begin{singlepar}
aaa
b
\end{singlepar}
\end{document}
答案2
你的感觉是对的。
\begin{singlepar}
Wrong.\endgraf Wrong.
\end{singlepar}
你会得到一个段落分隔符,并且不会出现错误。LaTeX 格式
\let\endgraf\par
因此使其\endgraf
等同于原始的\par
。 也\@@par
等同于原始的\par
,但它不应该困扰你,因为它@
的名称中有。
你可以说
\makeatletter
\newenvironment{singlepar}
{%
% Ensure that this environment starts a new paragraph
\@@par
% Save normal \par for later use
% Use of \par should abort the typesetting process
\def\par{\typeout{DISALLOWED}\QUIT}%
\let\endgraf\par
}
{%
% Issue a paragraph break
\@@par
}
\makeatother
但它并不能解决问题,因为某些包可能会在环境中说\let\foo\@@par
然后\foo
导致段落中断。
由于不可能知道哪些控制序列指向原始\par
内存位置以了解其含义(如\endgraf
和\@@par
),因此该问题实际上无法解决。
可以考虑用 的变体吸收环境主体,从而\NewEnviron
形成非\long
宏(标准操作是像 那样做\newcommand
),但这也不能解决问题。非\long
宏仅禁止令牌 \par
在它的参数中,但会很乐意接受\endgraf
或任何与原始的等同的控制序列\par
。
最后,无法禁用原语。您可以通过重新定义来隐藏它,但已经控制它的序列\let
将继续起作用。