索引 - 引用带有页面超链接的子部分

索引 - 引用带有页面超链接的子部分

我希望创建一个包含对小节的引用的索引(以及更复杂的编号方案)。

到目前为止,我能够很好地使用答案这里。但是我希望有一个指向部分.子部分.子部分.等号码。有什么办法吗?

答案1

您对索引条目进行编号的方式要求索引条目只能出现在编号的章节标题下。(如何对带星号/未编号的章节下的索引条目进行编号 — 例如\section*{foo} bar\index{bar}...?)

另一个要求是,章节标题应按照以下模式进行编号:数字的每个部分都经过格式化

  • 无论是小写罗马字母,
  • 或者用数字或阿拉伯语,
  • 或小写字母,
  • 或大写罗马字母,
  • 或大写字母。

数字的各个部分都由一个特殊字符串分隔,该字符串可以在制作索引作为page_compositor

制作索引据我所知,您可以仅指定一个page_compositor字符串。

如果您有这样的组合章节编号,其中章节编号的各个部分具有不同的格式,例如IV.3.2.必须是page_compositor),您还需要指定page_precedence用于对数字进行排序。

还要注意提供罗马数字之类的东西\part。如果\part尚未使用,则值\c@part将为 0,这不是正数,而\romannumeral如果所讨论的数字不是正数,则会默默地不传递任何令牌……

除了分段编号之外,您还需要提供有关超链接的锚点/目标名称的信息。

由于\index-macro 确实以无法进一步扩展的方式读取其参数,因此需要通过修补将索引条目写入 .idx 文件的机制的一部分来完成此操作,即通过\@wrindex

从节号形成超链接意味着格式化该节号。对于索引条目,格式化它们的机制就是 -thingie 。|⟨name of formatting-command⟩

由于我们必须在内使用这个东西,它不能再在-macro\@wrindex的参数内使用。\index

|see诸如和之类的东西|seealso可能会被破坏。

为了使这些东西工作起来,您要么需要修补 -macro\index本身,以便它以仍然可以进行扩展欺骗的方式读取其参数,要么进行修补,\@wrindex以便它复杂地解析其参数并自动插入创建超链接和超目标/锚点所需的内容。

后者可能是更好的方法,尽管实现解析程序可能是一个棘手且耗时的工作:你不会通过简单地搜索字符来完成!|因为@这些字符也可能出现在之前,"这意味着它们将被当作普通字符来处理制作索引. (也许可以采用一些技巧,首先用相同字符代码但不同类别代码的标记替换所有出现的!/ |/...... )@"

除此之外,还需要将每个\index条目引用为 和 之类的东西,|see并将|seealso其转换\hypertarget为可以通过\hyperlink引用项进行链接的条目。宏\see\seealso需要修补才能hyperlink为这些hypertargets 创建 s。

抛开所有这些问题,下面的代码可能会为您提供某种起点:

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.mst}
page_compositor "."
\end{filecontents*}

\documentclass{report}
\usepackage{makeidx}
\usepackage{hyperref}
\makeindex

