使用 \usebox 定义多个标签

使用 \usebox 定义多个标签

我想复制一些内容而不重新定义其标签。例如,

\newbox{\foobox}
\sbox{\foobox}{\vbox{\section{Foo}\label{sec:foo}}
\usebox{\foobox}
\usebox{\foobox}

会发出警告,因为sec:foo被定义多次。有什么方法可以阻止第二个\usebox写入辅助文件吗?

答案1

我假设您希望保留第一个,\label并禁用其他。然后使用以下技巧:

  1. 该框由两个命令创建\BeginIgnoreAux{<id>}\EndIgnoreAux位于原始内容之前和之后。这些宏将标记与结果一起写入文件.aux,标签内容位于两者之间。
  2. 如果.aux文件被读取,则第一次执行标签 stuff 时会照常执行。如果\BeginIgnoreAux{<id>}使用相同的 多次调用<id>,则忽略标签 stuff。这可以避免重复的标签。
  3. LaTeX 读取.aux文件两次。例如,在文档末尾.toc写入文件。因此,宏\AuxResetIgnoreStuff会清除<id>s。
\documentclass{article}

\makeatletter
\global\let\AuxResetIgnoreStuff\@empty
\usepackage{auxhook}
\AddLineBeginAux{\string\AuxResetIgnoreStuff}

% Macros inside the `.aux' file
\newcommand*{\AuxBeginIgnore}[1]{%
  \@ifundefined{ignore@#1}{%
    \global\expandafter\let\csname ignore@#1\endcsname\@empty
    \expandafter\g@addto@macro\expandafter\AuxResetIgnoreStuff
    \expandafter{%
      \expandafter\global\expandafter\let\csname ignore@#1\endcsname\relax
    }%
  }\AuxSkip
}
\def\AuxSkip#1\AuxEndIgnore{}
\let\AuxEndIgnore\relax

% User commands
\newcommand*{\BeginIgnoreAux}[1]{%
  \protected@write\@auxout{}{%
    \string\AuxBeginIgnore{#1}%
  }%
}   
\newcommand*{\EndIgnoreAux}[1]{%
  \protected@write\@auxout{}{%  
    \string\AuxEndIgnore
  }%
}   
\makeatother

\begin{document}
\tableofcontents
\newbox{\foobox}
\sbox{\foobox}{%
  \BeginIgnoreAux{foo}%
  \vbox{\section{Foo}\label{sec:foo}}%
  \EndIgnoreAux
}
\noindent
\usebox{\foobox}
\usebox{\foobox}

\noindent
Reference to the first label: \ref{sec:foo}.
\end{document}

结果

.aux文件包含:

\relax 
\AuxResetIgnoreStuff
\AuxBeginIgnore{foo}
\@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}}
\newlabel{sec:foo}{{1}{1}}
\AuxEndIgnore
\AuxBeginIgnore{foo}
\@writefile{toc}{\contentsline {section}{\numberline {1}Foo}{1}}
\newlabel{sec:foo}{{1}{1}}
\AuxEndIgnore

以及.toc文件:

\contentsline {section}{\numberline {1}Foo}{1}

相关内容