Quando escrevo manualmente no arquivo .toc, qual deve ser o quarto argumento de \contentsline?

Quando escrevo manualmente no arquivo .toc, qual deve ser o quarto argumento de \contentsline?

Quero alterar meu índice manualmente. A razão é que meu documento não é composto tanto de "seções", mas sim de "exercícios". Eu escrevi um comando personalizado para fazer isso e quase funciona. Os seguintes comandos são colocados em um .styarquivo personalizado, carregado depois 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
        }%
    }%
}

Basicamente, isso faz exatamente o que eu quero, exceto que não cria um marcador. Isto provavelmente se deve ao quarto argumento. Tentei descobrir como hyperrefredefine \contentsline, mas acho hyperref.styimpossível entender.

Portanto, minha pergunta é: qual deveria ser o quarto argumento da minha definição? Gostaria também de saber como funciona esse quarto argumento, mas é de baixa prioridade.

Nota: não estou interessado em instalar nenhum pacote que possa personalizar ToCs. Estou fazendo isso como prática, então gostaria muito de usar meu próprio .styarquivo para isso.

Responder1

Normalmente, qualquer alteração de \contentslineetc. deve ser feita antes de hyperrefser carregado, depois deve-se considerar o 4thargumento de \contentsline, sendo adicionado por hyperref.

O 4thargumento é a hiperâncora, ou seja, algo como section.1ou east.17.

A hiperâncora pode ser inserida com \@currentHref, o que deve fornecer a âncora correta desde que \phantomsectionfoi utilizada.

Para adicionar o marcador, use \Hy@writebookmark, já que \contentslineele próprio não adiciona os marcadores, isso é feito no comando wrapper \addcontentsline, que é 'ignorado' aqui.

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

insira a descrição da imagem aqui

AtualizarUma versão com o 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}

Responder2

Eu recomendaria não usar \write\@auxoutdiretamente, mas usar \addcontentsline. \addcontentslinerespeita \nofilee usa automaticamente \protected@writepara que você possa usar \protectpara proteger comandos frágeis. E hyperreflida automaticamente com marcadores, etc., se você usar \addcontentsline. Portanto, você não precisa saber como definir o quarto argumento de \contentsadd by hyperref. Uma solução muito simples que funciona independente do uso hyperrefou não (e independente de hyperrefser carregada antes ou depois do código adicional) seria:

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

Com esta solução \exercisetambém \sectionexiste um argumento opcional para definir um texto diferente para o índice. Veja \exercise[Bar]{Foo-Bar}no exemplo.

informação relacionada