3

I am involved in the later stages of a big project, in which we use the following \tocless command to exclude specific subsections from appearing in the table of contents:

\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[2]{\bgroup\let\addcontentsline=\nocontentsline#1{#2}\egroup}

However, I recently found out that this messes up the references as can be seen in the enclosed MWE. Is there a way to change the definition of \tocless to correct this behaviour?

\documentclass[12pt,a4paper]{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[2]{\bgroup\let\addcontentsline=\nocontentsline#1{#2}\egroup}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\tocless\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}

bad refs

jpb
  • 501

4 Answers4

5

The problem stems from grouping the sectional unit, which negates the referencing capability. One solution would be to place the \label inside the title, but that would require a coding change.

The following avoids grouping in the definition of \tocless by restoring the definition of \addcontentsline after the sectional unit:

enter image description here

\documentclass{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}
\let\oldaddcontentsline\addcontentsline
\newcommand{\tocless}[2]{%
  \let\addcontentsline\nocontentsline
  #1{#2}
  \let\addcontentsline\oldaddcontentsline}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\tocless\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
  \item referring to 1.1: \ref{subsec:AA}
  \item referring to 1.2: \ref{subsec:AB}
  \item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}

When a sectional unit is created, the appropriate counter is \refstep-ed, which leads to an update of a macro called \@currentlabel. \@currentlabel is updated using \def, which has a local scope and doesn't survive beyond the group.

Werner
  • 603,163
4

Here's a solution by temporarily changing the tocdepth counter (writing to .toc file and then restoring)

\documentclass[12pt,a4paper]{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[1]{\addtocontents{toc}{\protect\setcounter{tocdepth}{1}}%
  #1
  \addtocontents{toc}{\protect\setcounter{tocdepth}{2}}%
}


\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless{\subsection{this is a subsection not in TOC}}\label{subsec:AB}

\section{this the second section}
\tocless{\subsection{this is another subsection not in TOC}}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}

enter image description here

Update A slightly improved tocless command that has an optional argument, indicating a tocdepth level.

\documentclass[12pt,a4paper]{memoir}
\usepackage{etoolbox}
\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\tocless}[2][]{%
  \begingroup
  \edef\temptocdepth{\number\value{tocdepth}}%
  \edef\newtocdepth{\the\numexpr\value{tocdepth}-1}% Calculating a default new tocdepth
  \ifblank{#1}{% Apply default
    \addtocontents{toc}{\protect\setcounter{tocdepth}{\newtocdepth}}%
  }{% Use the value from #1
    \addtocontents{toc}{\protect\setcounter{tocdepth}{#1}}%
  }%
  #2%
  \addtocontents{toc}{\protect\setcounter{tocdepth}{\temptocdepth}}% Restoring
  \endgroup
}


\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless{\subsection{this is a subsection not in TOC}}\label{subsec:AB}

\section{this the second section}
\tocless[2]{\subsection{this will be in in TOC}}\label{subsec:BA} 

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}
  • This solution is specific to \tocless\subsection, which one might as well replace by a single macro (say) \toclesssubsection. This will not work as expected if you're using \tocless\section. – Werner Mar 11 '16 at 18:27
  • @Werner: I added another solution with specification of the toc depth counter ago -- and I did not claim that it would work for other levels ;-) –  Mar 11 '16 at 18:39
  • @ChristianHupfer you answered exactly the question's title ;-) – touhami Mar 11 '16 at 18:42
  • @touhami: Yes -- not more, not less ;-) –  Mar 11 '16 at 18:46
2

You have to take care that \@currentlabel is the right one after the group ends. You also should be careful about the optional arguments to \subsection.

\documentclass[12pt,a4paper]{memoir}
\usepackage{xparse}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}

\newcommand{\nocontentsline}[3]{}

\makeatletter
\NewDocumentCommand{\tocless}{msoom}{%
  \begingroup
  \let\addcontentsline\nocontentsline
  \IfBooleanTF{#2}
    {#1{#5}}% case \subsection*{z}
    {\IfNoValueTF{#3}
       {#1{#5}}% case \subsection{z}
       {\IfNoValueTF{#4}
          {#1[#3]{#5}}% case \subsection[x]{z}
          {#1[#3][#4]{#5}% case \subsection[x][y]{z}
       }%
    }%
  }%
  \edef\x{\endgroup\def\noexpand\@currentlabel{\@currentlabel}}\x
}
\makeatother

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}
\tocless\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\tocless\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}

\end{document}

enter image description here

egreg
  • 1,121,712
2

The memoir class has the \settocdepth-command (which other class can get with the tocvsec2 package) to (temporarly or globally) set the toc depth:

\documentclass[12pt,a4paper]{memoir}

\setcounter{tocdepth}{2}
\usepackage[usehighlevels]{alnumsec}
\alnumsectionlevels{1}{section,subsection,subsubsection,paragraph}
\alnumsecstyle{aaaa}
\surroundarabic[{.}][]{}{}
\otherseparators{1}
\alnumsecstyle{aaaa}


\newcommand{\nocontentsline}[3]{}
\newcommand{\tocless}[2]{\bgroup\let\addcontentsline=\nocontentsline#1{#2}\egroup}

\begin{document}

\tableofcontents

\section{this the first section}
\subsection{this is a normal subsection}\label{subsec:AA}

\settocdepth{section}
\subsection{this is a subsection not in TOC}\label{subsec:AB}

\section{this the second section}
\subsection{this is another subsection not in TOC}\label{subsec:BA}

\begin{itemize}
\item referring to 1.1: \ref{subsec:AA}
\item referring to 1.2: \ref{subsec:AB}
\item referring to 2.1: \ref{subsec:BA}
\end{itemize}


\settocdepth{subsection}
\subsection{this is again in the toc}
\end{document}

enter image description here

Ulrike Fischer
  • 327,261