Quiero cambiar mi tabla de contenido manualmente. La razón es que mi documento no está hecho tanto de "secciones", sino de "ejercicios". He escrito un comando personalizado para hacer esto y casi funciona. Los siguientes comandos se colocan en un .sty
archivo personalizado y se cargan después 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
}%
}%
}
Básicamente, esto hace exactamente lo que quiero, excepto que no crea un marcador. Probablemente esto se deba al cuarto argumento. Intenté encontrar cómo hyperref
se redefine \contentsline
, pero me resulta hyperref.sty
imposible entenderlo.
Entonces mi pregunta es: ¿Cuál debería ser el cuarto argumento en mi definición? También me gustaría saber cómo funciona este cuarto argumento, pero es de baja prioridad.
NB: no estoy interesado en instalar ningún paquete que pueda personalizar las ToC. Estoy haciendo esto como práctica, por lo que me gustaría mucho usar mi propio .sty
archivo para esto.
Respuesta1
Normalmente, cualquier cambio de \contentsline
etc. debe realizarse antes de hyperref
cargarlo, después hay que considerar el 4th
argumento de \contentsline
, que se agrega por hyperref
.
El 4th
argumento es el hiperancla, es decir, algo como section.1
o east.17
.
El hiperancla se puede insertar con \@currentHref
, lo que debería proporcionar el anclaje correcto desde que \phantomsection
se ha utilizado.
Para agregar el marcador, use \Hy@writebookmark
, ya que \contentsline
él mismo no agrega los marcadores, eso se hace en el comando contenedor \addcontentsline
, que se "omite" aquí.
\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}
ActualizarUna versión con lo habitual \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}
Respuesta2
Recomendaría no usarlo \write\@auxout
directamente sino usar \addcontentsline
. respeta y utiliza \addcontentsline
automáticamente para que pueda utilizar para proteger comandos frágiles. Y maneja automáticamente los marcadores, etc. si usas . Por lo tanto, no necesita saber cómo configurar el cuarto argumento de agregado por . Una solución muy simple que funciona independientemente de su uso o no (e independiente de si se carga antes o después del código adicional) sería:\nofile
\protected@write
\protect
hyperref
\addcontentsline
\contents
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}
Con esta solución, \exercise
like \section
también tiene un argumento opcional para configurar y un texto diferente para la tabla de contenido. Ver \exercise[Bar]{Foo-Bar}
en el ejemplo.