如何生成替代阅读顺序的目录

如何生成替代阅读顺序的目录

我在文档主体中有一个结构如下的工作:

1. Main topic 1
  1.1. Subject 1
  1.2. Subject 2
  1.3. Subject 3
2. Main topic 2
  2.1. Subject 1
  2.2. Subject 2
  2.3. Subject 3
3. Main topic 3
  3.1. Subject 1
  3.2. Subject 2
  3.3. Subject 3

我想要生成两种类型的目录:一种是传统的(自然顺序),一种是替代阅读顺序,如下所示:

Subject 1 
  Main topic 1
  Main topic 2
  Main topic 3
Subject 2
  Main topic 1
  Main topic 2
  Main topic 3
Subject 3
  Main topic 1
  Main topic 2
  Main topic 3

此生成必须完全自动化,并带有页码和hyperref链接。

我该怎么做?有没有什么软件包可以帮助我?我也愿意使用自定义宏。

答案1

这是再次读取的版本,.toc并进行了修改\contentsline,以便提取存储到的的信息.toc

我利用了expl3功能来将信息分组gtoc(即分组目录),这是一个需要改进的非常初步的版本。

\extracttocinformation是重新排序的形式ToC

简而言之,根据实际用例,这有点复杂。

\documentclass{book}

\usepackage{xcolor}
\usepackage{xpatch}

\usepackage{xparse}

\usepackage{hyperref}

\newcounter{loopcntr}


\makeatletter

\newcommand{\@firstoffour}[4]{%
  #1%
}

\newcommand{\@secondoffour}[4]{%
  #2%
}

\newcommand{\@thirdoffour}[4]{%
  #3%
}

\newcommand{\@fourthoffour}[4]{%
  #4%
}



\newcommand{\storedcontent}{%
  \@fourthoffour%
}


\newcommand{\groupedtoc}{%
  \chapter*{Subjects}
  \@starttoc{gtoc}%
}






\ExplSyntaxOn

\seq_new:N \g_toc_entries_seq
\int_new:N \g_lastlevel_int
\int_new:N \g_entry_id_int
\int_new:N \g_entry_lastid_int
\tl_new:N \g_lasttoclevel_tl

\seq_new:N \g_structurelevel_names_seq

\tl_new:N \l_tmpc_tl

\prop_new:N \g_tocid_prop

\prop_new:N \g_toclevel_prop

\prop_gput:Nnn \g_toclevel_prop {book} {-2}
\prop_gput:Nnn \g_toclevel_prop {part} {-1}
\prop_gput:Nnn \g_toclevel_prop {chapter} {0}
\prop_gput:Nnn \g_toclevel_prop {section} {1}
\prop_gput:Nnn \g_toclevel_prop {subsection} {2}
\prop_gput:Nnn \g_toclevel_prop {subsubsection} {3}
\prop_gput:Nnn \g_toclevel_prop {paragraph} {4}
\prop_gput:Nnn \g_toclevel_prop {subparagraph} {5}


