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. Commented 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. Commented 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}{}%

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .