[Tex/LaTex] Todonotes: group list-of-todos by section

table of contentstoclofttodonotes

This is a follow up question to group list-of-todos by chapter. egreg's solution works great with classicthesis and scrreprt, and I've been trying to do the same without classicthesis and for scrartcl, i.e. add group the list of todos by section.

The code below is directly based on egreg's code and almost works, although it always adds the title of the last section as well, even when there is no todonote. So this is the first thing I need help fixing, and secondly there is probably an easier way to do this rather than using code based on classicthesis.

I'm not wed to tocloft, but I quite like it for customisations (which are not in this MWE).

\documentclass{scrartcl}

\usepackage{todonotes,tocloft,xpatch,hyperref}

% This is based on classicthesis chapter definition
\let\oldsec=\section
\renewcommand*{\section}{\secdef{\Sec}{\SecS}}
\newcommand\SecS[1]{\oldsec*{#1}}%
\newcommand\Sec[2][]{\oldsec[\texorpdfstring{#1}{#1}]{#2}}%

% https://tex.stackexchange.com/a/61267/11984
\makeatletter
\xapptocmd{\Sec}{\addtocontents{tdo}{\protect\todoline{\thesection}{#1}{}}}{}{}
\newcommand{\todoline}[1]{\@ifnextchar\Endoftdo{}{\@todoline{#1}}}
\newcommand{\@todoline}[3]{%
  \@ifnextchar\todoline
    {}
    {\contentsline{section}{\numberline{#1}#2}{#3}{}{}}%
}
\let\l@todo\l@subsection
\newcommand{\Endoftdo}{}

\AtEndDocument{\addtocontents{tdo}{\string\Endoftdo}}
\makeatother


\begin{document}
\listoftodos

\tableofcontents

\section{My first Section}\todo{Section 1 note}
\subsection{A first Subsection}
\subsubsection{A first subsubsection}\todo{Section 1, section 1, subsection note}
\subsection{Another subsection}\todo{Section 1, section 1, subsection note 2}
\section{My second Section}
\subsection{Another subsection}\todo{Section 2, subsection 1 note}
\subsection{Another subsection}\todo{Section 2, subsection 2 note}
\section{A section without notes}
\subsection{A subsection without notes}
\subsubsection{A subsubsection without notes}
\end{document}

enter image description here

Best Answer

Here's a possible solution; only information for sections with \todo notes will be written to the List of Todos:

\documentclass{scrartcl}
\usepackage{todonotes,xpatch,hyperref}

% initial definitions for storing the section info (name and number)
\def\thissectiontitle{}
\def\thissectionnumber{}

\newtoggle{noTodos}

\makeatletter
% redefinition of \@sect so \section glbally stores its name and number 
\def\@sect#1#2#3#4#5#6[#7]#8{%
\ifnum #2>\c@secnumdepth
\let\@svsec\@empty
\else
\refstepcounter{#1}%
\protected@edef\@svsec{\@seccntformat{#1}\relax}%
\fi
\@tempskipa #5\relax
\ifdim \@tempskipa>\z@
\begingroup
#6{%
\@hangfrom{\hskip #3\relax\@svsec}%
\interlinepenalty \@M #8\@@par}%
\endgroup
\csname #1mark\endcsname{#7}%
\addcontentsline{toc}{#1}{%
\ifnum #2>\c@secnumdepth \else
\protect\numberline{\csname the#1\endcsname}%
\fi
#7}%
\else
\@xsect
\def\@svsechd{%
#6{\hskip #3\relax
\@svsec #8}%
\csname #1mark\endcsname{#7}%
\addcontentsline{toc}{#1}{%
\ifnum #2>\c@secnumdepth \else
\protect\numberline{\csname the#1\endcsname}%
\fi
#7}}%
\fi
\@xsect{#5}%
\ifnum#2=1\relax
\global\def\thissectiontitle{#8}
\global\def\thissectionnumber{\thesection}
\fi%
}

\pretocmd{\section}{\global\toggletrue{noTodos}}{}{}

% the \todo command does the job: the first time it is used after a \section command, 
% it writes the information of the section to the list of todos
\AtBeginDocument{%
  \xpretocmd{\todo}{%
    \iftoggle{noTodos}{
     \addtocontents{tdo}{\protect\contentsline {section}%
        {\protect\numberline{\thissectionnumber}{\thissectiontitle}}{}{} }
      \global\togglefalse{noTodos}
        }{}
    }{}{}%
  }
\makeatother

\begin{document}

\listoftodos
\tableofcontents

\section{My first Section}\todo{Section 1 note}
\subsection{A first Subsection}
\subsubsection{A first subsubsection}\todo{Section 1, section 1, subsection note}
\subsection{Another subsection}\todo{Section 1, section 1, subsection note 2}

\section{My second Section}
\subsection{Another subsection}\todo{Section 2, subsection 1 note}
\subsection{Another subsection}\todo{Section 2, subsection 2 note}

\section{A section without notes}
\subsection{A subsection without notes}
\subsubsection{A subsubsection without notes}

\section{My fourth Section}
\subsection{Another subsection}\todo{Section 2, subsection 1 note}
\subsection{Another subsection}\todo{Section 2, subsection 2 note}

\end{document}

enter image description here

Remarks and explanations

  1. This is basically an adaptation of my answer to Include chapters in List of Figures with titletoc?

  2. The \todo command does the job and decide if the section info will be written to the List of Todos; whenever the \todo command is used in the document, it will examine a boolean flag; if the boolean is false, then it adds the section information to the List of Todos and sets the boolean to true; otherwise, it does not add any information.

  3. The \section command was also modified to reset the boolean.

  4. \@sect was modified to globally store the information about the corresponding title and number for the section; this information will then be used when writing to the List of Todos.

Version using titlesec

In the comments it has been mentioned that the titlesec package is being used (which might produce undesired results with KOMA classes; see Incompatibilities between KOMA-Script and titlesec). In this case, using the explicit option the code simplifies considerable, since now there's no need to hook into \@sect to retrieve the name and number for sections: \documentclass{scrartcl} \usepackage{todonotes,xpatch,hyperref} \usepackage[explicit]{titlesec}

% initial definitions for storing the section info (name and number)
\def\thissectiontitle{}
\def\thissectionnumber{}

\newtoggle{noTodos}

\titleformat{\section}
  {\normalfont\Large\bfseries\sffamily}
  {\thesection}
  {0.5em}
  {\gdef\thissectiontitle{#1}\gdef\thissectionnumber{\thesection}#1}

\pretocmd{\section}{\global\toggletrue{noTodos}}{}{}

% the \todo command does the job: the first time it is used after a \section command, 
% it writes the information of the section to the list of todos
\AtBeginDocument{%
  \xpretocmd{\todo}{%
    \iftoggle{noTodos}{
     \addtocontents{tdo}{\protect\contentsline{section}%
        {\protect\numberline{\thissectionnumber}{\thissectiontitle}}{}{} }
      \global\togglefalse{noTodos}
        }{}
    }{}{}%
  }

\begin{document}

\listoftodos
\tableofcontents

\section{My first Section}\todo{Section 1 note}
\subsection{A first Subsection}
\subsubsection{A first subsubsection}\todo{Section 1, section 1, subsection note}
\subsection{Another subsection}\todo{Section 1, section 1, subsection note 2}

\section{My second Section}
\subsection{Another subsection}\todo{Section 2, subsection 1 note}
\subsection{Another subsection}\todo{Section 2, subsection 2 note}

\section{A section without notes}
\subsection{A subsection without notes}
\subsubsection{A subsubsection without notes}

\section{My fourth Section}
\subsection{Another subsection}\todo{Section 2, subsection 1 note}
\subsection{Another subsection}\todo{Section 2, subsection 2 note}

\end{document}