2

I have a document with very long section titles which span multiple lines (potential exam questions). I'd like to restrict them to one line in the table of contents.

I just found out that this is easy to achieve manually by providing a short title, e.g., \subsection[Short Title]{Title}. However, I'd like to automatize this. I'm pretty sure that it's easy to redefine \subsection etc. to automatically set the respective short title, I'm just not adept enough to come up with this myself.

Example:

\documentclass{article}
\begin{document}
\tableofcontents

\section{What I have}

\subsection{This is an insanely long subsection title that is supposed to span multiple lines, which it does because it's insanely long}
\subsubsection{This is a similarly long subsubsection title that should also span more than one line, which it does as it's very long}

\section{What I want}

\subsection[This is an insanely long subsection title that is supposed to span\ldots]{This is an insanely long subsection title that is supposed to span multiple lines, which it does because it's insanely long}
\subsubsection[This is a similarly long subsubsection title that should\ldots]{This is a similarly long subsubsection title that should also span more than one line, which it does as it's very long}

\end{document}

Ideally, the titles in the TOC would automatically be truncated wordwise such that they just fit on one line, but a solution with a fixed width or even a fixed number of characters would be OK as well.

Bonus requirement: I'm also coloring the titles to indicate the status of the respective section, i.e., a solution that also works with titles wrapped in \textcolor{...}{...} (or allows to set the color by means of an optional argument or so) would be great.

  • 1
    I think it's easier to do if you use a guard to mark where you want the split, something like \subsection{This is a long \splithere subsection title}. Do you want an answer with that? – Phelype Oleinik Oct 10 '18 at 13:02
  • @PhelypeOleinik Yes, please, that's already much better than the manual "solution" in my example. – flotzilla Oct 10 '18 at 13:06
4

This solution uses a dummy guard token \splithere to get the ToC material from the rest of the section title:

\documentclass{article}

\makeatletter
\def\DefSplitSection#1#2{%
  \def#1{\split@startsection#2}%
}
\def\split@startsection#1#2{%
  \split@section@aux#1#2\splithere\@nil
}
\def\split@section@aux#1#2\splithere#3\@nil{%
  \if\relax\detokenize{#3}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
    {#1{#2}}%
    {#1[#2]{#2#3}}%
}
\let\splithere\@empty
\makeatother

\DefSplitSection\splitsection\section
\DefSplitSection\splitsubsection\subsection
\DefSplitSection\splitsubsubsection\subsubsection

\begin{document}

\tableofcontents

\section{What I have}

\splitsubsection{This is an insanely long subsection title that is supposed to span \splithere multiple lines, which it does because it's insanely long}
\splitsubsubsection{This is a similarly long subsubsection title that should \splithere also span more than one line, which it does as it's very long}

\section{What I want}

\subsection[This is an insanely long subsection title that is supposed to span\ldots]{This is an insanely long subsection title that is supposed to span multiple lines, which it does because it's insanely long}
\subsubsection[This is a similarly long subsubsection title that should\ldots]{This is a similarly long subsubsection title that should also span more than one line, which it does as it's very long}

\end{document}

If no \splithere is used then the behaviour is the same as the standard sectioning command. Beware that this variant doesn't work with the optional * (it would be pointless, because this one doesn't write to the ToC) and doesn't work with the optional [...] argument (also pointless, because it already defines the optional argument internally).


Edit: With color support in an optional argument:

\documentclass{article}
\usepackage{xcolor}

\makeatletter
\def\DefSplitSection#1#2{%
  \def#1{\split@startsection#2}%
}
\def\split@startsection#1{%
  \let\split@color@cmd\@empty
  \@ifnextchar[%]
    {\split@color@startsection#1}%
    {\split@actually@startsection#1}%
}
\def\split@color@startsection#1[#2]{%
  \def\split@color@cmd{\color{#2}}%
  \split@actually@startsection#1%
}
\def\split@actually@startsection#1#2{%
  \split@section@aux#1#2\splithere\@nil
}
\def\split@section@aux#1#2\splithere#3\@nil{%
  \if\relax\detokenize{#3}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
    {#1{\split@color@cmd#2}}%
    {#1[\split@color@cmd#2]{\split@color@cmd#2#3}}%
}
\let\splithere\@empty
\makeatother

\DefSplitSection\splitsection\section
\DefSplitSection\splitsubsection\subsection
\DefSplitSection\splitsubsubsection\subsubsection

\begin{document}

\tableofcontents

\section{What I have}

\splitsubsection[blue]{This is an insanely long subsection title that is supposed to span \splithere multiple lines, which it does because it's insanely long}
\splitsubsubsection{This is a similarly long subsubsection title that should \splithere also span more than one line, which it does as it's very long}

\section{What I want}

\subsection[This is an insanely long subsection title that is supposed to span\ldots]{This is an insanely long subsection title that is supposed to span multiple lines, which it does because it's insanely long}
\subsubsection[This is a similarly long subsubsection title that should\ldots]{This is a similarly long subsubsection title that should also span more than one line, which it does as it's very long}

\end{document}
  • What is \@nil definition? Like \null? – Sigur Oct 10 '18 at 14:06
  • 2
    @Sigur No, \@nil is undefined (or in this case could be defined to anything). It's just a guard macro, just like \splithere that is very unlikely to appear in a section title. It could be \p@tat@es :) TeX will just look for it when grabbing the delimited argument to \split@section@aux (search for "TeX delimited arguments" to learn more). \null is defined as \hbox{}. It could be used instead of \@nil above, but I think it's less likely that someone will write \@nil in a section title, so I used it instead. – Phelype Oleinik Oct 10 '18 at 14:14
  • Thanks a lot, works great! One issue I ran into: I'm coloring the titles to indicate the status of the section, which breaks the splitting (\splithere is not recognized inside a \textcolor{...}{...}). I unsuccessfully tried to add the color as an optional argument (e.g., \splitsubsection[red]{...}), but at least managed to add the color as an additional mandatory argument (e.g., \splitsubsection{black}{...}). If you could add such an optional argument (provided it's not too difficult), that would be great! I'll add the color as a bonus requirement to the question. – flotzilla Oct 12 '18 at 7:55
  • @flotzilla Done. You can't just wrap the section title in \textcolor because when TeX is looking for the \splithere, it will respect brace groups. More generally, the \splithere cannot appear inside any pair of {...}, or it won't work. In this specific case you could've used \color{...} instead and it would have worked. – Phelype Oleinik Oct 12 '18 at 14:11
  • @PhelypeOleinik Thanks, works like a charm! Should've thought of \color instead of \textcolor, though... – flotzilla Oct 12 '18 at 16:08

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.