我在文档主体中有一个结构如下的工作:
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
,而\subject
s 是\subsection
(如果需要,可以更改)。这些角色在 中被反转,\subjecttoc
并且部分编号被删除(因为反转后没有意义)。