如何防止在新环境中引用枚举?

如何防止在新环境中引用枚举?

我定义了一个指导框环境,它类似于 longtable 环境,只是计数器/标题标签和引用标签不同。这工作正常,除非我在此环境中使用枚举,而 itemize 不会出现任何问题,请参见下面的示例:

\documentclass{report}
\usepackage{caption}
\usepackage{longtable,ltcaption}
\usepackage{hyperref}
\usepackage{newfloat}
\usepackage{xcolor}
\usepackage{enumitem}
\usepackage{colortbl}


%% Formatting table colors
\definecolor{guidancebox}{gray}{0.95}

\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}

%% New environment for guidance boxes
\DeclareFloatingEnvironment{guidancebox}[Guidance box][List of guidance boxes]
\newcommand*{\guidanceboxautorefname}{Guidance box}
\renewenvironment{guidancebox}{
    \renewcommand\LTcaptype{guidancebox}
    \longtable
}{\endlongtable}

\begin{document}

\begin{guidancebox}{C{0.5\textwidth}}
    \hline
    \rowcolor{guidancebox} This guidance box provides guidance on the following items:
    \begin{itemize}
        \item first item
        \item second item
    \end{itemize}\\
    \rowcolor{guidancebox}\\
    \hline
    \caption{caption of this guidance box.}
    \label{guide}
\end{guidancebox}

Look at \autoref{guide} above. Now look at \autoref{guide2} below:

\begin{guidancebox}{C{0.5\textwidth}}
    \hline
    \rowcolor{guidancebox} This guidance box provides guidance on the following numbered items:
    \begin{enumerate}
        \item first item
        \item second item
    \end{enumerate}\\
    \rowcolor{guidancebox}\\
    \hline
    \caption{caption of this guidance box.}
    \label{guide2}
\end{guidancebox}

\end{document}

输出结果如下:

在此处输入图片描述

显然,我希望引用的是“指导框 2”而不是“项目 2”。有人知道如何解决这个问题吗?

提前致谢!

蒂姆

答案1

LaTeX 2ε 中与交叉引用相关的概念

LaTeX 2ε 提供编号部分的项目和一个交叉引用编号部分项目的机制

编号分区项目\chapter由诸如、、、(等)之类的宏生成,\section(在类似枚举的环境中)和(在用于表示带有编号标题的浮动对象的环境中,如-environment或-environment)。\subsection\subsubsection\item\captionfiguretable

交叉引用编号部分项目的机制由以下部分组成

  • 交叉引用标签。 A交叉引用标签是一个被赋予名称并保存交叉引用所需数据的数据记录。

  • 该宏\label用于将交叉引用标签写入 .aux 文件/用于将交叉引用所需的交叉引用数据记录(包括该记录的名称)写入 .aux 文件。

  • 交叉引用宏\ref,,,,,,等。交叉引用宏用于访问交叉引用数据记录并将所需的交叉引用短语放入输出文件(.pdf 文件)中\pageref\nameref\autoref\hyperref

    您 始终需要为这些宏提供一个参数, 该 参数包含交叉引用数据记录的名称/包含交叉引用标签的名称 - 例如,,,,,,,, 等等 。\label{⟨name of cross-referencing-label⟩}\ref{⟨name of cross-referencing-label⟩}\pageref{⟨name of cross-referencing-label⟩}\nameref{⟨name of cross-referencing-label⟩}\autoref{⟨name of cross-referencing-label⟩}\hyperref[⟨name of cross-referencing-label⟩]{⟨text⟩}

有一些元素将项目编号分段交叉引用编号部分项目的机制

保存内部宏当前的交叉引用数据。(当在下文中进一步详细说明时,您会在这种情况下偶然发现包含短语“ @current”的宏名称,例如 \@currentlabel\@currentlabelname\@currentHref。)

编号分段的项目内部使用宏\refstepcounter

  • 都用于增加计数器
  • 并且——如果已加载 hyperref 包——用于放置超链接的锚点=目标=命名目的地
  • 用于重新定义/更新一些保存当前交叉引用数据的内部宏。

当 hyperref-package 加载编号部分的项目时,内部使用宏\NR@gettitle来更新该内部宏,该宏保存相关编号部分项目的名称/标题。该宏也属于保存当前交叉引用数据的宏。

简而言之,你可以说在 LaTeX 运行期间,当前交叉引用数据

  • 总是源于迄今为止遇到的编号部分的最后一项。
  • 总是可以通过扩展保存当前交叉引用数据的内部宏来访问。

