在 LaTeX3 中定义嵌套命令的替代方法

在 LaTeX3 中定义嵌套命令的替代方法

由于 LaTeX 惯例似乎是使用全局作用域而非局部作用域命令/环境(现在出于复杂的原因,这很有意义),我想知道如何处理我想要同一命令/环境的两种不同实现的情况姓名

例如,假设我有这个:

\NewDocumentEnvironment{myenva}{} {
  \NewDocumentCommand{\mycmd}{m} {

  }
}

\NewDocumentEnvironment{myenvb}{} {
  \NewDocumentCommand{\mycmd}{m} {

  }
}

我不会将其写成嵌套的形式,而是将其写成类似这样的形式:

\NewDocumentCommand{\mycmd}{} {
  \if environment is myenva {
    \typeout{myenva}
  }

  \if environment is myenvb {
    \typeout{myenvb}
  }

  \else {
    throw error This needs to be in myenva or myenvb.
  }
}

\NewDocumentEnvironment{myenva}{} {

}

\NewDocumentEnvironment{myenvb}{} {

}

以下是 MWE:

\documentclass[a4paper]{article}

\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\mycmd}{} {
  \if environment is myenva {
    \typeout{myenva}
  }

  \if environment is myenvb {
    \typeout{myenvb}
  }

  \else {
    \PackageError{mypackage}{This needs to be in myenva or myenvb.}{}
  }
}

\NewDocumentEnvironment{myenva}{} {

}

\NewDocumentEnvironment{myenvb}{} {

}

\begin{document}

\begin{myenva}
  Hello
  \mycmd{}
\end{myenva}

\begin{myenvb}
  world
  \mycmd{}
\end{myenvb}

\end{document}

想知道这是否是正确的方法,以及如何使其工作(即检查它是否在正确的环境中)。另一种方法是重新打开命令定义如果这在 LaTeX3 中是可能的,那么它会稍微干净一些/有关注点分离。

\NewDocumentCommand{\mycmd}{} {
  \if environment is myenva {
    \typeout{myenva}
  }
}

% something along these lines:

\RenewDocumentCommand{\mycmd}{}{
  \super{}

  \if environment is myenvb {
    \typeout{myenvb}
  }
}

不确定如何让它工作(如何检查正确的环境)。另外,我在某处读到,如果环境错误,则可能抛出错误可能是一个不错的选择,所以不确定是否应该包括这一点。可能对调试和使其更强大有用。

另外,我想避免传递环境名称,例如这样:

\mycmd{myenva}
\mycmd{myenvb}

答案1

在 LaTeX2e 中,当前环境名称存储在 中\@currenvir。这可用于定义\mycmd调用正确的命令。所以我要么使用这个:

\documentclass[]{article}

\usepackage{xparse}
\makeatletter
\NewDocumentCommand\mycmd{}{\csname mycmd@\@currenvir\endcsname}
\NewDocumentCommand\mycmd@enva{}{myenva}
\NewDocumentCommand\mycmd@envb{}{myenvb}
\NewDocumentEnvironment{enva}{}{}{}
\NewDocumentEnvironment{envb}{}{}{}
\makeatother

\begin{document}
\begin{enva}
  \mycmd
\end{enva}

\begin{envb}
  \mycmd
\end{envb}
\end{document}

或这个:

\documentclass[]{article}

\usepackage{xparse}
\makeatletter
\NewDocumentCommand\mycmd@enva{}{myenva}
\NewDocumentCommand\mycmd@envb{}{myenvb}
\NewDocumentEnvironment{enva}{}{\let\mycmd\mycmd@enva}{}
\NewDocumentEnvironment{envb}{}{\let\mycmd\mycmd@envb}{}
\makeatother

\begin{document}
\begin{enva}
  \mycmd
\end{enva}

\begin{envb}
  \mycmd
\end{envb}
\end{document}

第一个问题是,如果嵌套环境,它将失败,enva因为\@currenvir将是该环境的名称。因此后者(\let指向\mycmd正确的定义)似乎更可靠。

相关内容