如何定义一个环境,其中任何未定义的环境都是“已定义”的?

如何定义一个环境,其中任何未定义的环境都是“已定义”的?

我需要定义一个环境,在其中我可以简单地处理\begin{some string}some stuff\end{some string}任意字符串,并让它将这些字符串处理为环境(输出例如\textbf{some string:} somestuff)。环境还应接受修改其行为的可选参数。

诸如 enumerate 或 itemize 之类的预先存在的环境仍应在我的环境中工作。

我可以使用以下代码实现大部分功能:

\makeatletter
\def\ifEqString#1#2{\def\csa{#1}\def\csb{#2}\ifx\csa\csb }
\def\ifUnDefinedCs#1{\expandafter \ifx\csname#1\endcsname\relax}
\let\old@begin=\begin
\def\new@begin{\ifx[\next \expandafter\newXX@begin \else \expandafter\newX@begin \fi}
\def\newX@begin#1{\ifUnDefinedCs{#1}\newZ@begin{#1}\else\old@begin{#1} \fi}
\def\newZ@begin#1{\head@font{#1}\par\newenvironment{#1}{\let\head@font=\textit}{\relax}\old@begin{#1}}
\def\newXX@begin[#1]#2{\ifEqString{#1}{plain}--\else{#1}\fi {#2}\par\newenvironment{#2}{\let\head@font=\textit}{\relax}\old@begin{#2}}
\newenvironment{myenvironment}{\begingroup%
\let\head@font=\textbf
\def\begin{\futurelet\next\new@begin}
}{\endgroup}
\makeatother

但是,这会破坏tabular需要提供参数的现有环境。有没有更好的方法来编写代码而不破坏这些?

答案1

我认为你在这里必须做一些繁重的工作。简单的修补\begin无法完成这项工作,因为\begin必须能够偶尔读取可选和必需的参数。你最好只是声明一个自定义环境来满足你的需求。你甚至可以通过给它起一个好听的简短名字来保持你的输入简洁,例如(假设xparse可用):

\NewDocumentEnvironment{||}{ m o }{%
   \IfNoValueTF{#2}{%
      No optional argument
   }%
   {%
     Optional argument #2
   }%
   \textbf{#1:}}%
   {} % We don't need to do anything at the end

\begin{||}{some string} some stuff \end{||}

但如果您不想这样做,请声明将处理您的特殊环境的命令:

\NewDocumentCommand{\UndeclaredEnvironment}{ m o }{...}

这将把未声明的环境的名称作为其第一个必需参数,然后作为可选参数,您可以像我们上面的环境一样定义它。

现在到了手术时间。在我们进一步讨论之前,让我强调一下,这是一个坏的idea.texdoc source2e将为您提供带注释的 LaTeX 源代码。 的定义\begin出现在第 473 页的 D ltmiscen.dtx 部分中:

\DeclareRobustCommand*\begin[1]{%
  \UseHook{env/#1/before}%
  \@ifundefined{#1}%
    {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}% ❶
    {\def\reserved@a{\def\@currenvir{#1}%
        \edef\@currenvline{\on@line}%
        \@execute@begin@hook{#1}%
        \csname #1\endcsname}}%
  \@ignorefalse
  \begingroup\@endpefalse\reserved@a}

我们感兴趣的行是我用 ❶ 标记的行。您需要将上述内容复制到新命令(例如,\BadIdeaBegin使用\makeatletteractive)并将该行更改为:

    {\def\reserved@a{\def\@currenvir{#1}%
        \edef\@currenvline{\on@line}%
        \@execute@begin@hook{#1}%
        \UndeclaredEnvironment{#1}}}%

然后你可以让你的环境

\newenvironment{VeryBadIdea}{\let\begin\BadIdeaBegin}{}

事情就会按照你希望的方式进行。

相关内容