\makeatletter
\newcommand\My@definewritesection[1]{%
  \My@@definewritesection{#1}{}{}%
}%
\newcommand\My@@definewritesection[3]{%
   \My@definewritesectionloop{#1}#1{.}\relax{#2}{#3}%
}%
\newcommand\My@definewritesectionloop{}
\def\My@definewritesectionloop#1#2#3\relax#4#5{%
  \ifx\relax#3\relax
    \expandafter\@secondoftwo
  \else
    \expandafter\@firstoftwo
  \fi
  {%
    \expandafter\My@@definewritesection
    \expandafter{\@gobble#1}{{#2}#4}{{#1}#5}%
  }{%
    \My@definewritesectionloopB
       {\My@Writeifdefinedloop{}#4\relax}#4{.}\relax#5{.}\relax
    \My@definewritehypersectionloopB
       {\My@Writeifdefinedloop{H}#4\relax}#4{.}\relax#5{.}\relax
  }%
}%
\newcommand\My@Exchange[2]{#2#1}%
\newcommand\My@definewritesectionloopB{}%
\long\def\My@definewritesectionloopB#1#2#3\relax#4#5\relax{%
  \ifx\relax#3#5\relax
    \expandafter\@secondoftwo
  \else
    \expandafter\@firstoftwo
  \fi
  {%
    \expandafter\expandafter
    \expandafter            \My@definewritesectionloopB
    \expandafter\expandafter
    \expandafter            {%
    \expandafter\My@Exchange
    \expandafter{%
    \expandafter{%
    \csname the#2\endcsname}}{\My@InCaseOneOfIsZero{#4}{#1}}%
    }#3\relax#5\relax
  }{%
    \newcommand\My@writesection{#1}%
  }%
}%
\newcommand\My@definewritehypersectionloopB{}%
\long\def\My@definewritehypersectionloopB#1#2#3\relax#4#5\relax{%
  \ifx\relax#3#5\relax
    \expandafter\@secondoftwo
  \else
     \expandafter\@firstoftwo
  \fi
  {%
    \expandafter\expandafter
    \expandafter            \My@definewritehypersectionloopB
    \expandafter\expandafter
    \expandafter           {%
    \expandafter\My@Exchange
    \expandafter{%
    \expandafter{%
    \romannumeral
      \expandafter\My@Exchange
      \expandafter{%
      \csname theH#2\endcsname}{0 #2.}}}{\My@InCaseOneOfIsZero{#4}{#1}}%
    }#3\relax#5\relax
  }{%
    \newcommand\My@writehypersection{#1}%
  }%
}%
\newcommand\My@InCaseOneOfIsZero[1]{%
  \My@IsZeroLoop{\@secondoftwo}#1\relax
}%
\newcommand\My@IsZeroLoop[2]{%
  \ifx\relax#2\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
  {%
    \@ifundefined{c@#2}{\@secondoftwo}{%
      \ifnum\the\csname c@#2\endcsname=0 %
        \expandafter\@firstoftwo
      \else
        \expandafter\@secondoftwo
      \fi
    }%
    {\My@IsZeroLoop{\@firstoftwo}}%
    {\My@IsZeroLoop{#1}}%
  }{#1}%
}%
\newcommand\My@gobbletorelax{}%
\long\def\My@gobbletorelax#1\relax{}
\newcommand\My@Writeifdefinedloop[2]{%
  \ifx\relax#2\expandafter\@gobble\else\expandafter\@firstofone\fi
  {%
    \@ifundefined{the#1#2}{%
      \@ifundefined{the#2}%
                   {\My@Writeifdefinedloop{#1}}%
                   {\csname the#2\expandafter\endcsname\My@gobbletorelax}%
    }{\csname the#1#2\expandafter\endcsname\My@gobbletorelax}%
  }%
}%

% This will define \My@writesection  and
% \My@writehypersection.
%
% \My@writesection will write the \the<countername>-printing
% of the value of that sectioning counter which belongs to the 
% lowest sectioning-level where both the counter itself and 
% counters of all superordinate sectioning levels do not have 
% the value 0.
% (In case no such counter exists, e.g., as there is no
% sectioning heading at all before the `\index`-entry in question,
% the \the<countername>-printing of the value of the counter 
% belonging to the most superordinate existing sectioning level 
% will be used. That value should be zero. In that case
% \My@writehypersection, see below, will attempt to create an
% anchor-name for that counter. The likelihood is high that
% in this case an anchor of the created name does not exist
% which means that in this case you will get warning-messages
% and .log-file-entries about non existing destinations that
% were replaced by fixed ones.
% There are scenarios involving \romannumeral, where the 
% \the<countername>-printing of counters of value 0 doesn't yield
% any token at all.)
%
% \My@writehypersection will attempt to create the name
% of the corresponding anchor/hypertarget produced by
% `\refstepcouter` by concatenating the name of that counter, a dot
% and \theH<countername>.
%
\My@definewritesection{%
  {subsubsubparagraph}%
  {subsubparagraph}%
  {subparagraph}%
  {paragraph}%
  {subsubsection}%
  {subsection}%
  {section}%
  {chapter}%
  % If a sectioning level/a sectioning-counter occurring in this 
  % list is undefined, that doesn't matter. E.g., there are
  % documentclasses where \chapter and the chapter-counter aren't
  % defined at all...
  %
  % But distinguish the case of a sectioning level being undefined 
  % from the case of a sectioning-level being defined but unused while
  % sectioning headings of subordinate levels are used!!!
  % The latter case is not good practice but there are people who
  % do it anyway.
  %
  % Don't include the part-counter into the hierarchy of
  % sectioning counters.
  %
  % Although \part is a means for dividing a work into
  % portions, it is not an element of that sectioning hierarchy 
  % which is formed by section headings. 
  % Therefore \part does not reset any other counters that
  % belong to the hierarchy of sectioning headings.
  % E.g., \part does not reset the chapter-counter.
  %
  % Besides this: If part is not used, it has the value 0. 
  % If you---while not using \part---consider the part
  % counter an element of the set of those counters that belong 
  % to the hierarchy of sectioning headings, then no
  % sectioning-counter in the hierarchy will not have
  % a superordinate sectioning counter of value 0...
  %
  % Besides this, parts are numbered in roman numerals
  % while \romannumeral0 yields no tokens at all...
}%

\renewcommand*\@wrindex[1]{%
    \set@display@protect
    \immediate\write\@indexfile{%
      \protect\indexentry{#1\string|hyperlink{\My@writehypersection}}%
                         {\My@writesection}%
    }%
  \endgroup
  \@esphack
}%

\makeatother

\begin{document}

\chapter{First chapter}
  \index{first} 
  \index{chapter}
\chapter{Second chapter}
  \index{second}
  \index{chapter}
\section{First section}
  \index{first}
  \index{section}
\subsection{First subsection}
  \index{first}
  \index{subsection}
\section{Second section}
  \index{second}
  \index{section}
\subsection{Another subsection}
  \index{second}
  \index{subsection}
\setcounter{section}{9}
\section{Another section}
  \index{section}
\subsection{Last subsection}
  \index{subsection}
\printindex
\end{document}

相关内容