正如前面所述,该命令的 作用是将交叉引用所需的交叉引用数据记录(包括该记录的名称)写入 .aux 文件。 该记录的名称来自 -argument 。 交叉引用数据来自使用/扩展保存当前交叉引用数据的内部宏。\label{⟨name of cross-referencing-label⟩}
⟨name of cross-referencing-label⟩

写入 .aux 文件的交叉引用数据记录依次被交叉引用宏 ( 、、、、、\ref等)使用。\pageref\nameref\autoref\hyperref

实际上,如果存在的话,上一次 LaTeX 运行中的 .aux 文件会在当前 LaTeX 运行开始时被读取。因此,为上一次 LaTeX 运行期间由宏写入 .aux 文件的每个交叉引用数据记录定义
一个宏。因此,该宏扩展为由宏写入 .aux 文件的交叉引用数据记录以及上一次 LaTeX 运行期间的相应数据。因此,当前 LaTeX 运行中引用宏传递/显示的交叉引用数据源自上一次 LaTeX 运行。 在当前 LaTeX 运行开始时读取上一次 LaTeX 运行期间创建的 .aux 文件之后,上一次 LaTeX 运行的 .aux 文件会被销毁,而 .aux 文件会在当前 LaTeX 运行期间重新创建。 引用宏只是扩展了它们将引用的标签所属的宏,并从扩展/获得的交叉引用数据记录中提取所需的数据。(例如,需要页码、需要章节号,……) 在 LaTeX 运行结束时,仍然可以通过宏访问来自上一次 LaTeX 运行的交叉引用数据记录,而当前 LaTeX 运行期间创建的交叉引用数据记录现在可通过新创建的 .aux 文件获得。 因此,在 LaTeX 运行结束时,将读取新创建的 .aux 文件,以将来自上一次 LaTeX 运行的交叉引用数据记录与当前 LaTeX 运行期间写入的交叉引用数据记录进行比较。如果交叉引用数据发生变化,因此需要另一次 LaTeX 运行以使交叉引用命令显示更改的数据,则将通过控制台和 .log 文件提供一条消息,通知用户需要重新运行 LaTeX :)\r@⟨name of cross-referencing-label⟩\label\r@⟨name of cross-referencing-label⟩\label⟨name of cross-referencing-label⟩

\r@⟨name of cross-referencing-label⟩\pageref\ref
\r@⟨name of cross-referencing-label⟩
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.

为什么要采用.aux-file-route?

我没有看到任何其他方法可以提供交叉引用后文本中编号章节项目所需的数据。


现在我试图对“机械的齿轮如何啮合”给出一个粗略的概述。

现在我们来看一些细节:

当 LaTeX 遇到一个\label命令时,这将导致在 LaTeX 在遇到/处理该命令时即将构建的页面\label被发送出去时,将交叉引用数据记录写入辅助文件。
(内部\immediate\write不使用 来作为底层的写入机制,因为这可能会导致错误的页码和引用,\pageref因为在处理相关命令时,相关页面的构建过程可能尚未完成\label,因此页面计数器在处理相关命令时可能仍保留先前构建的页面的值。而是使用\label所谓的“延迟”,即没有前缀的,因此在处理相关命令时不会执行,但在发送 LaTeX 在遇到/处理相关命令时即将构建的页面时会执行。 实际上,内部使用了一种巧妙的组合(会立即执行非受保护控制序列的完全扩展)和延迟(不会立即扩展内容,但在发送相关页面时会扩展和写入内容)来实现底层机制。)\write\write\immediate\label\label
\protected@edef\write\protected@write

当 LaTeX 遇到命令时,写入辅助文件的交叉引用数据记录\label被组织成所谓的\newlabel条目。\newlabel辅助文件中的条目具有以下模式:

当。。。的时候超链接- 程序包已加载:

