8

I'm using memoir class to write my master's thesis, and my university asks to align all section labels to the left. I say section, but I really mean all levels, as chapters, sections, subsecs and so on. So far, I've managed that.

The real problem is that they ask to align all the section titles based on the widest section label. I know that I can always guess what this length would be, but I was looking for an automatic way of getting this value from latex, so it would be easier when others wrote their thesis based on my source code (I'm kinda the pioneer on standardizing the text using latex...).

Incorrect TOC

This is how it looks right now. I wanted a way to know that my widest label is the label 2.2.4, so I could tell memoir its length. And then, if I added a subsubsection there, the new widest would be 2.2.4.1 and, again, its length would be automatically passed to memoir.


Edit: Since the contents of my document are really a lot, I split it, putting each chapter in a different .tex, including everything in the "master document". Also, I'm using pdflatex from the standard texlive that comes with Ubuntu 13.04.


Edit: Here is a MWE based on one of the answers:

File: main.tex

\documentclass{memoir}
\usepackage[T1]{fontenc}

\setsecnumdepth{subsubsection}
\settocdepth{subsubsection}

\maxsecnumdepth{subsubsection}
\maxtocdepth{subsubsection}

\begin{document}
\frontmatter
\tableofcontents

\mainmatter

\include{chap1}
\include{chap2}

\end{document}

File: chap1.tex

\chapter{First Chapter}

\section{First Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}

\section{Second Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}

File: chap2.tex

\chapter{Second Chapter}

\section{First Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}

And I intend the TOC to output like this: Correct TOC

6

Related to the answer of Danie here a suggestion where the length of the widest label is written do the aux file. So you can use it at the begin of a document.

Some notes:

  • If you change secnumdepth the widest label won't be overwritten. You must delete the aux file.
  • You need two compilation runs.
  • I add a length of 0.5cm to the widest label to get some distance between number and text.

Here the mwe:

\RequirePackage{filecontents}
\begin{filecontents}{chap1.tex}
\chapter{First Chapter}

\section{First Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}

\section{Second Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}
\end{filecontents}
\begin{filecontents}{chap2.tex}
\chapter{Second Chapter}

\section{First Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}
\end{filecontents}
\documentclass{memoir}
\usepackage[T1]{fontenc}

\setsecnumdepth{subsubsection}
\settocdepth{subsubsection}

\maxsecnumdepth{subsubsection}
\maxtocdepth{subsubsection}
\makeatletter
\newlength\widesttoclabel
\setlength{\widesttoclabel}{0pt}
%\renewcommand*{\numberlinehook}[1]{%
%  \setbox0=\hbox{\@cftn@me\@cftbsnum #1\@cftasnum}%
%  \ifdim\wd0>\widesttoclabel%
%    \setlength{\global\widesttoclabel}{\the\wd0}%
%  \fi%
%}
\renewcommand*{\numberline}[1]{%
  \numberlinehook{#1}%
  \setbox0=\hbox{\@cftn@me\@cftbsnum #1\@cftasnum}%
  \ifdim\wd0>\widesttoclabel%
     \global\setlength{\widesttoclabel}{\the\wd0}%
  \fi%
  \hb@xt@\@tempdima{\@cftn@me\@cftbsnum #1\@cftasnum\hfil}\@cftasnumb}

\AtEndDocument{%
 \immediate\write\@mainaux{%
       \string\global\string\setlength{\string\widesttoclabel}{\the\widesttoclabel}%
 }%
}%
\makeatother
\AtBeginDocument{%
\cftsetindents{chapter}{0em}{\dimexpr\widesttoclabel+.5cm\relax}
\cftsetindents{section}{0em}{\dimexpr\widesttoclabel+.5cm\relax}
\cftsetindents{subsection}{0em}{\dimexpr\widesttoclabel+.5cm\relax}
\cftsetindents{subsubsection}{0em}{\dimexpr\widesttoclabel+.5cm\relax}
}

\begin{document}
\the\widesttoclabel
\frontmatter
\tableofcontents

\mainmatter

\include{chap1}
\include{chap2}

\end{document}

Edit. After two compilation steps I am getting the following result:

enter image description here

  • It just occurred to me to print the value of \thewidesttoclabel and see what comes off. Strangely, it claims that this size is 0.0pt... I don't know what can possibly be going on, since I just copied the example you gave me... Then I tried to compile your code and again the dimension was 0.0pt... Just to add more information, I'm using ubuntu 13.04, with the standard texlive version that comes with it. – araruna May 23 '13 at 17:15
  • @araruna: I added an image of the result. – Marco Daniel May 24 '13 at 8:21
  • @araruna how many times are you compiling your document? It needs to be compiled a few times, not just once – daleif May 24 '13 at 13:36
  • I just realized something. Your answer is not working for me because I split my document through several .tex files, and when I check the .aux files, none of them includes the information about \widesttoclabel! I tried compiling your example and it includes everything in the .aux, but when I tried splitting the chapters into two other files, \widesttoclabel just vanished... I'll try to edit my question to add that information. – araruna May 24 '13 at 16:45
  • @araruna: Edited. – Marco Daniel May 24 '13 at 20:07
5

Marcos solution is the way forward. But the \numberlinehook is actually intended to be used for this sort of measuring. By default it does nothing but gobble its argument. I just never got around to documenting it.

Thus you only need this change regarding \numberline:

\makeatletter
\renewcommand*{\numberlinehook}[1]{%
  \setbox0=\hbox{\@cftn@me\@cftbsnum #1\@cftasnum}%
  \ifdim\wd0>\widesttoclabel%
    \global\setlength{\widesttoclabel}{\the\wd0}%
  \fi%
}
\makeatother

I added the hook with this exact thing in mind, just never got around to documenting it.

It you want to be able to tell \section and \subsection apart from within \numberline, there it another undocumented macro called \cftwhatismyname that will hold the current type (i.e., section, subsection, etc.)

(they will be documented in the next release).

  • could you please edit your answer to contain the "whole document", just as Marco Daniel did? – araruna May 23 '13 at 16:51
  • It's just that I'm trying to use your solution, but the chapter names keep being written over their numbers... Here is what is going on when I add 0.5cm to \widesttoclabel: imageshack.us/photo/my-images/14/sumario2.png – araruna May 23 '13 at 16:59
2

I assume this is what you are needing? If you need to align the unnumbered chapter (such as contents) it will take a little bit of extra redefinitions of memoir internals.

\documentclass{memoir}
\usepackage[T1]{fontenc}

\renewcommand*\cftchapterfont{\bfseries\scshape}
\renewcommand*\cftsectionfont{\normalfont}
\renewcommand*\cftsubsectionfont{\normalfont}
\renewcommand*\cftsubsubsectionfont{\normalfont\itshape}

\renewcommand*\cftchapterdotsep{\cftdotsep}

\newlength\mydimA
\settowidth\mydimA{\cftsubsubsectionfont 2.10.10.10~}% -> widest number
\cftsetindents{chapter}      {0em}{\mydimA}
\cftsetindents{section}      {0em}{\mydimA}
\cftsetindents{subsection}   {0em}{\mydimA}
\cftsetindents{subsubsection}{0em}{\mydimA}

\setsecnumdepth{subsubsection}
\settocdepth{subsubsection}

\maxsecnumdepth{subsubsection}
\maxtocdepth{subsubsection}

\begin{document}
\frontmatter
\tableofcontents

\mainmatter
\chapter{First Chapter}

\section{First Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}

\section{Second Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}

\chapter{Second Chapter}

\section{First Section}
\subsection{Subsection}
\subsection{Subsection}
\subsubsection{Subsubsection}
\subsubsection{Subsubsection}

\end{document}

enter image description here

  • I appreciate your effort, @danie-els, but what you did here was guessing the widest label value, as 2.10.10.10 is not even there. I know it works, but I was hoping that I didn't need to hardcode myself that value everytime... – araruna Apr 21 '13 at 4:10
1

After some "fine tunning" and based on the answers of Marco Daniel and daleif, using something from Danie Els, and after asking this question: Write information on aux file when using include to build document , I was able to come up with this solution. I ask you to read the accepted answer to understand the reasons why everythisng is done the way it is in here.

Using the same two content files in the MWE, this is the new main.tex file:

File: main.tex

\documentclass{memoir}
\usepackage[T1]{fontenc}

% provides \AfterLastShipout command
\usepackage{atveryend}

\setsecnumdepth{subsubsection}
\settocdepth{subsubsection}

\maxsecnumdepth{subsubsection}
\maxtocdepth{subsubsection}

\newlength\wtl
\newlength\widesttoclabel
\setlength{\widesttoclabel}{0pt}

\makeatletter
\renewcommand*{\numberlinehook}[1]{%
    \settowidth\wtl{\@cftn@me\@cftbsnum #1\@cftasnum}%
    \ifdim\wtl>\widesttoclabel%
        \global\widesttoclabel=\the\wtl\relax%
    \fi%
}

% See why the use of this in the answer to the other question
\AfterLastShipout{%
    \if@filesw
        \immediate\write\@mainaux{%
            \global\string\widesttoclabel=\the\widesttoclabel\relax
        }%
    \fi
}
\makeatother

\AtBeginDocument{%
    \xdef\thewidesttoclabel{\the\widesttoclabel}%
    \cftsetindents{chapter}{0em}{\dimexpr\thewidesttoclabel+.5cm\relax}
    \cftsetindents{section}{0em}{\dimexpr\thewidesttoclabel+.5cm\relax}
    \cftsetindents{subsection}{0em}{\dimexpr\thewidesttoclabel+.5cm\relax}
    \cftsetindents{subsubsection}{0em}{\dimexpr\thewidesttoclabel+.5cm\relax}
}

\begin{document}
\frontmatter
\tableofcontents

\mainmatter

\include{chap1}
\include{chap2}

\end{document}

And this is the result after two compilation runs using pdflatex: final result

I think the only thing missing is handle the situation where the font size of the labels are manually changed, and then it should be complete.

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.