我想手动更改目录。原因是我的文档不是由“章节”组成,而是由“练习”组成。我编写了一个自定义命令来执行此操作,它几乎可以正常工作。以下命令放在自定义文件中.sty
,在之后加载hyperref
:
\def\numberline@exer#1{%
\makebox[50pt][l]{\bf Ex. #1\hspace*{1em}}
}
\def\exercise#1{%
\section*{#1}\refstepcounter{exercise}\phantomsection%
\write\@auxout{%
\protect\@writefile{toc}{%
\protect\contentsline {section}{\numberline@exer{\theexercise}Title}{\thepage}%
{????}% This is the fourth argument, defined by hyperref
}%
}%
}
这基本上就是我想要的,除了它不创建书签。这可能是由于第四个参数。我试图找到如何hyperref
重新定义\contentsline
,但我发现hyperref.sty
无法理解。
所以我的问题是:我的定义中的第四个参数应该是什么? 我也想知道这个第四个参数是如何工作的,但这是低优先级的。
注意:我对安装任何可以自定义目录的软件包不感兴趣。我这样做是为了练习,所以我非常想.sty
为此使用我自己的文件。
答案1
通常,\contentsline
对等的任何更改都应在加载之前完成hyperref
,之后必须考虑由添加4th
的参数。\contentsline
hyperref
该4th
参数是超锚点,即类似于section.1
或 的东西east.17
。
超锚点可以插入\@currentHref
,它应该提供正确的锚点,因为\phantomsection
已经被使用。
为了添加书签,请使用\Hy@writebookmark
,因为\contentsline
它本身不会添加书签,这是在包装器命令中完成的\addcontentsline
,在这里被“绕过”。
\documentclass{article}
\usepackage[bookmarksopen]{hyperref}
\newcounter{exercise}
\makeatletter
\def\numberline@exer#1{%
\makebox[50pt][l]{\bfseries Ex. #1\hspace*{1em}}
}
\def\exercise#1{%
\phantomsection
\refstepcounter{exercise}
\section*{#1}%
\Hy@writebookmark{\csname theexercise\endcsname}{#1}{\@currentHref}{\toclevel@section}{toc}
\write\@auxout{%
\protect\@writefile{toc}{%
\protect\contentsline {section}{\numberline@exer{\theexercise}#1}{\thepage}{\@currentHref}%
}%
}%
}
\makeatother
\usepackage{blindtext}
\begin{document}
\tableofcontents
\section{First section}\label{foosection}
\clearpage
\blindtext[3]
\exercise{Foo}
\blindtext[2]
\end{document}
更新通常的版本\addcontentsline
:
\documentclass{article}
\usepackage[bookmarksopen]{hyperref}
\newcounter{exercise}
\makeatletter
\newcommand*\l@exercise[2]{%
\ifnum \c@tocdepth >\z@
\addpenalty\@secpenalty
\addvspace{1.0em \@plus\p@}%
\setlength\@tempdima{3.8em}%
\begingroup
\parindent \z@ \rightskip \@pnumwidth
\parfillskip -\@pnumwidth
\leavevmode \bfseries
\advance\leftskip\@tempdima
\hskip -\leftskip
#1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par
\endgroup
\fi}
\let\toclevel@exercise\toclevel@section
\newcommand{\exercisebetter}[1]{%
\refstepcounter{exercise}
\section*{#1}%
\addcontentsline{toc}{exercise}{\protect\numberline{Ex: \theexercise}#1}
}
\makeatother
\usepackage{blindtext}
\begin{document}
\tableofcontents
\section{First section}\label{foosection}
\clearpage
\blindtext[3]
\exercisebetter{Foobar}
\blindtext[2]
\end{document}
答案2
我建议不要\write\@auxout
直接使用,而是使用\addcontentsline
。\addcontentsline
它会自动尊重\nofile
和使用\protected@write
,因此您可以使用它\protect
来保护脆弱的命令。hyperref
如果您使用,它会自动处理书签等\addcontentsline
。因此,您不需要知道如何设置\contents
由添加的第 4 个参数。一个非常简单的解决方案,它可以独立于使用与否(以及独立于在附加代码之前或之后加载)hyperref
工作:hyperref
hyperref
\documentclass{article}
\usepackage[bookmarksopen]{hyperref}
\providecommand*{\texorpdfstring}[2]{#1}% Needed if `hyperref` is not used.
\newcounter{exercise}
\makeatletter
\def\numberline@exer#1{%
\texorpdfstring{\makebox[50pt][l]{\bfseries Ex. #1\hspace*{1em}}}{Ex. #1}
}
\newcommand\l@exercise{\l@section}
\newcommand*{\exercise}{%
\@dblarg\@exercise
}
\newcommand*{\@exercise}[2][]{%
\refstepcounter{exercise}%
\section*{#2}%
\addcontentsline{toc}{exercise}{\protect\numberline@exer{\theexercise}#1}%
}
\let\toclevel@exercise\toclevel@section
\makeatother
\usepackage{blindtext}
\begin{document}
\tableofcontents
\section{First section}\label{foosection}
\clearpage
\blindtext[3]
\exercise{Foo}
\blindtext[2]
\exercise[Bar]{Foo-Bar}
\blindtext
\end{document}
使用此解决方案\exercise
,\section
还可以设置可选参数,并为目录设置不同的文本。请参阅\exercise[Bar]{Foo-Bar}
示例。