hyperref 和通过 `\refstepcounter` 计数的重复事物

hyperref 和通过 `\refstepcounter` 计数的重复事物

我尝试使用 hyperref 包编写文档,其中的节元素重复多次且编号相同。
这些内容由 进行计数\refstepcounter

在示例文档中,我只有第 1 节几次。
在实际情况下,它不仅仅是关于\sections。还有小节、编号练习和方程式等。

我知道您不能有两个同名的目的地。因此在示例中\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包导入的标签)。

相关内容