0

I try to customize TOC entry of section via redefining \l@section and defining \@section macros.

My purpose was to add different mark (\sectiontitlemark) before section counter in main text as well as in TOC. I achieved the goal. But problem arised with "space" between section counter and it body in TOC.

This "space" is just a shift of text from the left border of the page, regardless of the presence of the section counter (and \sectiontitlemark) and it need to be calculated depending on total width of \sectiontitlemark + \thesection + dot. But the total width depend on width of \sectiontitlemark. In MWE it controlled by \setlength\@tempdima{2.7em}

MWE

\documentclass[]{book}
\usepackage{lipsum}
\makeatletter


\renewcommand*\l@section[2]{%
    \ifnum \c@tocdepth >\m@ne
    \addpenalty{-\@highpenalty}%
    \vskip 0.1em \@plus\p@
    \setlength\@tempdima{2.7em} % Space between number and section title need to be calculated
    \begingroup
    \parindent \z@ \rightskip \@pnumwidth
    \parfillskip -\@pnumwidth
    \leavevmode
    \advance\leftskip\@tempdima
    \hskip -\leftskip
    #1\leaders\hbox to .5em{\hss.\hss}\hfil \nobreak\hb@xt@\@pnumwidth{\hss  #2}\par
    \penalty\@highpenalty%
    \endgroup
    \fi}

\renewcommand\section{\global\@topnum\z@
                    \@afterindentfalse
                    \secdef\@section\empty}
\def\@section[#1]#2{\refstepcounter{section}%
                    \addcontentsline{toc}{section}{\protect\numberline{\sectiontitlemark~\thesection.}#1}%
                    \sectionmark{#1}%
                    \addtocontents{lof}{\protect\addvspace{10\p@}}%
                    \addtocontents{lot}{\protect\addvspace{10\p@}}%
                    \@makesectionhead{#2}%
                    \@afterheading
                    }
\def\@makesectionhead#1{%
  \vspace*{10\p@}%
  {\parindent \z@ \raggedright \normalfont
        \normalfont\large\bfseries \sectiontitlemark~\thesection.\hspace{1ex}#1\par\nobreak
    \vskip 10\p@
  }}
\def\@ssection#1{\refstepcounter{section}%
                 \if@twocolumn
                   \@topnewpage[\@makessectionhead{#1}]%
                 \else
                   \@makessectionhead{#1}%
                   \@afterheading
                   \sectionmark{#1}%
                 \fi}
\def\@makessectionhead#1{%
  \vspace*{10\p@}%
  {\parindent \z@ \raggedright
    \normalfont
    \interlinepenalty\@M
    \normalfont\large\bfseries  #1\par\nobreak
    \vskip 10\p@
  }}

\makeatother
\begin{document}
\tableofcontents
\def\sectiontitlemark{\S}
\section{section One may be very very very and very very long and wrap to next line}
\lipsum[1]
\def\sectiontitlemark{$\to$}
\section{section Two may be also very very very and very very long and wrap to next line}
\lipsum[1]
\end{document}

enter image description here

  • I think using tocloft might be easier here – user31729 Jul 31 '17 at 7:41
  • @Christian Hupfer I never used tocloft. May be you can solve with it? – sergiokapone Jul 31 '17 at 7:44
1

I had found solution! The main idea is to save length of counter with mark \@sechead@len to toc-file by \addtocontents{toc}{\setlength{\sechead@len}{\the\@sechead@len}} in \@section macro and use it with \renewcommand*\l@section{\@dottedtocline{2}{3em}{\sechead@len}}.

\documentclass[]{book}
\usepackage{lipsum}
\makeatletter
\def\sectiontitlemark{}
\newlength{\sechead@len}
\newlength{\@sechead@len}

\newif{\ifappendix}

\renewcommand*\l@section{\@dottedtocline{2}{3em}{\sechead@len}}


\renewcommand\section{\global\@topnum\z@
                    \@afterindentfalse
                    \secdef\@section\empty}
\def\@section[#1]#2{\refstepcounter{section}%
                    \settowidth{\@sechead@len}{\sectiontitlemark~\thesection.\space}
                    \addtocontents{toc}{\setlength{\sechead@len}{\the\@sechead@len}}
                    \addcontentsline{toc}{section}{\protect\numberline{\sectiontitlemark~\thesection.}#1}%
                    \sectionmark{#1}%
                    \addtocontents{lof}{\protect\addvspace{10\p@}}%
                    \addtocontents{lot}{\protect\addvspace{10\p@}}%
                    \@makesectionhead{#2}%
                    \@afterheading
                    }
\def\@makesectionhead#1{%
  \vspace*{10\p@}%
  {\parindent \z@ \raggedright \normalfont
        \normalfont\large\bfseries \sectiontitlemark~\thesection.\hspace{1ex}#1\par\nobreak
    \vskip 10\p@
  }}
\def\@ssection#1{\refstepcounter{section}%
                 \if@twocolumn
                   \@topnewpage[\@makessectionhead{#1}]%
                 \else
                   \@makessectionhead{#1}%
                   \@afterheading
                   \sectionmark{#1}%
                 \fi}
\def\@makessectionhead#1{%
  \vspace*{10\p@}%
  {\parindent \z@ \raggedright
    \normalfont
    \interlinepenalty\@M
    \normalfont\large\bfseries  #1\par\nobreak
    \vskip 10\p@
  }}

\makeatother
\begin{document}
\tableofcontents
\def\sectiontitlemark{\S}
\section{section One may be very very very and very very long and wrap to next line}
\lipsum[1]


\def\sectiontitlemark{$\to$}
\section{section Two may be also very very very and very very long and wrap to next line}
\lipsum[1]

\def\sectiontitlemark{ ------------1 }
\section{section Two may be also very very very and very very long and wrap to next line}
\lipsum[1]
\end{document}

It's interesting that I found the solution after couple of days of searching right after I described the problem here.

May be someone will find the more laconic solution.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.