重复使用 \newsavebox 并避免编译警告

重复使用 \newsavebox 并避免编译警告

这里的答案可能很明显,但我找不到。我\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}

在此处输入图片描述

相关内容