3

I want to change my table of contents manually. The reason is that my document isn't so much made out of "sections", but rather "exercises". I have written a customized command to do this and it almoast works. The following commands are put in a custom .sty file, loaded after 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
        }%
    }%
}

This basically does exactly what I want, exept it doesn't create a bookmark. This is probably due to the fourth argument. I tried to find how hyperref redefines \contentsline, but I find hyperref.sty impossible to understand.

So my question is: What should the fourth argument in my definition be? I would also like to know how this fourth argument works, but this is low priority.

N.B. I am not interested in installing any packages that can customize ToCs. I am doing this as practice, so I would very much like to use my own .sty file for this.

1
  • 2
    Wouldn't it be much much much more simpler to define a new float (even if it is non-floating) and have stuff done by a package?
    – Johannes_B
    Commented Apr 15, 2017 at 14:37

2 Answers 2

7

Normally, any changes of \contentsline etc. should be done before hyperref is loaded, afterwards one has to consider the 4th argument of \contentsline, being added by hyperref.

The 4th argument is the hyperanchor, i.e. something like section.1 or east.17.

The hyperanchor can be inserted with \@currentHref, which should provide the correct anchor since \phantomsection has been used.

In order to add the bookmark, use \Hy@writebookmark, since \contentsline itself does not add the bookmarks, that's done in the wrapper command \addcontentsline, which is 'by-passed' here.

\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}

enter image description here

Update A version with usual \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}
12
  • Please note that this is a quick and dirty example only... a better MWE would show more content and it is advisable to check whether hyperref is loaded or not
    – user31729
    Commented Apr 15, 2017 at 15:11
  • I've put \HyperGlobalCurrentHref in the fourth argument. I still don't get bookmarks in Adobe. Also, if I click on the ToC enty the document is jumped to just below the title of the section, not showing the section title (though I believe this is a \phantomsection problem??)
    – gebruiker
    Commented Apr 15, 2017 at 15:27
  • The \phantomsection will not provide with a bookmark, nor will \contentsline do.
    – user31729
    Commented Apr 15, 2017 at 15:30
  • I should think of something else for that then. I should also note that loading my custom .sty before hyperref doesn't seem to change anything. Nor does writing the \def.. in the preamble before hyperref.
    – gebruiker
    Commented Apr 15, 2017 at 15:35
  • 1
    But on the whole your answer is what I was looking for. Thank you.
    – gebruiker
    Commented Apr 15, 2017 at 15:36
5

I would recommend not to use \write\@auxout directly but use \addcontentsline. \addcontentsline automatically respects \nofile and uses \protected@write so you can use \protect to protect fragile commands. And hyperref automatically handles bookmarks etc. if you use \addcontentsline. So you don't need to know how to set the 4th argument of \contents added by hyperref. A very simple solution that does work independent from using hyperref or not (and independent whether hyperref is loaded before or after the additional code) would be:

\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}

With this solution \exercise like \section also has an optional argument to set and different text for the table of contents. See \exercise[Bar]{Foo-Bar} in the example.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .