9

Every time I typeset some book or articles, I start to renew sectioning commands (\part, \section, some \@-commands and so on), \maketitle, \tableofcontents commands by copy-pasting it to my class and changing later to obtain the desired view. I think it's a bit tedious, and for the LaTeX noob, this task is daunting, as evidenced by the many posts in tex.stackexchange. Recently I discover xtemplate-package. Now I want to recreate \tableofcontents with it. The template should look something like (I need to think about it yet).

\DeclareTemplateInterface{toc}{toc}{1}
{
  contentsnameformat: tokenlist ,
  chapterview : tokenlist ,
  sectionview : tokenlist ,

  %and so on
}

Now my micro challenge - is to override the \addcontentsline and \@starttoc functions with expl3. But I have no idea how to do this. I need some initial assistance.

3
6

Preface

In an attempt to answer this question, to outline a possible way to go, and to show a proof of concept I somehow got carried away… :$ the code developed into a small package.

It seems to be reasonably usable with standard classes but no guaranties whatsoever from me :) Also – even if I got carried away – it still is a long way from being feature complete and near to what the original goal was: outlining a possible way to go.

Usage example

\documentclass{article}
% \documentclass{report}

\usepackage{xtoc}

\setxtoc{
  % top-entry-dotted = true ,
  main-entry-dotted = true ,
  sub-entry-formatting = \itshape ,
  preamble = Just a test.
}

\begin{document}

\tableofcontents

\listoffigures

\part{part: a somewhat longer text for demonstration purposes spanning at
  least two lines}
\section{section: a somewhat longer text for demonstration purposes spanning
  at least two lines}
\subsection{subsection: a somewhat longer text for demonstration purposes
  spanning at least two lines}
\subsubsection{subsubsection: a somewhat longer text for demonstration
  purposes spanning at least two lines}
\section{section: a somewhat longer text for demonstration purposes spanning
  at least two lines}
\subsection{subsection: a somewhat longer text for demonstration purposes
  spanning at least two lines}
\subsubsection{subsubsection: a somewhat longer text for demonstration
  purposes spanning at least two lines}
\begin{figure}
  \caption{bla bla bla}
\end{figure}

\end{document}

enter image description here

The package code (xtoc.sty)

The code isn't commented, yet. I hope it is clear, anyway. If it isn't I'll try to add some explanation. The default settings are those of the standard classes.

% http://tex.stackexchange.com/q/246595/
\ProvidesPackage{xtoc}[2016/09/11 v0.1 formatting of the table of contents (CN)]
\RequirePackage{xtemplate,etoolbox}

\newbool{@xtoc@noredef}
\DeclareOption{noredef}{\booltrue{@xtoc@noredef}}
\ProcessOptions\relax

\newbool{@xtoc@topentrydotted}
\newbool{@xtoc@mainentrydotted}
\newbool{@xtoc@subentrydotted}

\newbool{@xtoc@toppagenumberright}
\newbool{@xtoc@mainpagenumberright}
\newbool{@xtoc@subpagenumberright}

\newrobustcmd*\@xtoc@fillwidthdots{%
  \leaders\hbox{%
    $\m@th\mkern\@xtoc@dotseparation mu
    \hbox{\@xtoc@dotsymbol}
    \mkern\@xtoc@dotseparation mu$%
  }%
}

