2

When using the titlesec package to customize part headers, the counter \thepart is somehow incremented before its value is used in, for example, running headers:

\documentclass[oneside]{book}
\usepackage{titlesec}

% If you do not issue the \titleformat command, everything is fine
\titleformat{\part}[display]
            {\bfseries\huge\filcenter}
            {\partname\ \thepart%
             % A working hack: set the mark here instead, expanding \thepart
             % (note the lack of \protect)
             %\markright{Part \thepart, page \protect\thepage} 
            }
            {20pt}
            {\Huge}
\titlespacing*{\part}{0pt}{*36}{*1}

\begin{document}
\part{Intro}
\pagestyle{myheadings}

% Remove this to see the hack work.
\markright{Part \protect\thepart, page \protect\thepage}

This page should have ``\textsl{Part \thepart, page \thepage}'' at the top.
\newpage
This page should have ``\textsl{Part \thepart, page \thepage}'' at the top.
\part{A Problem}                % This command does the incrementing
\end{document}

Page 3 – the last page in Part I – is the problem:

Demonstration of \thepart counter error on page 3

Somehow the second \part{A Problem} is advancing the counter before the counter is used in the header.

What exactly is the problem, and what is the suggested fix? One can hack a solution as shown, saving the value of the \thepart counter when the part is typeset, but this is not a satisfactory solution as I would like a user to be able to use the counter in custom headers etc.

The titlesec manual notes that parts are somewhat unique and non-starndard, but this seems like a bug to me.

Update

In response to the answer by @hugovdberg, I can trace the problem to the following definition in titlesec.sty:

