我想要一个命令,它获取一个标签并返回环境(或最后一个分段命令等),之后我有了\label
。我的意思是,像\autoref
,但不需要从 TeX 命令/环境名称转换为用于输出的名称(即,如果另一个命令接受并给我,我可以使用\somethingname
或自己。)\somethingautorefname
mylabel
something
笔记:我想要一个不使用提供此功能的软件包的解决方案,例如hyperref
或cleveref
(尽管如果来自其源代码的一段代码可以解决问题,那么这是一个非常好的解决方案)。
答案1
是cleveref
解决方案可以接受吗?
编辑:虽然cleveref
能够区分标签类型,但它默认使用相同的名称,例如节和子节。使用\crefname
和\Crefname
宏来更改名称定义。还请注意,较低级别的节标题有一个继承机制(例如,子子节将继承对子节所做的任何更改)。有关详细信息,请参阅手册第 7.1.2 节。
\documentclass{article}
\usepackage{cleveref}
\crefname{subsection}{subsection}{subsections}
\begin{document}
\section{foo}\label{foo}
The label type is \namecref{foo}.
\subsection{bar}\label{bar}
The label type is \namecref{bar}.
\end{document}
答案2
重要的是要理解 (La)TeX 本质上是按顺序处理文件的,从头到尾只处理一次。由于对标签的引用可能比标签本身更早出现在文档中,因此很明显,一次运行 LaTeX 是不够的。您至少需要运行两次,并且需要以某种方式将信息从第一次运行传递到第二次运行(以便 LaTeX 可以知道\label
它在当前运行中尚未处理的 )。
这就是 .aux 文件的用途。除了在每次运行期间将信息写入此文件之外,LaTeX 还会在开始处理文档之前读取此文件的内容(如果存在)。具体来说,\label
命令会导致标签信息以行的形式写入 .aux 文件\newlabel
。当在以后的 LaTeX 运行开始时重新读取 .aux 文件时,\newlabel
.aux 文件中的命令会导致定义一个\r@<labelname>
宏,其中包含上次运行中写入 .aux 文件的数据。
写入 .aux 文件的信息来自哪里\label
?创建新标签所需的当前信息始终存储在宏的当前值中\@currentlabel
。任何创建新\label
上下文的 LaTeX 命令都会更新此信息。其中最重要的是\refstepcounter
,它会移动计数器并相应地更新数据\@currentlabel
。
自动找出标签所指环境的软件包(cleveref
、hyperref
's \autoref
、varioref
、ntheorem
...)都以大致相同的方式执行此操作。基本思想是重新定义\refstepcounter
以将其他数据(例如当前环境名称)存储在 中\@currentlabel
,然后通过命令将其存储在 .aux 文件中\label
。然后您可以编写从 中检索此数据的宏\r@<labelname>
。
为了更详细地理解这一点,我建议您看看\refstepcounter
cleveref 包中是如何重新定义的,以便为下一个存储额外的数据\label
。然后看看例如\cref@gettype
宏如何从结果宏中检索标签类型信息\r@<labelname>
。
不用说,要使所有这些适用于每种类型的标签(章节、方程式、定理、脚注……),包括由其他软件包引入的标签,需要付出不小的努力。其中许多都使用了除\refstepcounter
将标签信息输入之外的其他机制\@currentlabel
,所有这些都需要进行适当的重新定义。
对于简单的应用程序来说,仅复制\refstepcounter
和\cref@gettype
宏cleveref
可能就足够了。但是,如果您复制了足够多的“能解决问题的代码片段”以使其可靠地工作,那么您将复制大约一半的软件包。您最好使用cleveref
(或其他软件包之一),因为它们已经为您完成了所有艰苦的工作。