1

I'm trying to add a section* to the toc with addcontentsline. It's a macro as part of a larger group of commands I'm working on. What I want is to add the toc entry based on a section level counter. But using a macro to get the string for the current section level in addcontentsline causes an error I can't figure out. This is a minimal (not)working example of my problem (I'm using overleaf btw.)

\documentclass{article}
\usepackage[utf8]{inputenc}

\usepackage{xifthen}        % If else commands

\makeatletter
\newcounter{counter@section@level}

\newcommand{\currentSectionString}{
    \ifthenelse{\equal{\value{counter@section@level}}{0}}{section}{}
}

\makeatother

\begin{document}

\tableofcontents

\currentSectionString                    % to check the macro itself, works as expected

\section*{Foo}
\addcontentsline{toc}{section}{Foo}                  % works as expected

\section*{Bar}
\addcontentsline{toc}{\currentSectionString}{Bar}    % does not work

\section{FooBar}                                     % overlapping in toc

\end{document}
1

3 Answers 3

2

\ifthenelse is not expandable. You need that argument to expand to section but

\addcontentsline{toc}{\currentSectionString}{Bar}

is like

\addcontentsline{toc}{\def\tmp{section}\tmp}{Bar}

which would not work for the same reason.

You could use an expandable test such as \ifcase

\addcontentsline{toc}{\ifcase\mycounter section\or subsection\else error\fi}{Bar}
1
  • Thanks. I tried the ifcase version. It's a little long for all levels, but it works. Jun 27, 2021 at 18:47
1

My impression is that you want to automatically add starred sections to the TOC.

\documentclass{article}
\usepackage[utf8]{inputenc}

\NewCommandCopy{\latexsection}{\section}
\NewCommandCopy{\latexsubsection}{\subsection}

\RenewDocumentCommand{\section}{sO{#3}m}{%
  \IfBooleanTF{#1}{% starred section
    \latexsection*{#3}%
    \checkfortoc{#3}{\addcontentsline{toc}{section}{#3}}%
  }{% nonstarred section
    \latexsection[#2]{#3}%
  }%
}
\RenewDocumentCommand{\subsection}{sO{#3}m}{%
  \IfBooleanTF{#1}{% starred subsection
    \latexsubsection*{#3}%
    \addcontentsline{toc}{subsection}{#3}%
  }{% nonstarred section
    \latexsubsection[#2]{#3}%
  }%
}
% do the same for the other sectional levels you need

\ExplSyntaxOn
\NewDocumentCommand{\checkfortoc}{mm}
 {
  \str_if_eq:eeF { #1 } { \contentsname } { #2 }
 }
\ExplSyntaxOff


\begin{document}

\tableofcontents

\section*{Foo}

\section*{Bar}

\section{FooBar}

\end{document}

An additional check is needed for \section, because \tableofcontents does \section*{\contentsname}, but the table of contents should not go in the table of contents.

1
  • Thanks for your answer. I went with the other approach because it fits the rest of my code better. You are almost right. It's part of a relative sectioning I'm writing with key-value arguments. Jun 27, 2021 at 18:51
0

E.g., \addcontentsline{toc}{section}{Foo} beneath other things triggers that during the inputting of the .toc-file the macro \contentsline does
\csname l@section\endcsname\l@section.

Thus the second argument of \addcontentsline must consist of tokens which can be used between \csname..\endcsname, i.e., tokens whose expansion does not yield non-character-tokens.
\ifthenelse-stuff yields non-character-tokens and therefore can be used neither between \csname..\endcsname nor with macro-arguments that at some stage are inserted between \csname..\endcsname. Same for macros whose expansion at some stage yields \ifthenelse-stuff.

If you insist in sticking to \ifthenelse-stuff you need to change the order of processing to have \ifthenelse-stuff done before it comes to processing \addcontentsline—what about this? :

\documentclass{article}
\usepackage[utf8]{inputenc}

\usepackage{xifthen}        % If else commands

\makeatletter
\newcounter{counter@section@level}%
% The optional argument of \DoWithCurrentSectionString denotes tokens that
% process "{section}" as argument.
\newcommand{\DoWithCurrentSectionString}[1][\@firstofone]{%
    \ifthenelse{\equal{\value{counter@section@level}}{0}}{#1{section}}{%
%      \ifthenelse{\equal{\value{counter@section@level}}{1}}{#1{subsection}}{%
%         ...
%      }%
    }%
}%
\makeatother

\begin{document}

\tableofcontents

\noindent\hrulefill

\DoWithCurrentSectionString               % to check the macro itself, works as expected

\kern\ht\strutbox\hrule\hfill

\section*{Foo}
\addcontentsline{toc}{section}{Foo}                  % works as expected

\section*{Bar}
\DoWithCurrentSectionString[{\addcontentsline{toc}}]{Bar}    % does work

\section{FooBar}                                     % overlapping in toc

\end{document}

enter image description here

the .aux-file:

\relax 
\@writefile{toc}{\contentsline {section}{Foo}{1}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{Bar}{1}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {1}FooBar}{1}{}\protected@file@percent }
\gdef \@abspage@last{1}

the .toc-file:

\contentsline {section}{Foo}{1}{}%
\contentsline {section}{Bar}{1}{}%
\contentsline {section}{\numberline {1}FooBar}{1}{}%


For the sake of having fun here is an expandable approach which does with delimited arguments instead of \if...-constructs:

\documentclass{article}
\usepackage[utf8]{inputenc}

\makeatletter
\newcounter{counter@section@level}
\newcommand{\currentSectionString}{%
   \expandafter\currentSectionStringSelect\expandafter{\number\value{counter@section@level}}%
}%
\newcommand\currentSectionStringSelect[1]{%
  \currentSectionStringFork
  #1!1!2!3!4!{section}%
  0!#1!2!3!4!{subsection}%
  0!1!#1!3!4!{subsubsection}%
  0!1!2!#1!4!{paragraph}%
  0!1!2!3!#1!{subparagraph}%
  0!1!2!3!4!{subparagraph}%
  !!!!%
}%
\@ifdefinable\currentSectionStringFork{%
  \long\def\currentSectionStringFork#10!1!2!3!4!#2#3!!!!{#2}%
}%
\makeatother

\begin{document}

\tableofcontents

\noindent\hrulefill

\currentSectionString               % to check the macro itself, works as expected

\kern\ht\strutbox\hrule\hfill

\section*{Foo}
\addcontentsline{toc}{section}{Foo}                  % works as expected

\section*{Bar}
\addcontentsline{toc}{\currentSectionString}{Bar}    % does work

\section{FooBar}                                     % overlapping in toc

\end{document}

enter image description here

the .aux-file:

\relax 
\@writefile{toc}{\contentsline {section}{Foo}{1}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{Bar}{1}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {1}FooBar}{1}{}\protected@file@percent }
\gdef \@abspage@last{1}

the .toc-file:

\contentsline {section}{Foo}{1}{}%
\contentsline {section}{Bar}{1}{}%
\contentsline {section}{\numberline {1}FooBar}{1}{}%

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.