\makeatletter\def\ttl@page@i#1[#2]#3{%
  \gdef\ttl@savemark{\csname#1mark\endcsname{#3}}%
  \def\ttl@savewrite{\ttl@write{#1}{#3}}%  A default value. Not #2!
  \def\ttl@savetitle{#3}%
  \ttl@labelling{#1}{#2}%
  \ttl@startargs\ttl@page@ii{#1}{#3}}

The \clearpage commands that will cause the headers to be processed is inside the \ttl@startargs\ttl@page@ii{#1}{#3} call while the part counter is increased in the previous \ttl@labelling{#1}{#2} call. Switching the order of these fixes the problem, but I do not know if there are other consequences. Seems like a bug to me.

Second Update

There are some questions about why I need to \protect\thepage: it is because \markright expands its arguments, but because of the way the standard classes reset the headers each time, this forces me to call \markright after each part, so using an expanded (unprotected) \thepart will appear to solve the problem. Here is a second, not quit MWE that uses fancyhdr to demonstrate that there really is a problem, and it has nothing to do with protection:

\documentclass[oneside]{book}
\usepackage{titlesec}
\usepackage{fancyhdr}

% Now I can do this once and for all: no protection needed.
\chead{Part \thepart, page \thepage}

% If you do not issue the \titleformat command, everything is fine
\titleformat{\part}[display]
            {\bfseries\huge\filcenter}
            {\partname\ \thepart%
             % A working hack: set the mark here instead, expanding \thepart
             % (note the lack of \protect)
             %\markright{Part \thepart, page \protect\thepage} 
            }
            {20pt}
            {\Huge}
\titlespacing*{\part}{0pt}{*36}{*1}

\begin{document}
\pagestyle{fancy}
\part{Intro}

This page should have ``\textsl{Part \thepart, page \thepage}'' at the top.
\newpage
This page should have ``\textsl{Part \thepart, page \thepage}'' at the top.
\part{A Problem}                % This command does the incrementing

A new page
\end{document}

Demonstration of problem with fancyhdr and no protection

Related

  • I tried sending a bug report on the page tex-tipografia.com/contact.html but the form failed. – mforbes Feb 26 '14 at 4:53
  • I'm seeing this and I'll have a look at it. – Javier Bezos Feb 26 '14 at 14:37
  • Why are you protecting \thepart in \markright (you shouldn't). If I remove \protect it works. – Javier Bezos Feb 26 '14 at 14:43
  • Because \markright expands its arguments. This is a little hard to demonstrate with the standard classes since I need to reset the header each time, but is easy to show with the KOMA classes. (I thought at first it might be a KOMA/titlesec issue, but it is not.) I will update the MWE shortly with will use fancyhdr: there expansion is not done, and using an unprotected \thepart fails exactly as here. – mforbes Feb 26 '14 at 18:38
2

The problem is the \part{A Problem} is executed on the last page of your first part, and the value of \thepart is the part number at the end of the current page. Since you start a new part on that page, even though the part title is printed on the next, your part counter is increased. The solution is to manually enter a \newpage before \part. This will not create superfluous empty pages since \part will only insert blank pages to get to a recto page.

Edit To automatically insert this for every part the accepted answer to this question could be used.

\documentclass[oneside]{book}
\usepackage{titlesec}

% If you do not issue the \titleformat command, everything is fine
\titleformat{\part}[display]
            {\bfseries\huge\filcenter}
            {\partname\ \thepart%
             % A working hack: set the mark here instead, expanding \thepart
             % (note the lack of \protect)
             %\markright{Part \thepart, page \protect\thepage} 
            }
            {20pt}
            {\Huge}
\titlespacing*{\part}{0pt}{*36}{*1}

\let\oldpart\part
\renewcommand{\part}{\clearpage\oldpart}

\begin{document}
\part{Intro}
\pagestyle{myheadings}

% Remove this to see the hack work.
\markright{Part \protect\thepart, page \protect\thepage}

This page should have ``\textsl{Part \thepart, page \thepage}'' at the top.
\newpage
This page should have ``\textsl{Part \thepart, page \thepage}'' at the top.
\part{A Problem}                % This command does the incrementing
\end{document}
  • That makes sense, but one should be able to get away without having to do this. Does the standard \part command do this in a way that titlesec fails to redefine properly? – mforbes Feb 26 '14 at 4:08
  • Apparently this is a known problem with the titlesec package, updated my answer to include the a \clearpage automatically. – hugovdberg Feb 26 '14 at 8:40
  • Can you point me to a discussion about the "known problem"? It seems to me that the correct answer to the question you mention should actually be \titleclass{\part}{top} (the highest voted answer), but that does not fix my issue either. The solution of adding \clearpage to every part does work, but still seems like a hack: I think it should be possible to emulate the standard book behaviour without resorting to hacks like this. – mforbes Feb 26 '14 at 10:27
  • What I meant to say is that this problem occurs to other people as well. As I said, the hack of adding a \clearpage comes without a penalty. Besides, it really wouldn't surprise me if the standard book behaviour is to do a \clear(double)page first and then increment the counter, whereas this is somehow swapped in the titlesec package. By the way, at least this hack works whereas the highest voted answer apparently doesn't ;-) – hugovdberg Feb 26 '14 at 10:40
  • Yes - the standard classes do exactly that. I think I am convinced now that there is a bug in titlesec, and that the correct way to deal with it until it gets fixed is the \clearpage hack, so I will accept your answer until titlesec is fixed. – mforbes Feb 27 '14 at 17:34
2

Remove the \protect before \thepart. The mark mechanism relies on its expansion when the mark is emitted and not when it's typeset. You are protecting \thepart and therefore it gets expanded in the headline, but at that point the value can be the wrong one. On the other hand, \thepage must be protected, because it's supposed to print the value when the headline is typeset, not when the mark is emitted.

EDIT For the same reason, \thepart mustn't be used directly in heads/foots (well, you can if you are using titleps, which `hides' the mark mechanism). Just use marks, which are the correct mechanism to pass info to headlines. See my comment below.

  • I understand the idea here – it was the basis for what I called my "hack" – but my second example using fancyhdr should clarify that the standard mechanism does not rely on expansion of the mark at definition time. Instead, the standard mechanism ensures that the page is cleared before \thepart is incremented, which I think is the bug in titlesec. – mforbes Feb 27 '14 at 17:30
  • It seems it should be easy to fix titlesec so that the \clearpage occurs before the counter is updated, but I am afraid to suggest a full bugfix as I am most-likely unaware of additional unintended side-effects of rearranging things at a high level. Do you have some regression tests for titlesec behaviour? If so, I would feel more confident taking a stab at fixing this. I really appreciate titlesec and would love for it to work flawlessly. Fixing KOMA compatibility would also be fantastic... (P.S. I still can't send you a note with your web form.) – mforbes Feb 27 '14 at 17:43
  • Nope. Where the counter is increased is irrelevant - what's relevant is where the mark is emitted. The example with fancyhdr is wrong, too, because you are using \thepart in the the headline, and its value must be passed in a mark. This is the whole point of the mark mechanism! No bug here - just pass the info to headlines as explained in LaTeX manuals. – Javier Bezos Feb 28 '14 at 7:38

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.