Thmtools – Using \listoftheorems for Named Theorems and Optional Arguments

thmtools

In the following, I have three kinds of theorems:

  1. an "ordinary" theorem, which just has the head "Theorem", as in the 3rd;
  2. a theorem having both a head and a note, "Theorem (…)", as in the 2nd; and
  3. a namedtheorem, where the note becomes the name, as in the 1st.

Desired format:
Wanted form for list of theorems

Question: What modification is needed so that the output from \listoftheorems removes the parentheses from the namedtheorem entry but preseres the parentheses of the note in a theorem having both head and note?

Failed attempt 1: removes parentheses for namedtheorem but unfortunately also removes them from the entry with the note.

\documentclass{article}
\usepackage{amsmath,amsthm,thmtools}

% For \listoftheorems
\renewcommand\thmtformatoptarg[1]{#1} % remove parens
\usepackage{xpatch}
\makeatletter
\patchcmd{\thmt@mklistcmd}{\thmt@thmname}{}{}{}
\makeatother

\swapnumbers

\declaretheoremstyle[
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\slshape,
]{thmstyle}
\declaretheorem[name=Theorem,style=thmstyle]{theorem}
    
\declaretheoremstyle[
  postheadspace=0.5em,
  notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  notefont=\bfseries,
  bodyfont=\slshape,
]{namedthmstyle}
\declaretheorem[
  style=namedthmstyle,
  name=Theorem,
  title = {},
  numberlike=theorem
]{namedtheorem}

\begin{document}

\listoftheorems[ignoreall,onlynamed={theorem,namedtheorem}]

\bigskip

\begin{namedtheorem}[Heine-Borel Theorem]
A closed and bounded subset of Euclidean $n$-space is compact.
\end{namedtheorem}

\begin{theorem}[compact subset of Hausdorff space]
A compact subset of a Hausdorff space is closed in that space.
\end{theorem}

\begin{theorem}
The square on the hypotenuse of a right triangle equals the sum of the squares on the other two sides.
\end{theorem}

\end{document}

No parens whatsoever in listoftheorems
Failed attempt 2: Comment out the line \renewcommand\thmtformatoptarg[1]{#1}. Then parentheses still remain around the entry for the namedtheorem.

Unwanted parens around name of named theorem

Question, restated: Thus, how can I somehow combine different treatments of a theorem having a parenthesized note, on the one hand, and a namedtheorem, on the other hand?

Related: https://tex.stackexchange.com/a/193020/13492, https://tex.stackexchange.com/a/180749/13492,https://tex.stackexchange.com/q/509672/13492, How make first letter upper-case in list of theorems?

Best Answer

There are several problems in the code you posted, aside from what you are asking about.

  1. The bit that does the \patchcmd does nothing in your minimal example (what it does, is to remove the theorem title from being shown in the listoftheorems only for unnumbered theorems. This doesn't make any sense to me so I removed it in my code below.
  2. The \makeatletter...\makeatother pair should encompass everything that uses the @ symbol, currently your \declaretheoremstyle macros do not include it, and so the code you showed does something different from its coded intent. I've moved the \makeatother to the correct place, and removed the declaration to remove \thmt@space from the basic thmstyle, since that space should be there and should not be removed.
  3. In defining namedtheorem, you specified both name and title; they are synonyms and you should specify only one.

Now, on to the real problem: the use of the \thmtformatoptarg macro is baked firmly into how thmtools handle the list of theorems. Specifically, we note that:

  1. The <project>.loe file which has all the theorem entries for the list of theorems uses \thmtformatoptarg. This means that any changes to \thmtformatoptarg will automatically apply to ALL entries, and you cannot do it selectively.
  2. And someone annoyingly, the onlynamed key in \listoftheorems detects the presence of \thmtformatoptarg in the contents line to decide whether to show that entry.

To work around the two problems, the following is a bit of a hack:

  1. We redefine how namedtheorems are written to the loe file, to ignore \thmtformatoptarg completely. This is most easily done by just completely redefining how things goes, rather than patching, so I also removed xpatch.
  2. We assume that every instance of namedtheorem comes with an optional argument (if not, the theorem name would be empty....), so instead of testing for onlynamed={namedtheorem}, we just do show={namedtheorem} which should functionally be the same.

With that, the following MWE is attained:

\documentclass{article}
\usepackage{amsmath,amsthm,thmtools}


\swapnumbers

\makeatletter
\declaretheoremstyle[
  headformat=\NAME\NUMBER\NOTE,
  bodyfont=\slshape,
]{thmstyle}
\declaretheorem[name=Theorem,style=thmstyle]{theorem}
    
\declaretheoremstyle[
  postheadspace=0.5em,
  notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  notefont=\bfseries,
  bodyfont=\slshape,
]{namedthmstyle}
\declaretheorem[
  style=namedthmstyle,
  title = \@empty,
  numberlike=theorem
]{namedtheorem}

%% Note, the following line must come AFTER the \declaretheorem...{namedtheorem}
%% as we are trying to overwrite the definition provided by thmtools
%% that occurs during the \declaretheorem process 
%% The definition below will still work if you don't \swapnumbers, but
%% it does assume that the namedtheorems are numbered. 
\@xa\def\csname ll@namedtheorem\endcsname{%
      \protect\ifthmt@listswap
        \thmt@shortoptarg~\csname thenamedtheorem\endcsname
      \protect\else
        \protect\numberline{\csname thenamedtheorem\endcsname}%
        \thmt@shortoptarg
      \protect\fi
    }%
\makeatother

\declaretheorem[name=Remark,style=thmstyle,numbered=no]{remark}


\begin{document}

\listoftheorems[ignoreall,onlynamed={theorem,remark},show={namedtheorem}]

\bigskip

\begin{namedtheorem}[Heine-Borel Theorem]
A closed and bounded subset of Euclidean $n$-space is compact.
\end{namedtheorem}

\begin{theorem}[compact subset of Hausdorff space]
A compact subset of a Hausdorff space is closed in that space.
\end{theorem}

\begin{theorem}
The square on the hypotenuse of a right triangle equals the sum of the squares on the other two sides.
\end{theorem}

\begin{remark}[Test]
    Test
\end{remark}

\end{document}

Output:

enter image description here


To automate the process somewhat, if you have multiple environments, we can redefine the \thmt@mklistcmd to do the right thing automatically. There may be better way to do this logic, but the following should work. (Basically, instead of printing \thmt@thmname, we test to see if it is empty, and if true, print the optional argument instead. But this means that when it comes time to print the optional argument, we should suppress it from printing at all if it has already been used in place of the empty \thmt@thmname. Note: I didn't bother to make the analogous change for unnumbered theorems; hopefully you can figure out what to change yourself by comparing this with the definition in thmtools/thm-listof.sty.)

\documentclass{article}
\usepackage{amsmath,amsthm,thmtools}

\swapnumbers
\makeatletter

\renewcommand\thmt@mklistcmd{%
  \thmtlo@newentry
  \ifthmt@isstarred
    \@xa\def\csname ll@\thmt@envname\endcsname{%
      \protect\ifthmt@listswap
      \protect\else
        \protect\numberline{\protect\let\protect\autodot\protect\@empty}%
      \protect\fi
      \thmt@thmname
      \ifx\@empty\thmt@shortoptarg\else\protect\thmtformatoptarg{\thmt@shortoptarg}\fi
    }%
  \else
    \@xa\def\csname ll@\thmt@envname\endcsname{%
      \protect\ifthmt@listswap
          \ifx\@empty\thmt@thmname\thmt@shortoptarg\else\thmt@thmname\fi~\csname the\thmt@envname\endcsname
      \protect\else
        \protect\numberline{\csname the\thmt@envname\endcsname}%
            \ifx\@empty\thmt@thmname\thmt@shortoptarg\else\thmt@thmname\fi
      \protect\fi
      \ifx\@empty\thmt@thmname\else\ifx\@empty\thmt@shortoptarg\else\protect\thmtformatoptarg{\thmt@shortoptarg}\fi\fi
    }%
  \fi
  \@xa\gdef\csname thmt@contentsline@\thmt@envname\endcsname{%
    \thmt@contentslineShow% default:show
  }%
}

\declaretheoremstyle[
  headformat=\NAME\NUMBER\NOTE,
  bodyfont=\slshape,
]{thmstyle}
\declaretheorem[name=Theorem,style=thmstyle]{theorem}
    
\declaretheoremstyle[
  postheadspace=0.5em,
  notebraces={}{},
  headformat=\NUMBER\let\thmt@space\@empty\NOTE,
  notefont=\bfseries,
  bodyfont=\slshape,
]{namedthmstyle}
\declaretheorem[
  style=namedthmstyle,
  title = \@empty,
  numberlike=theorem
]{namedtheorem}
\declaretheorem[
  style=namedthmstyle,
  title = {},
  numberlike=theorem
  ]{namedlemma}
\makeatother


\begin{document}

\listoftheorems[ignoreall,onlynamed={theorem},show={namedtheorem,namedlemma}]

\bigskip

\begin{namedtheorem}[Heine-Borel Theorem]
A closed and bounded subset of Euclidean $n$-space is compact.
\end{namedtheorem}

\begin{theorem}[compact subset of Hausdorff space]
A compact subset of a Hausdorff space is closed in that space.
\end{theorem}

\begin{theorem}
The square on the hypotenuse of a right triangle equals the sum of the squares on the other two sides.
\end{theorem}

\begin{namedlemma}[Borel-Cantelli Lemma]
    Very useful in analysis
\end{namedlemma}

\end{document}

This provides

enter image description here

Related Question