\newlabel{<Name of cross-referencing-label>}%
         {%
           {<The printing of the value which that counter had right
             after having been "refstepped" which was incremented via
             \refstepcounter as the last one before encountering the
             \label-command.
             [\refstepcounter in turn is called by macros like \chapter,
             \section, \item (within an enumerate-like environment), 
             \caption (within environments for denoting floating objects
             with numbered captions like the figure-environment or the
             table-environment.)]
             \refstepcounter provides this piece of data to the \label-
             command by (re)defining the macro \@currentlabel to provide
             the expansion of the sequence \p@<counter>\the<counter>
             belonging to the <counter> that is "refstepped".
             This piece of data is retrieved by the \ref-command.>%
           }%
           {<The printing of the number of the page which LaTeX was about
             to  build when encountering the \label-command.
             This piece of data comes from expanding the macro \thepage 
             at the time of shipping out the page.
             This piece of data is retrieved by the \pageref-command.>%
           }%
           {<The name/title of the sectioning-item which caused
             \refstepcounter to increment the counter mentioned above.
             If, e.g., the causing sectioning-item was a command
             \section{About mice and elephants}, this will be the phrase
             "About mice and elephants". If, e.g., the causing
             sectioning-item was a a table-environment or a figure-
             environment, this will be the phrase "table 4" or the phrase
             "figure 5". If, e.g., the causing sectioning-item  was an
             \item-command within an enumerate-environment, this will be
             the phrase "item 23".
             This piece of data is to be provided by the items of
             sectioning via (re)defining the macro \@currentlabelname.
             Redefining  \@currentlabelname is not done by the macro
             \refstepcounter but often is done by the macro \NR@gettitle.
             This is because \refstepcounter only takes the name of a
             LaTeX-counter as its argument for dealing with that
             counter and with named destinations/targets/anchors related
             to that counter and therefore has no information about
             the name/title of the corresponding item of sectioning.
             Info about the name/title of the corresponding item of
             sectioning often is passed to \NR@gettitle by sectioning-
             commands. \NR@gettitle in turn calls \GetTitleString for
             pre-processing things and hereby handling things that are
             undesired when referencing and then redefines
             \@currentlabelname. E.g., if somebody does
             \section{Title of the section\label{label of the section}}
             , then you don't want the label to be placed with each
             reference to the title of the section. Therefore the
             \label-command needs to be removed. \GetTitleString does
             such things and more.
             This piece of data is retrieved by the \nameref-command.>%
           }%
           {<The name of the anchor for hyperlinks whose automatic
             placement was caused by the \refstepcounter-command
             mentioned above, that also incremented the counter mentioned
             above.
             The sequence which forms the name of the counter incremented
             by \refstepcounter as the last one before encountering the
             \label-command usually is a subset of the sequence that
             forms the name of the anchor that was placed automatically
             as the last one by \refstepcounter (or by \phantomsection as
             a special case) before the \label-command in question was
             encountered.
             In oder to ensure unique anchor names, the sequence forming
             the anchor-name besides the counter-name has elements that
             come from expanding \theH<counter>. Therefore with the 
             hypperref package to each <counter> a macro \theH<counter>
             must exist which expands to that counter's value in a way
             where uniqueness of names of anchors is ensured throughout
             the entire document.
             \refstepcounter will provide this piece of data to the 
             \label-command by (re)defining the macro \@currentHref.
             This piece of data is retrieved by the \autoref-command and
             by all other cross-referencing-commands that besides 
             delivering a textual phrase also deliver a hyperlink, e.g.
             \ref, \pageref,  \nameref, \hyperref. (The starred variants
             \ref*, \pageref*, \nameref* do not deliver hyperlinks.)>
           }%
           {<An empty data-field. In case the auxiliary-file in question 
             does not belong to this document but is imported by the
             command \externaldocument of the xr package or the 
             xr-hyper-package, this will hold the url under which the
             referenced external document can be found.  
             That url is provided via `\externaldocument` at the time
             of importing the referencing-data from the external  
             document's .aux-files.
             This piece of data is retrieved by all cross-referencing-
             commands that besides delivering a textual phrase also
             deliver a hyperlink.>
           }%
         }%

当没有加载任何附加包时:

\newlabel{<Name of cross-referencing-label>}%
         {%
           {<The printing of the value which that counter had right
             after having been "refstepped" which was incremented via
             \refstepcounter as the last one before encountering the
             \label-command.
             [\refstepcounter in turn is called by macros like \chapter,
             \section, \item (within an enumerate-like environment), 
             \caption (within environments for denoting floating objects
             with numbered captions like the figure-environment or the
             table-environment.)]
             \refstepcounter provides this piece of data to the \label-
             command by (re)defining the macro \@currentlabel to provide
             the expansion of the sequence \p@<counter>\the<counter>
             belonging to the <counter> that is "refstepped".
             This piece of data is retrieved by the \ref-command.>%
           }%
           {<The printing of the number of the page which LaTeX was about
             to  build when encountering the \label-command.
             This piece of data comes from expanding the macro \thepage 
             at the time of shipping out the page.
             This piece of data is retrieved by the \pageref-command.>%
           }%
         }%

