![hyperref 和通过 `\refstepcounter` 计数的重复事物](https://linux22.com/image/402768/hyperref%20%E5%92%8C%E9%80%9A%E8%BF%87%20%60%5Crefstepcounter%60%20%E8%AE%A1%E6%95%B0%E7%9A%84%E9%87%8D%E5%A4%8D%E4%BA%8B%E7%89%A9.png)
我尝试使用 hyperref 包编写文档,其中的节元素重复多次且编号相同。
这些内容由 进行计数\refstepcounter
。
在示例文档中,我只有第 1 节几次。
在实际情况下,它不仅仅是关于\section
s。还有小节、编号练习和方程式等。
我知道您不能有两个同名的目的地。因此在示例中\theHsection
重新定义了文档。
这似乎可行。
页码计数器也被重置。因此,我必须重新定义\thepage
所有依赖于页面目标的索引宏。\thepage
重新定义后,使用-string 向 pdf 中不属于显示文本的每个页码\texorpdfstring
添加\Person
。这不是最佳选择,因为除了更改页面目标的名称外,它还会更改书签中页码的可见文本短语以及用于显示文档的 pdf 查看器窗口框架底部的可见文本短语。
所以在下面的例子中我做了很多修补。
\documentclass{article}
\usepackage{refcount, makeidx}
\usepackage{hyperref}
\makeatletter
\newcommand\savecounterstolabel[1]{%
\begingroup
\def\@elt##1{\space\space\string\localsetcounter{##1}{\number\value{##1}}\@percentchar^^J}%
\protected@edef\@currentlabel{\@percentchar^^J\cl@@ckpt}%
\label{#1}%
\endgroup
}%
\@ifdefinable\localsetcounter{%
\DeclareRobustCommand\localsetcounter[2]{%
\csname c@#1\endcsname=#2\relax
}%
}%
\newcommand\locallyrestorecountersfromlabel[1]{%
\getrefbykeydefault{#1}{}{}%
}%
\newcommand\myhyperpage[2]{%
\hyperlink{page.#2.#1}{#2 (Sheet for #1)}%
}%
\newcommand\patch@@wrindex{%
\def\@@wrindex##1|##2|##3\\{%
\if@filesw
\ifx\\##2\\%
\protected@write\@indexfile{%
\let\thepage\thepagecopy
\let\savedthepage\relax
}{\string\indexentry{##1|myhyperpage{\Person}}{\savedthepage}}%
\else
\HyInd@@@wrindex{##1}##2\\%
\fi
\fi
\endgroup
\@esphack
}%
}%
\newcommand\namelist{Aldrich,Brenda,Charles,Demelza,Emerson,%
Farrah,Gilford,Harmony,Irving,Jocelyn,Kenton,%
Lindsay,Manley,Nara,Ogden,Pamela,Quentin,%
Roberta,Stan,Tanja,Ulysses,Veronica,Wayland,%
Xanthis,York,Zilla}
\makeindex
\begin{document}
\vspace*{-3cm}%
\tableofcontents
\newpage
\savecounterstolabel{LabelBeforeBranchingTheText}%
\expandafter\@for\expandafter\Person\expandafter:\expandafter=\namelist\do{%
\begingroup
\locallyrestorecountersfromlabel{LabelBeforeBranchingTheText}%
% This is my current workaround for page-numbers/page-destinations
% but I would like not to need to resort to \texorpdfstring
% because this does write \Person's expansion not only to
% destination-names but also to page numbers displayed as
% part of visible phrases of bookmarks or displayed in the
% frame bottom of the window where the pdf-viewer displays
% the document.
\let\savedthepage=\thepage
\def\thepagecopy{\savedthepage.\Person}%
\def\thepage{\savedthepage\texorpdfstring{}{.\Person}}%
\patch@@wrindex
% I would like a hook so that this is not only done for
% section counter but for all counters:
\let\SavedTheHsection=\theHsection
\def\theHsection{\Person.\SavedTheHsection}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\null\hfill(Sheet for \Person)
\section{First section for \Person}
\label{FirstSectionFor\Person}%
Text\index{text} of first section for \Person
\newpage
\endgroup
}%
\expandafter\@for\expandafter\Person\expandafter:\expandafter=\namelist\do{%
\noindent\hyperref[FirstSectionFor\Person]{%
Click here to reach the first section for \Person.%
}\smallskip\\%
}%
\newpage
Some text\index{text}.
\printindex
\end{document}
问题1:有没有更好的方法来处理这个页面锚点问题?
问题 2:现在我必须手动重新定义每个在重复的事情中\theH...
增加的计数器。\refstepcounter
是否可以在 hyperref 中仅在某些位置提供前缀,该前缀会添加到在这些位置创建的所有目标,并且在将这些目标的名称写入辅助文件时(例如通过 -command \label
、目录或 .out 文件)会包含该前缀?
在我看来,这在重复事情时确实非常有用。
如果尚不存在:我需要修补 hyperref 的哪些底层宏以添加钩子,以便可以(在本地范围内)重新定义钩子以向所有目的地添加前缀,该前缀在将目标名称写入 .aux-file/.toc-file/.out-file 时也会写入? hyperref 中是否实现了某种方式,使得添加这样的钩子不会对输出例程的时间异步性造成问题?(否则问题可能是在输出例程执行和写入时钩子不再重新定义\write
。)我尝试阅读 hyperref 包的注释源代码,但经过一天的工作后,对于一个晚上来说太过分了。
我无法使用\HyperDestNameFilter
/\HyperDestLabelReplace
为在特定本地范围内创建的所有目标添加前缀,因为\HyperDestNameFilter
/\HyperDestLabelReplace
不会更改写入 .aux/.toc/.out 文件的内容。这意味着:\HyperDestNameFilter
本地范围内的修改不会在本地范围之外生效。因此,从本地范围之外链接到本地范围内创建的目标将行不通。
我很感激能得到答案和指向资源的指针,在那里我可以找到/得出我问题的答案。
我不是在制作幻灯片。我设计了笔试,人们基本上必须解决相同的数学问题,但系数不同。
真挚地
朱多基亚
答案1
通常该宏\hyper@makecurrent
用于创建以 计算的事物的锚点/目的地的名称,并将\refstepcounter
这些名称保存为名为 的宏\@currentHref
。
也许您可以修补\hyper@makecurrent
以添加前缀或后缀或其他内容。
“通常”是因为有例外。例如,有些软件包提供了自己的方法来支持 hyperref-package 的加载。
除此之外,还有\hyper@makecurrent
未使用的命名目的地等。
例如,可以通过 链接的页面锚点\hyperpage
。
例如,根据 创建\hyperdef
并根据 引用的目的地\hyperref
。
例如,通过 创建\hypertarget
并根据 引用的目的地\hyperlink
。
(可能是通过 创建的目的地\phantomsection
。也许这些目的地的名称是在\@currentHref
不使用 的情况下创建和存储的\hyper@makecurrent
,但我不确定。)
这里您可能需要修补构成超参考驱动程序接口的宏(例如,,,,,\hyper@@anchor
等等)。\hyper@@anchorstart
\Hy@writebookmark
\hyper@link
\hyper@linkstart
当这样做时 - 为了防止添加两次前缀 - 您可能需要实现区分目标/锚点的名称是否已经在先前的处理步骤中提供(例如,通过\@currentHref
,例如由于从辅助文件中读取内容,其中目标名称是用前缀写入的)。
总而言之,这并不好笑。
我个人的看法是:
为了正确完成这些工作,需要严格将目的地/锚点/目标划分为不同的类别,并通过用于处理目的地/锚点/目标名称的宏来反映这些类别。
例如,此类类别可以是:
- 放入文档中的目的地/锚点的名称。
- 指向文档外部内容的目的地/锚点/目标的名称。(例如,“https://www.[...]“或”mailto:“,例如通过xr包导入的标签)。
反映这些类别的宏观类别可以是:
- 创建放置在文档中的目标/锚点的名称并将该信息提供给其他宏的宏。(类似于
\hyper@makecurrent
--\@currentHref
机制。) - 宏处理放置在文档中的目标/锚点的名称,并且不需要考虑前缀,因为在将目标名称/锚点名称写入 .aux-file/to .toc-file/whatever 时已经考虑了前缀。
- 处理放入文档中的目的地/锚点的名称的宏,并且仍需考虑前缀等。
- 处理文档外部内容的链接/引用的宏(例如“https://www.[...]“或”mailto:“,例如通过xr包导入的标签)。