我试图创建一个环境,它既能显示文本,又能将内容存储在一个框中以供日后使用。为此,我需要使用环境的输入参数来生成命令名称,即\#1
。出于某种原因,我无法在 latex 中使用它。
\documentclass{article}
\newenvironment{testenv}[1]
{ \textbf{Test Environment}
\newsavebox{\#1}
\begin{lrbox}{\#1}
}
{
\end{lrbox} \usebox{\#1}
}
\begin{document}
\begin{pattern}{aaa}
test
\end{pattern}
\usebox{\aaa}
\end{document}
答案1
尝试这个:
\documentclass{article}
\newenvironment{pattern}[1]
{%
\newsavebox#1%
\lrbox#1
}
{%
\endlrbox
}
\begin{document}
\begin{pattern}{\aaa}
test
\end{pattern}
\usebox{\aaa}
\end{document}
您的代码的最大问题是您无法通过将反斜杠附加到未知文本(如#1
)来构造宏名称。这与 TeX 读取其输入的方式有关;当它看到中的内容时#1
,它已经停止构造名称了。您可以通过编写来解决这个问题\csname#1\endcsname
,但这有一些技术细节,不值得处理,因为您可以首先要求环境的参数pattern
是宏名称。
我要做的一个小改动(除了它不能按书面形式编译,因为你做了定义testenv
但使用了pattern
环境)是直接使用\lrbox
and\endlrbox
而不是\begin
and\end
结构。这允许 LaTeX 正确跟踪它是你的打开的环境,而不是lrbox
您在其中使用的环境。(如果您搞砸了,它会告诉您lrbox
没有正确关闭,这在技术上是正确的,但如果您没有lrbox
在文档中明确写出,则并不总是有用的)。
答案2
节省盒子的问题环境是环境内的所有代码通常都是本地的。'lrbox' 环境实际上脱离了其自己的组,以确保框分配是周围范围的一部分。这使得将其作为其他环境的一部分包含起来很困难。使用“纯 TeX 样式” \lrbox
..\endlrbox
会因为特殊的组处理而导致问题。
您可以复制内部代码lrbox
(参见文件latex.ltx
),也可以使用全局分配,这将使您的 B 级分数减分,但实现起来要简单得多,并且可能适合您的情况。您可以使用较低级别的 TeX 代码(\setbox
使用\bgroup
和\egroup
而不是括号)来存储环境内容。您需要添加内部颜色分组语句,以确保所有颜色宏(如果有)也正确存储在框中。
\documentclass{article}
\makeatletter
\newenvironment{patternn}[1]{%
\par % I think you should start a paragraph first, but it's up to you
\textbf{Pattern}%
\newsavebox{#1}%
\global\setbox#1\hbox\bgroup\color@setgroup
}{%
\color@endgroup\egroup
\usebox{#1}%
}
\makeatother
\begin{document}
\begin{patternn}{\aaa}
test
\end{patternn}
And now try again:
\usebox{\aaa}
\end{document}
答案3
感谢大家的回复,我确实学到了很多关于宏/环境工作原理的知识。我将你们的回答结合到以下内容中,让它完全按照我想要的方式工作!:)
\documentclass{article}
\usepackage{environ}
\NewEnviron{patternn}[1]
{ \textbf{Pattern} \BODY \newsavebox{#1} \global\sbox{#1}{\BODY} \usebox{#1}}
\begin{document}
\begin{patternn}{\aaa}
test
\end{patternn}
And now try again:
\usebox{\aaa}
\end{document}