我想知道您是否可以“重新打开”一个环境来扩展其定义,类似于在 Ruby 等编程语言中您可以在代码中的任何位置重新打开一个类/模块并扩展其定义。
例如,假设你的文档中有这样的部分:
\newenvironment{myenv}{
\newcommand\a{}
}{}
然后在文档的后面执行以下操作:
\reopenenvironment{myenv}{
\newcommand\b{}
}{}
这样最终的结果就是这样的:
\newenvironment{myenv}{
\newcommand\a{}
}{}
\reopenenvironment{myenv}{
\newcommand\b{}
}{}
其功能应等同于:
\newenvironment{myenv}{
\newcommand\a{}
\newcommand\b{}
}{}
想知道 Latex 中是否存在类似的东西。理由是假设您有一个包含一些通用定义的类。您可能希望多次重复使用各种格式的特定图表,但没有必要将其添加到类定义中。相反,您只需在文档中内联定义它并在需要的地方使用它。
这个问题的另一种变体(或可能实现的另一种方法)是向现有命令添加新的条件块。假设我们有\a
:
\newenvironment{myenv}{
\newcommand\a[1]{
\ifthenelse{\equal{##1}{\string foo}}
{\typeout{foo}}
{}
}
}{}
然后您可以在运行时扩展这样的定义:
\reopenenvironment{myenv}{
\reopencommand\a[1]{
\ifthenelse{\equal{##1}{\string bar}}
{\typeout{bar}}
{}
\super{}
}
}{}
这样,您可以在运行时扩展它,以便保留 API:
\begin{myenv}
\a{foo}
\a{bar}
\end{myenv}
想知道是否存在类似的东西,或者是否有一种正常的方法来用乳胶实现这一点。
我希望能够执行以下操作:
\begin{athing}{label=baz}
\stuff
\stuff
\stuff
\stuff
\end{athing}
然后将其用作:
\begin{myenv}
\a{baz}
\end{myenv}
也许可以通过本地键/值存储来实现这一点。也就是说,
kvstore = {
foo: athing
bar: athing
baz: athing
}
\newcommand\a[1]{
kvstore[##1]
}
也许这种事情是可能的,如果可能的话,那将是另一种解决方案。
总而言之,我希望能够拥有一个 API:
myapi{somelabela}
myapi{somelabelb}
...
这样就可以在运行时使用更多定义进行扩展。这里概述的 3 种方法只是初步想法,我是 Latex 的新手。非常感谢您的帮助。
答案1
LaTeX3 (expl3) 实际上有一个很好的界面来处理代币列表,它或多或少具有您正在寻找的功能。
编辑:意识到我(之前)的第一个方法并不规范。这个方法更好,也更不老套:
在 LaTeX 中,我怀疑规范方法是使用宏钩子,或者更具体地说\g@addto@macro
。这就是\AtBeginDocument
工作原理!
\makeatletter
\def\somehook{hello}
\g@addto@macro\somehook{ world}
\somehook %<- prints hello world
\makeatother
该命令实际上会触发您执行时定义的\begin{myenv}
宏。因此:\myenv
\newenvironment
\makeatletter
\newenvironment{myenv}{hello}{}
\g@addto@macro\myenv{ world}
\begin{myenv}
!
\end{myenv}
\makeatother
打印hello world!
以下是我不太规范的方法:
不管怎样,你可以用纯 TeX 自己做,或多或少:你可以做的一个“黑客”是
\newenvironment{myenv}{Hello}{}
\let\oldMyenv = \myenv
\def\myenv{\oldMyenv world}
\begin{myenv}
!
\end{myenv}
输出结果Hello world !
为 。这可以推广到
\makeatletter
\def\removebs#1{\if#1\@backslashchar\else#1\fi}
\def\macname#1{\expandafter\removebs\string#1}
\def\reopencommand#1#2{
\def\mname{\macname{#1}}
\let\oldCommand#1
\expandafter\gdef\csname \mname\endcsname{\oldCommand #2}
}
\def\hello{hello}
\reopencommand{\hello}{ world}
\hello
\makeatother