Cuando escribo manualmente en el archivo .toc, ¿cuál debería ser el cuarto argumento de \contentsline?

Cuando escribo manualmente en el archivo .toc, ¿cuál debería ser el cuarto argumento de \contentsline?

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 .styarchivo 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 hyperrefse redefine \contentsline, pero me resulta hyperref.styimposible 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 .styarchivo para esto.

Respuesta1

Normalmente, cualquier cambio de \contentslineetc. debe realizarse antes de hyperrefcargarlo, después hay que considerar el 4thargumento de \contentsline, que se agrega por hyperref.

El 4thargumento es el hiperancla, es decir, algo como section.1o east.17.

El hiperancla se puede insertar con \@currentHref, lo que debería proporcionar el anclaje correcto desde que \phantomsectionse 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}

ingrese la descripción de la imagen aquí

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\@auxoutdirectamente sino usar \addcontentsline. respeta y utiliza \addcontentslineautomá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\protecthyperref\addcontentsline\contentshyperrefhyperrefhyperref

\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, \exerciselike \sectiontambién tiene un argumento opcional para configurar y un texto diferente para la tabla de contenido. Ver \exercise[Bar]{Foo-Bar}en el ejemplo.

información relacionada