在当前 LaTeX 运行开始时,读取上一次 LaTeX 运行期间创建的辅助文件,从而\newlabel执行其中的所有条目,处理\newlabel条目会产生一个宏,该宏在加载 hyperref 的情况下扩展为五个,在未加载 hyperref 的情况下扩展为两个未分隔/括号嵌套的项,每个项都保存其数据。这些未分隔/括号嵌套的项又可以用作处理未分隔参数的宏的参数。\r@⟨name of cross-referencing-label⟩

交叉引用命令(例如或或或)将扩展相应的宏并选择创建所需引用所需的那些数据片段保存参数。\ref{⟨name of cross-referencing-label⟩}\pageref{⟨name of cross-referencing-label⟩}\autoref{⟨name of cross-referencing-label⟩}\nameref{⟨name of cross-referencing-label⟩}\hyperref[⟨name of cross-referencing-label⟩]{⟨text⟩}\r@⟨name of cross-referencing-label⟩

在当前 LaTeX 运行结束时,将读取在当前 LaTeX 运行期间创建的辅助文件,并\newlabel执行其中的所有条目,\newlabel将重新定义命令所依据的某些内容,以便这次处理条目\newlabel会将其内容与相应宏的扩展进行比较\r@...,如果发现差异,则会导致 LaTeX 在 LaTeX 运行结束时通知用户需要重新运行 LaTeX:LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.这样,在当前 LaTeX 运行结束时,将保存在宏中\r@且来自上一次 LaTeX 运行的数据与来自当前 LaTeX 运行的数据进行比较,以检测交叉引用的数据是否已更改,从而检测是否需要在下一次 LaTeX 运行中重新运行 LaTeX,以显示来自本次 LaTeX 运行的交叉引用数据。

现在让我们看一下导致您所遇到的交叉引用问题的模糊性:

上面说了:生成编号分段项的宏—例如,,,,,\chapter(等等\section),(在类似枚举的环境中),(在用于表示带有编号标题的浮动对象的环境,如-环境或-环境)—内部用于增加计数器和放置超链接的锚点以及重新定义/更新一些保存当前交叉引用数据的内部宏,如:和。 生成编号分段项的宏通常在内部用于重新定义。\subsection\subsubsection\item\captionfiguretable\refstepcounter\@currentlabel\@currentHref
\NR@gettitle\@currentlabelname

因此,\label-command 将导致在下一个 LaTeX 运行中向引用命令提供由最后一个\refstepcounter-command 提供的数据,以及由\NR@gettitle在本次 LaTeX 运行中在\label所讨论的 -command 之前发生的最后一个 -command 提供的数据。

重新定义/更新保存当前交叉引用数据的内部宏的情况很有趣:

\refstepcounter重新定义/更新宏\@currentlabel已在 LaTeX2e 内核中实现。
重新定义/更新此宏仅限于当前范围

\NR@gettitle重新定义/更新宏 \@currentlabelname实现于超链接包裹/包裹内名称引用通过包中的宏获取标题字符串.
重新定义/更新此宏仅限于当前范围

\refstepcounter重新定义/更新宏\@currentHref实现于超链接包。
重新定义/更新此宏不仅限于当前范围,而是是全球性的

这种局部更新和全局更新混合产生的一个奇怪的效果是:

如果计数器在局部作用域内被“refstepped”,例如,在枚举环境中的项目中发生这种情况,并且\label在该局部作用域关闭之后立即放置一个,\@currentlabel则将保存在打开该局部作用域之前作为最后一个“refstepped”的计数器的值,同时\@currentHref将保存在关闭该局部作用域之前作为最后一个放置的锚点的名称\refstepcounter

在这种情况下,例如, 传递的文本短语\ref将表示在打开本地范围之前发生的最后一个分段项的编号,而单击 创建的超链接\ref不会导致该分段项,但会导致在关闭所讨论的本地范围之前发生的最后一个分段项。

由于\autoref依赖于从锚点名称派生计数器名称(它需要计数器名称来调用适当的-macros / -macros),您还可能会得到奇怪的混合,包括在关闭本地范围之前作为最后一个“refstepped”的计数器的名称和在打开所讨论的本地范围之前作为最后一个“refstepped”的计数器的值。\⟨counter⟩autorefname\⟨counter⟩name