\newcommand{\addtotocseq}[1]{%
  \seq_gput_right:Nn \g_toc_entries_seq {#1}
}
\cs_generate_variant:Nn \str_set:Nn {Nx,No}

\cs_generate_variant:Nn \prop_if_in:NnTF {NxTF}

\cs_generate_variant:Nn \prop_item:Nn {NV,No}

\cs_generate_variant:Nn \prop_gput:Nnn {Nox,NVx,Nxx}

\cs_generate_variant:Nn \int_set:Nn {No,Nx}

\cs_generate_variant:Nn \prop_gput:Nnn {NVo,NVx}

\cs_generate_variant:Nn \seq_set_split:Nnn {Nnx,Nno,cno,cnx}

\cs_generate_variant:Nn \seq_set_from_clist:Nn {Nx,No,co,cx}

\cs_generate_variant:Nn \tl_if_eq:nnT {xnT}

\newcommand{\showtocproperties}{%
    \prop_show:N  \g_tocid_prop
}

\newcommand{\postprocesstocseq}{
  \group_begin:
  \int_gzero:N \g_entry_id_int
  \seq_map_inline:Nn \g_toc_entries_seq {%
    \int_gincr:N \g_entry_id_int
    \prop_if_exist:cF {g_prop_\@secondoffour##1 _prop} {
      \prop_new:c {g_prop_\@secondoffour##1 _prop} 
    }
    \tl_set:No  \l_tmpa_tl {\@firstoffour##1}%
    \tl_set:No  \l_tmpb_tl {\prop_item:NV \g_toclevel_prop \l_tmpa_tl}
    \tl_set:Nx \l_tmpa_tl {{\tl_use:N \l_tmpb_tl}}
    \tl_put_right:No \l_tmpa_tl {##1}
    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int} {\tl_use:N \l_tmpa_tl}
    \tl_set:No  \l_tmpa_tl {\@firstoffour##1}%
    \tl_set:Nn  \g_lasttoclevel_tl {\@firstoffour##1} %
    \int_set:No \g_lastlevel_int {\int_use:N \l_tmpb_int}
  }
  \group_end:
}

\renewcommand{\postprocesstocseq}{%
  \group_begin:
  \int_gzero:N \g_entry_id_int
  \int_gset:Nn \g_entry_lastid_int {1}%

  \cs_set:Npn \numberline##1 {}%

  \seq_map_inline:Nn \g_toc_entries_seq {%



    \tl_set:No  \l_tmpa_tl {\@firstoffour##1}%
    \tl_set:No  \l_tmpb_tl {\prop_item:NV \g_toclevel_prop \l_tmpa_tl}
    \int_set:No \l_tmpb_int { \prop_item:NV \g_toclevel_prop \l_tmpa_tl}

    \tl_if_eq:NNTF \g_lasttoclevel_tl \l_tmpa_tl { 
    }{%
      \int_compare:nNnTF {\l_tmpb_int} < {\g_lastlevel_int }{
        \int_gset_eq:NN \g_entry_lastid_int \g_entry_id_int
        \int_gincr:N \g_entry_lastid_int
      }{
      \tl_set_eq:NN   \g_lasttoclevel_tl \l_tmpa_tl
      \int_gdecr:N \g_entry_lastid_int
      \int_gset_eq:NN \g_entry_lastid_int \g_entry_id_int
      }
    }
    \int_gincr:N \g_entry_id_int

    \tl_set:NV \l_tmpb_tl {\g_entry_id_int}
    \tl_put_right:Nn \l_tmpb_tl {/}
    \tl_put_right:NV \l_tmpb_tl {\g_entry_lastid_int}
    \tl_set:No  \l_tmpa_tl {\@firstoffour##1}%
    \tl_set:No  \l_tmpb_tl {\prop_item:NV \g_toclevel_prop \l_tmpa_tl}
    \tl_set:Nx \l_tmpa_tl {{\tl_use:N \l_tmpb_tl}}
    \tl_put_right:Nx \l_tmpa_tl {{\int_use:N \g_entry_lastid_int}}
    \tl_put_right:No \l_tmpa_tl {##1}

    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int} {\tl_use:N \l_tmpa_tl}
    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int _parentlevelid} {\int_use:N \g_entry_lastid_int}
    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int _anchor} {\@fourthoffour##1}
    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int _page} {\@thirdoffour##1}
    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int _level} {\@firstoffour##1}

    \tl_set:No \l_tmpc_tl {\prop_item:NV \g_tocid_prop {\g_entry_id_int _name}}

    %  Store all names
    \seq_gput_right:Nx \g_structurelevel_names_seq {\@secondoffour##1}
    \seq_gremove_duplicates:N \g_structurelevel_names_seq


    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int _name} {\@secondoffour##1}

    \prop_gput:NVx \g_tocid_prop {\g_entry_id_int _name} {\@secondoffour##1}

    \str_set:Nx \l_tmpc_str {\@secondoffour##1}
    \str_set_eq:NN \l_tmpb_str \l_tmpc_str

    \prop_if_in:NVTF \g_tocid_prop {\l_tmpc_str} {
      \tl_set:No \l_tmpc_tl {\prop_item:NV \g_tocid_prop {\l_tmpb_str}}
      \tl_put_right:No \l_tmpc_tl {, \prop_item:NV \g_tocid_prop {\g_entry_id_int _parentlevelid}}
      \prop_gput:Nxx \g_tocid_prop {\str_use:N \l_tmpb_str} {\tl_use:N \l_tmpc_tl}
    }{
      \prop_gput:Nxx \g_tocid_prop {\tl_use:N \l_tmpc_tl} {\@firstoffour##1 ; \prop_item:NV \g_tocid_prop {\g_entry_id_int _parentlevelid}}
    }

    \tl_set:No  \l_tmpa_tl {\@firstoffour##1}%
    \int_set:No \g_lastlevel_int {\int_use:N \l_tmpb_int}
  }

  \group_end:
}


\newcommand{\showtocprop}{%
  \group_begin:
  \cs_set:Npn \numberline##1 {}%
  \seq_map_inline:Nn \g_structurelevel_names_seq {
    \int_set:Nn \l_tmpa_int {-1}
    \seq_set_split:Nnx \l_tmpa_seq {;} {\prop_item:Nn \g_tocid_prop {##1} }
    \seq_set_from_clist:Nx \l_tmpb_seq { \seq_item:Nn \l_tmpa_seq {2}}
    \tl_if_eq:xnT {\seq_item:Nn \l_tmpa_seq {1}} {section} {
      \addtocontents{gtoc}{\protect\contentsline{chapter}{##1}{}{}}
      \seq_map_inline:Nn \l_tmpb_seq {%
        \int_set:Nn \l_tmpa_int {####1}
        \addtocontents{gtoc}{\protect\contentsline{section}{\prop_item:NV \g_tocid_prop {\l_tmpa_int _name}}{\prop_item:NV \g_tocid_prop {\l_tmpa_int _page}}{\prop_item:NV \g_tocid_prop {\l_tmpa_int _anchor}}}
      }
    }
  }
  \group_end:
}

\ExplSyntaxOff

\newcommand{\extracttocinformation}{%
  \begingroup
  \renewcommand{\contentsline}[4]{%
    \renewcommand{\numberline}[1]{}%
    \addtotocseq{{##1}{##2}{##3}{##4}}
  }%

  \IfFileExists{\jobname.toc}{\input{\jobname.toc}%
    \postprocesstocseq%
    \showtocprop
  }{\typeout{Nope!}}
  \endgroup
  \groupedtoc
}


\makeatother

\begin{document}

\extracttocinformation

\tableofcontents
\makeatletter


\loop\unless\ifnum6=\value{loopcntr}%
\chapter{Main topic \thechapter}
\section{Subject \arabic{section}}

\section{Subject \arabic{section}}
\section{Subject \arabic{section}}
\stepcounter{loopcntr}
\repeat
\makeatother





\end{document}

在此处输入图片描述

答案2

您可以使用以下内容创建“主题目录”:

在此处输入图片描述

\documentclass{article}

\usepackage{lipsum,pgffor}% Just for this example
\usepackage{etoolbox,refcount}
\usepackage{hyperref}

\makeatletter
\newcommand{\maintopic}[1]{%
  \edef\maintopictitle{Main topic #1}% Caption main topic name/title
  \section{\maintopictitle}% Set main topic in document
}

\newcounter{subjectnum}
\newcommand{\subject}[1]{%
  \subsection{Subject #1}% Set subject in document
  \stepcounter{subjectnum}% Step subjectnum counter; used for internal reference purposes only
  \label{subject-\thesubjectnum}% Set an internal link (for page extraction)
  \xifinlistcs{#1}{subject_list}{}{%
    \listcsxadd{subject_list}{#1}% Add subject to subject_list list if not already in it
  }%
  \edef\maintopicHref{subsection.\theHsubsection}% Capture hyperref link
  \edef\maintopicpageref{\getpagerefnumber{subject-\thesubjectnum}}% Capture page number
  % Store main topic title, page and hyperref link in subject-specific list
  \listcsxadd{subject_#1_topic}{\maintopictitle @@@ \maintopicpageref @@@ \maintopicHref}%
}

\newcommand{\reorderlist}[1]{%
  \addtocontents{cot}{% Set subject entry in the .cot
    \protect\contentsline{section}{Subject #1}{}{}
  }
  \forlistcsloop{\cotmaintopic}{subject_#1_topic}% Process subject-specific list
}
\def\topicname#1@@@ #2@@@ #3...{#1}% Extract main topic name/title
\def\topicpage#1@@@ #2@@@ #3...{#2}% Extract main topic page
\def\topicHref#1@@@ #2@@@ #3...{#3}% Extract main topic hyperref link
\newcommand{\cotmaintopic}[1]{%
  \edef\x{\noexpand\addtocontents{cot}{%
    \noexpand\protect\noexpand\contentsline{subsection}
      {\topicname#1...}% Main topic name/title
      {\topicpage#1...}% Main topic page
      {\topicHref#1...}% Main topic hyperref link
  }}\x% Set main topic entry in .cot
}
\AtEndDocument{%
  \forlistcsloop{\reorderlist}{subject_list}% Process subject_list list
}
\let\subjecttoc\tableofcontents% \subjecttoc is similar to \tableofcontents
% \patchcmd{<cmd>}{<search>}{<replace>}{<true>}{<false>}
\patchcmd{\subjecttoc}{{toc}}{{cot}}{}{}% ...just change .toc to .cot
\makeatother

\begin{document}

\subjecttoc

\sloppy% Just for this example
% Create a mock document with 5 topics and 7 subjects under each
\foreach \topicnum in {1,...,5} {
  \maintopic{\topicnum}\lipsum[1-5]
  \foreach \subjectnum in {One, Two, Three, Four, Five, Six, Seven} {
    \subject{\subjectnum}\lipsum[6-10]
  }
}

\end{document}

该解决方案背后的原理是积累一个主题列表。并且,对于每个主题,您创建一个列表,其中包含(1)主要主题标题,(2)主题的页码和(3)hyperref-与主题兼容的引用。

在文档的末尾,将针对每个可能的主题处理列表,并将每个条目写入目录(使用.cot文件扩展名)。您可以调用\subjecttoc来创建“主题目录”和/或\tableofcontents常规目录。

每个都\maintopic被视为\section,而\subjects 是\subsection(如果需要,可以更改)。这些角色在 中被反转,\subjecttoc并且部分编号被删除(因为反转后没有意义)。

相关内容