这里的答案可能很明显,但我找不到。我\newsavebox
在许多例程中使用它,用于不同的目的。这些都是全局保存的,我想这是一种相当宝贵的资源。
在所有情况下,将内容保存到盒子中后,盒子会立即用于各种用途。我不在乎覆盖以前的盒子内容(可能很大)。
为了节省资源,我决定用同一个盒子来装很多不同的东西
\newsavebox{\mybox}
我事先并不知道某个文档需要哪些特定的例程,也不想在源之外为每个框的使用声明一个公共框。因此,有多个声明\newsavebox{\mybox}
(或根本没有声明,具体取决于我正在做什么)。
\mybox
底线是,在重新创建它之前,如何测试它的存在? MWE 是:
\documentclass{article}
\newsavebox{\mybox}
\newsavebox{\mybox}
\begin{document}
\end{document}
答案1
用 定义的框\newsavebox
基本上只不过是相应框寄存器的包装器命令名称。检查宏名称即可,例如用\@ifundefined
。
\documentclass{article}
\newsavebox{\mybox}
\makeatletter
\@ifundefined{mybox}{%
\newsavebox{\mybox}%
}{}
\makeatother
\begin{document}
Foo
\end{document}
答案2
LaTeX 内核在通过 处理常规宏时提供了类似的方法\providecommand{<cs>}
。如果<cs>
已经存在,则什么也不会发生*,否则,\providecommand
其行为与 相同\newcommand
。可以复制此方法来创建\providesavebox
:
ABC
定义
\documentclass{article}
\makeatletter
\newcommand{\providesavebox}[1]{%
\begingroup
\escapechar\m@ne\xdef\@gtempa{{\string#1}}%
\endgroup
\expandafter\@ifundefined\@gtempa
{\newsavebox#1}%
{}%
}
\makeatother
\begin{document}
\providesavebox{\mybox}
\savebox{\mybox}{abc}
\usebox{\mybox}
\providesavebox{\mybox}
\savebox{\mybox}{def}
\usebox{\mybox}
\end{document}
当然,上述方法也有替代方案,因为引用框的方式与我们引用宏的方式相同。因此,您还可以使用如何在 LaTeX 中有条件地定义新命令?。
*
实际上,临时宏\@reserveda
是重新定义而不是提供的宏名。
答案3
作为替代方案,该stackengine
软件包提供了一个将内容放入已保存框中的命令\savestack{<name>}{<box content>}
。但是,无需使用\usebox
它来调用它,只需调用宏名称即可调用该框。
如果深入研究,就会发现调用\savestack{\mybox}{<content>}
实际上会将<content>
放入名为 的框中\myboxcontent
。宏\mybox
仅设置为,\usebox{\myboxcontent}
如 MWE 中所示。在内部,它使用它\@ifundefined
来确定是否需要创建框。
\documentclass{article}
\usepackage{stackengine}
\begin{document}
\savestack{\mybox}{A}
\mybox\par
\savestack{\mybox}{B}
\mybox{} is the same as \usebox{\myboxcontent}
\end{document}