例如,以下面这个例子,

  • \ref{ShouldReferToSectionThree}产生对第 3 节的文本引用,而超链接指向第一项。

  • \autoref{ShouldReferToSectionThree}产生对“项目 3”的文本引用,但实际上并不存在项目 3,并且会产生指向第一项的超链接。

  

\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{Section One}
\section{Section Two}
\section{Section Three}
\newpage
\begin{enumerate}
\item First Item.
\end{enumerate}
\label{ShouldReferToSectionThree}

section \ref{ShouldReferToSectionThree}

\autoref{ShouldReferToSectionThree}

\end{document}

在此处输入图片描述

在此处输入图片描述

根据经验法则,\label将 尽可能靠近您想要引用的那些部分的项目放置:

\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{Section One}
\section{Section Two}
\section{Section Three}
\label{ShouldReferToSectionThree}%
\newpage
\begin{enumerate}
\item\label{ShouldReferToFirstItem} First Item.
\end{enumerate}

section \ref{ShouldReferToSectionThree}

\autoref{ShouldReferToSectionThree}

item \ref{ShouldReferToFirstItem}

\autoref{ShouldReferToFirstItem}

\end{document}

在此处输入图片描述

在此处输入图片描述

将此经验法则应用到您的代码中可得出:

\documentclass{report}
\usepackage{caption}
\usepackage{longtable,ltcaption}
\usepackage{hyperref}
\usepackage{newfloat}
\usepackage{xcolor}
\usepackage{enumitem}
\usepackage{colortbl}


%% Formatting table colors
\definecolor{guidancebox}{gray}{0.95}

\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}

%% New environment for guidance boxes
\DeclareFloatingEnvironment{guidancebox}[Guidance box][List of guidance boxes]
\newcommand*{\guidanceboxautorefname}{Guidance box}
\renewenvironment{guidancebox}{%%%%%
    \renewcommand\LTcaptype{guidancebox}%%%%%
    \longtable
}{\endlongtable}

\begin{document}

\begin{guidancebox}{C{0.5\textwidth}}
    \hline
    \rowcolor{guidancebox}%
    \label{guide}%<--------------------
    This guidance box provides guidance on the following items:
    \begin{itemize}
        \item first item
        \item second item
    \end{itemize}\\
    \rowcolor{guidancebox}\\
    \hline
    \caption{caption of this guidance box.}%
\end{guidancebox}

Look at \autoref{guide} above. Now look at \autoref{guide2} below:

\begin{guidancebox}{C{0.5\textwidth}}
    \hline
    \rowcolor{guidancebox}%
    \label{guide2}%<--------------------
    This guidance box provides guidance on the following numbered items:
    \begin{enumerate}
        \item first item
        \item second item
    \end{enumerate}\\
    \rowcolor{guidancebox}\\
    \hline
    \caption{caption of this guidance box.}%
\end{guidancebox}

\end{document}

在此处输入图片描述

答案2

使用cleveref更安全。

\documentclass{report}

\usepackage{caption}
\usepackage{longtable,ltcaption}
\usepackage{newfloat}
\usepackage[table]{xcolor}
\usepackage{enumitem}
\usepackage{hyperref}
\usepackage{cleveref}

%% Formatting table colors
\definecolor{guidancebox}{gray}{0.95}

\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}

%% New environment for guidance boxes
\DeclareFloatingEnvironment{guidancebox}[Guidance box][List of guidance boxes]
\crefformat{guidancebox}{#2Guidance Box #1#3}
\renewenvironment{guidancebox}
  {\renewcommand\LTcaptype{guidancebox}\longtable}
  {\endlongtable}

\begin{document}

\begin{guidancebox}{C{0.5\textwidth}}
    \hline
    \rowcolor{guidancebox} This guidance box provides guidance on the following items:
    \begin{itemize}
        \item first item
        \item second item
    \end{itemize}\\
    \rowcolor{guidancebox}\\
    \hline
    \caption{caption of this guidance box.}\label{guide}
\end{guidancebox}

Look at \cref{guide} above. Now look at \cref{guide2} below:

\begin{guidancebox}{C{0.5\textwidth}}
    \hline
    \rowcolor{guidancebox} This guidance box provides guidance on the following numbered items:
    \begin{enumerate}
        \item first item
        \item second item
    \end{enumerate}\\
    \rowcolor{guidancebox}\\
    \hline
    \caption{caption of this guidance box.}
    \label{guide2}
\end{guidancebox}

\end{document}

在此处输入图片描述

相关内容