\newrobustcmd*\@xtoc@entry[3]{%
  \leavevmode
  \csuse{@xtoc@#1entryformatting}%
  #2%
  \ifbool{@xtoc@#1pagenumberright}
    {\nobreak\ifbool{@xtoc@#1entrydotted}{\@xtoc@fillwidthdots}{}\hfil}{}%
  \makebox
    [\@xtoc@pagenumberwidth]%
    [\@xtoc@pagenumberalign]%
    {\@xtoc@pagenumberformatting#3}%
  \ifbool{@xtoc@#1pagenumberright}{}{\hfil\null}%
  \par
}

\newrobustcmd*\xtocsubentry[5]{%
  \ifnum #1>\@xtoc@leveldepth \else
    \vskip \@xtoc@subentryprespace
    \begingroup
      \leftskip#2\relax
      \rightskip\@xtoc@rightmargin
      \parfillskip -\rightskip
      \parindent #2\relax \@afterindenttrue
      \interlinepenalty\@M
      \@tempdima #3\relax
      \advance\leftskip \@tempdima
      \hskip -\leftskip
      \@xtoc@entry{sub}{#4}{#5}%
    \endgroup
  \fi
}

\newrobustcmd*\xtocmainentry[5]{%
  \ifnum \@xtoc@leveldepth >\z@
    \addpenalty\@secpenalty
    \addvspace{\@xtoc@mainentryprespace}%
    \setlength\@tempdima{#3}%
    \begingroup
      \parindent\z@
      \rightskip\@xtoc@pagenumberwidth
      \parfillskip -\@xtoc@pagenumberwidth
      \advance\leftskip\@tempdima
      \hskip -\leftskip
      \@xtoc@entry{main}{#4}{#5}%
    \endgroup
  \fi
}

\newrobustcmd*\xtoctopentry[5]{%
  \ifnum \@xtoc@leveldepth >-2\relax
    \addpenalty\@secpenalty
    \addvspace{\@xtoc@mainentryprespace}%
    \setlength\@tempdima{#3}%
    \begingroup
      \parindent\z@
      \rightskip\@xtoc@pagenumberwidth
      \parfillskip -\@xtoc@pagenumberwidth
      \@xtoc@entry{top}{#4}{#5}%
      \nobreak
    \endgroup
  \fi
}%

\newrobustcmd*\@xtoc@makel@entry[1]{%
  \csdef{l@#1}{%
    \csuse{@xtoc@#1entry}
      {\csuse{@xtoc@#1level}}
      {\csuse{@xtoc@#1indent}}
      {\csuse{@xtoc@#1numwidth}}%
  }%
}

\DeclareObjectType{xtoc}{0}

\DeclareTemplateInterface{xtoc}{list-of}{0}
  {
    file-extension           : tokenlist   = toc ,
    heading-function         : function{1} = \section*{#1} ,
    heading                  : tokenlist   = \contentsname ,
    header                   : tokenlist   = \MakeUppercase\contentsname ,
    preamble                 : tokenlist ,
    preamble-post-space      : skip        = \baselineskip ,
    postamble                : tokenlist ,
    postamble-pre-space      : skip        = \baselineskip ,
    right-margin             : length      = 2.55em ,
    dot-separation           : tokenlist   = 4.5 ,
    dot-symbol               : tokenlist   = . ,
    page-number-width        : length      = 1.55em ,
    page-number-alignment    : choice{left,center,right} = right ,
    page-number-formatting   : tokenlist ,
    depth                    : integer     = 3 ,
    %
    top-entry-pre-space      : skip        = 2.25em \@plus\p@ ,
    top-entry-formatting     : tokenlist   = \large\bfseries ,
    top-entry-dotted         : choice{true,false} = false ,
    top-entry-page-number-right : choice{true,false} = true ,
    %
    main-entry-pre-space     : skip        = 1.0em \@plus\p@ ,
    main-entry-formatting    : tokenlist   = \bfseries ,
    main-entry-dotted        : choice{true,false} = false ,
    main-entry-page-number-right : choice{true,false} = true ,
    %
    sub-entry-pre-space      : skip        = \z@ \@plus.2\p@ ,
    sub-entry-formatting     : tokenlist ,
    sub-entry-dotted         : choice{true,false} = true ,
    sub-entry-page-number-right : choice{true,false} = true ,
    %
    part-entry               : function{5} = \xtoctopentry{#1}{#2}{#3}{#4}{#5} ,
    chapter-entry            : function{5} = \xtocmainentry{#1}{#2}{#3}{#4}{#5} ,
    section-entry            : function{5} = \xtocmainentry{#1}{#2}{#3}{#4}{#5} ,
    subsection-entry         : function{5} = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
    subsubsection-entry      : function{5} = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
    paragraph-entry          : function{5} = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
    subparagraph-entry       : function{5} = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
    figure-entry             : function{5} = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
    table-entry              : function{5} = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
    %
    part-level               : integer     = 0 ,
    chapter-level            : integer     = 1 ,
    section-level            : integer     = 1 ,
    subsection-level         : integer     = 2 ,
    subsubsection-level      : integer     = 3 ,
    paragraph-level          : integer     = 4 ,
    subparagraph-level       : integer     = 5 ,
    figure-level             : integer     = 1 ,
    table-level              : integer     = 1 ,
    %
    part-indent              : length      = 0pt ,
    chapter-indent           : length      = 0pt ,
    section-indent           : length      = 0pt ,
    subsection-indent        : length      = 1.5em ,
    subsubsection-indent     : length      = 3.8em ,
    paragraph-indent         : length      = 7em ,
    subparagraph-indent      : length      = 10em ,
    figure-indent            : length      = 1.5em ,
    table-indent             : length      = 1.5em ,
    %
    part-num-width           : length      = 0pt ,
    chapter-num-width        : length      = 1.5em ,
    section-num-width        : length      = 1.5em ,
    subsection-num-width     : length      = 2.3em ,
    subsubsection-num-width  : length      = 3.2em ,
    paragraph-num-width      : length      = 4.1em ,
    subparagraph-num-width   : length      = 5em ,
    figure-num-width         : length      = 2.3em ,
    table-num-width          : length      = 2.3em
  }

\DeclareTemplateCode{xtoc}{list-of}{0}
  {
    file-extension           = \@xtoc@fileextension ,
    heading-function         = \@xtoc@headingfunction ,
    heading                  = \@xtoc@heading ,
    header                   = \@xtoc@header ,
    preamble                 = \@xtoc@preamble ,
    preamble-post-space      = \@xtoc@preamblepostspace ,
    postamble                = \@xtoc@postamble ,
    postamble-pre-space      = \@xtoc@postambleprespace ,
    right-margin             = \@xtoc@rightmargin ,
    dot-separation           = \@xtoc@dotseparation ,
    dot-symbol               = \@xtoc@dotsymbol ,
    page-number-width        = \@xtoc@pagenumberwidth ,
    page-number-alignment    =
      {
        left   = \def\@xtoc@pagenumberalign{l} ,
        center = \def\@xtoc@pagenumberalign{c} ,
        right  = \def\@xtoc@pagenumberalign{r}
      } ,
    page-number-formatting   = \@xtoc@pagenumberformatting ,
    depth                    = \@xtoc@leveldepth ,
    %
    top-entry-pre-space      = \@xtoc@topentryprespace ,
    top-entry-formatting     = \@xtoc@topentryformatting ,
    top-entry-dotted         =
      {
        true = \@xtoc@topentrydottedtrue ,
        false = \@xtoc@topentrydottedfalse
      } ,
    top-entry-page-number-right =
      {
        true = \@xtoc@toppagenumberrighttrue ,
        false = \@xtoc@toppagenumberrightfalse
      } ,
    %
    main-entry-pre-space     = \@xtoc@mainentryprespace ,
    main-entry-formatting    = \@xtoc@mainentryformatting ,
    main-entry-dotted        =
      {
        true = \@xtoc@mainentrydottedtrue ,
        false = \@xtoc@mainentrydottedfalse
      } ,
    main-entry-page-number-right =
      {
        true = \@xtoc@mainpagenumberrighttrue ,
        false = \@xtoc@mainpagenumberrightfalse
      } ,
    %
    sub-entry-pre-space      = \@xtoc@subentryprespace ,
    sub-entry-formatting     = \@xtoc@subentryformatting ,
    sub-entry-dotted         =
      {
        true = \@xtoc@subentrydottedtrue ,
        false = \@xtoc@subentrydottedfalse
      } ,
    sub-entry-page-number-right =
      {
        true = \@xtoc@subpagenumberrighttrue ,
        false = \@xtoc@subpagenumberrightfalse
      } ,
    %
    part-entry               = \@xtoc@partentry ,
    chapter-entry            = \@xtoc@chapterentry ,
    section-entry            = \@xtoc@sectionentry ,
    subsection-entry         = \@xtoc@subsectionentry ,
    subsubsection-entry      = \@xtoc@subsubsectionentry ,
    paragraph-entry          = \@xtoc@paragraphentry ,
    subparagraph-entry       = \@xtoc@subparagraphentry ,
    figure-entry             = \@xtoc@figureentry ,
    table-entry              = \@xtoc@tableentry ,
    %
    part-level               = \@xtoc@partlevel ,
    chapter-level            = \@xtoc@chapterlevel ,
    section-level            = \@xtoc@sectionlevel ,
    subsection-level         = \@xtoc@subsectionlevel ,
    subsubsection-level      = \@xtoc@subsubsectionlevel ,
    paragraph-level          = \@xtoc@paragraphlevel ,
    subparagraph-level       = \@xtoc@subparagraphlevel ,
    figure-level             = \@xtoc@figurelevel ,
    table-level              = \@xtoc@tablelevel ,
    %
    part-indent              = \@xtoc@partindent ,
    chapter-indent           = \@xtoc@chapterindent ,
    section-indent           = \@xtoc@sectionindent ,
    subsection-indent        = \@xtoc@subsectionindent ,
    subsubsection-indent     = \@xtoc@subsubsectionindent ,
    paragraph-indent         = \@xtoc@paragraphindent ,
    subparagraph-indent      = \@xtoc@subparagraphindent ,
    figure-indent            = \@xtoc@figureindent ,
    table-indent             = \@xtoc@tableindent ,
    %
    part-num-width           = \@xtoc@partnumwidth ,
    chapter-num-width        = \@xtoc@chapternumwidth ,
    section-num-width        = \@xtoc@sectionnumwidth ,
    subsection-num-width     = \@xtoc@subsectionnumwidth ,
    subsubsection-num-width  = \@xtoc@subsubsectionnumwidth ,
    paragraph-num-width      = \@xtoc@paragraphnumwidth ,
    subparagraph-num-width   = \@xtoc@subparagraphnumwidth ,
    figure-num-width         = \@xtoc@figurenumwidth ,
    table-num-width          = \@xtoc@tablenumwidth
  }
  {%
    \AssignTemplateKeys
    \if@twocolumn
      \@restonecoltrue\onecolumn
    \else
      \@restonecolfalse
    \fi
    \@xtoc@headingfunction{\@xtoc@heading\@mkboth{\@xtoc@header}{\@xtoc@header}}%
    \@xtoc@makel@entry{part}%
    \@xtoc@makel@entry{chapter}%
    \@xtoc@makel@entry{section}%
    \@xtoc@makel@entry{subsection}%
    \@xtoc@makel@entry{subsubsection}%
    \@xtoc@makel@entry{paragraph}%
    \@xtoc@makel@entry{subparagraph}%
    \@xtoc@makel@entry{figure}%
    \ifdefvoid\@xtoc@preamble{}
      {\@xtoc@preamble\par\addvspace{\@xtoc@preamblepostspace}}%
    \@starttoc{\@xtoc@fileextension}%
    \ifdefvoid\@xtoc@postamble{}
      {\par\addvspace{\@xtoc@postambleprespace}\noindent\@xtoc@postamble}%
    \if@restonecol\twocolumn\fi
  }


\DeclareInstance{xtoc}{article-toc}{list-of}{}
\DeclareInstance{xtoc}{article-lof}{list-of}{
  file-extension = lof ,
  heading = \listfigurename ,
  header  = \MakeUppercase\listfigurename
}
\DeclareInstance{xtoc}{article-lot}{list-of}{
  file-extension = lot ,
  heading = \listtablename ,
  header  = \MakeUppercase\listtablename
}

\DeclareInstance{xtoc}{book-toc}{list-of}{
  heading-function        = \chapter*{#1} ,
  depth                   = 2 ,
  part-level              = -1 ,
  section-entry           = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
  section-indent          = 1.5em ,
  section-num-width       = 2.3em ,
  subsection-indent       = 3.8em ,
  subsection-num-width    = 3.2em ,
  subsubsection-indent    = 7.0em ,
  subsubsection-num-width = 4.1em ,
  paragraph-indent        = 10em ,
  paragraph-num-width     = 5em ,
  subparagraph-indent     = 12em ,
  subparagraph-num-width  = 6em
}
\DeclareInstance{xtoc}{book-lof}{list-of}{
  file-extension = lof ,
  heading = \listfigurename ,
  header  = \MakeUppercase\listfigurename ,
  heading-function        = \chapter*{#1} ,
  depth                   = 2 ,
  part-level              = -1 ,
  section-entry           = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
  section-indent          = 1.5em ,
  section-num-width       = 2.3em ,
  subsection-indent       = 3.8em ,
  subsection-num-width    = 3.2em ,
  subsubsection-indent    = 7.0em ,
  subsubsection-num-width = 4.1em ,
  paragraph-indent        = 10em ,
  paragraph-num-width     = 5em ,
  subparagraph-indent     = 12em ,
  subparagraph-num-width  = 6em
}
\DeclareInstance{xtoc}{book-lot}{list-of}{
  file-extension = lot ,
  heading = \listtablename ,
  header  = \MakeUppercase\listtablename ,
  heading-function        = \chapter*{#1} ,
  depth                   = 2 ,
  part-level              = -1 ,
  section-entry           = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
  section-indent          = 1.5em ,
  section-num-width       = 2.3em ,
  subsection-indent       = 3.8em ,
  subsection-num-width    = 3.2em ,
  subsubsection-indent    = 7.0em ,
  subsubsection-num-width = 4.1em ,
  paragraph-indent        = 10em ,
  paragraph-num-width     = 5em ,
  subparagraph-indent     = 12em ,
  subparagraph-num-width  = 6em
}

\DeclareInstance{xtoc}{report-toc}{list-of}{
  heading-function        = \chapter*{#1} ,
  depth                   = 2 ,
  part-level              = -1 ,
  section-entry           = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
  section-indent          = 1.5em ,
  section-num-width       = 2.3em ,
  subsection-indent       = 3.8em ,
  subsection-num-width    = 3.2em ,
  subsubsection-indent    = 7.0em ,
  subsubsection-num-width = 4.1em ,
  paragraph-indent        = 10em ,
  paragraph-num-width     = 5em ,
  subparagraph-indent     = 12em ,
  subparagraph-num-width  = 6em
}
\DeclareInstance{xtoc}{report-lof}{list-of}{
  file-extension = lof ,
  heading = \listfigurename ,
  header  = \MakeUppercase\listfigurename ,
  heading-function        = \chapter*{#1} ,
  depth                   = 2 ,
  part-level              = -1 ,
  section-entry           = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
  section-indent          = 1.5em ,
  section-num-width       = 2.3em ,
  subsection-indent       = 3.8em ,
  subsection-num-width    = 3.2em ,
  subsubsection-indent    = 7.0em ,
  subsubsection-num-width = 4.1em ,
  paragraph-indent        = 10em ,
  paragraph-num-width     = 5em ,
  subparagraph-indent     = 12em ,
  subparagraph-num-width  = 6em
}
\DeclareInstance{xtoc}{report-lot}{list-of}{
  file-extension = lot ,
  heading = \listtablename ,
  header  = \MakeUppercase\listtablename ,
  heading-function        = \chapter*{#1} ,
  depth                   = 2 ,
  part-level              = -1 ,
  section-entry           = \xtocsubentry{#1}{#2}{#3}{#4}{#5} ,
  section-indent          = 1.5em ,
  section-num-width       = 2.3em ,
  subsection-indent       = 3.8em ,
  subsection-num-width    = 3.2em ,
  subsubsection-indent    = 7.0em ,
  subsubsection-num-width = 4.1em ,
  paragraph-indent        = 10em ,
  paragraph-num-width     = 5em ,
  subparagraph-indent     = 12em ,
  subparagraph-num-width  = 6em
}

\newrobustcmd*\setxtoc[1]{\EditTemplateDefaults{xtoc}{list-of}{#1}}

\ifbool{@xtoc@noredef}{}{%
  \IfInstanceExistTF{xtoc}{\@currname}{%
    \renewrobustcmd*\tableofcontents{\UseInstance{xtoc}{\@currname-toc}}%
    \renewrobustcmd*\listoffigures  {\UseInstance{xtoc}{\@currname-lof}}%
    \renewrobustcmd*\listoftables   {\UseInstance{xtoc}{\@currname-lot}}%
  }{%
    \renewrobustcmd*\tableofcontents[1][]{\UseTemplate{xtoc}{list-of}{#1}}%
    \renewrobustcmd*\listoffigures[1][]{\UseTemplate{xtoc}{list-of}{
      file-extension = lof ,
      heading = \listfigurename ,
      header  = \MakeUppercase\listfigurename ,
      #1
    }}%
    \renewrobustcmd*\listoftables[1][]{\UseTemplate{xtoc}{list-of}{
      file-extension = lot ,
      heading = \listtablename ,
      header  = \MakeUppercase\listtablename ,
      #1
    }}%
  }%
}

\endinput

Remark

I have no intension whatsoever of publishing this package otherwise than in this answer, nor in developing and maintaining it further. If someone wants to take this and make it into a real package: please do so:)

6
  • 1
    Honestly, are you doing some orange stuff right now? ;-) – Johannes_B Feb 2 '17 at 17:25
  • @Johannes_B no, I'm not! :) I had this question on my todo list for a while since I have a bit of experience with xtemplate – cgnieder Feb 2 '17 at 17:31
  • I have to lok at it as well sometime. And start developing the mega-class :-p – Johannes_B Feb 2 '17 at 17:32
  • @Johannes_B my next task will be to finally make a proper re-implementation of exsheets... – cgnieder Feb 8 '17 at 15:21
  • Oh. Exciting news. :-) – Johannes_B Feb 8 '17 at 15:23

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.