1

I am writing a math paper consisting of several Definitions, Lemmas, Theorems, Corollaries, etc. Every such part can have a title and/or a reference. In the text, I would like to have both the title and the reference appear. In the table of contents, I would like for only the title to appear. I have been able to come up with the following MWE. However, I would like to ask whether there is a more idiomatic way of achieving this. In particular, I'm unsure whether my handling of the keyword arguments using the keyval package could be made simpler, i.e. more idiomatic. In particular, I would like to avoid all the csname usage.

MWE:

\documentclass[border={10pt 10pt 10pt 10pt}]{standalone}

\usepackage{keyval}
\usepackage{etoolbox}
\usepackage{amsthm}
\usepackage{thmtools}
\makeatletter
\newcommand{\HelperDeclareTheorem}[4]{
  \define@key{#1@keys}{title}{\expandafter\def\csname #1@title\endcsname{##1}}
  \define@key{#1@keys}{reference}{\expandafter\def\csname #1@reference\endcsname{##1}}
  \declaretheorem[
    numberlike=subsubsection,
    name=#3,
    refname={#1, #2},
    Refname={#3, #4},
    style=definition
  ]{#1aux}
  \newenvironment{#1}[1][]{
    \setkeys{#1@keys}{##1}
    \@ifundefined{#1@title}{
      \@ifundefined{#1@reference}{
        \begin{#1aux}
      }{
        \def\reference{\csname #1@reference\endcsname}
        \begin{#1aux}[\reference]
      }
      \addcontentsline{toc}{subsubsection}{\protect\numberline{\thesubsubsection} #3}
    }{
      \def\title{\csname #1@title\endcsname}
      \@ifundefined{#1@reference}{
        \begin{#1aux}[\title]
      }{
        \def\reference{\csname #1@reference\endcsname}
        \begin{#1aux}[\title \  (\reference)]
      }
      \addcontentsline{toc}{subsubsection}{\protect\numberline{\thesubsubsection} #3 (\title)}
    }
  }{
    \end{#1aux}
  }
}
\makeatother
\HelperDeclareTheorem{definition}{definitions}{Definition}{Definitions}
\HelperDeclareTheorem{lemma}{lemmas}{Lemma}{Lemmas}
\HelperDeclareTheorem{theorem}{theorems}{Theorem}{Theorems}
\HelperDeclareTheorem{corollary}{corollaries}{Corollary}{Corollaries}

\begin{document}
\begin{minipage}{\textwidth}
\tableofcontents
\section{Section 1}
\subsection{Subsection 1.1}
\begin{definition}[]
This Definition has neither a title nor a reference.
\end{definition}
\begin{lemma}[title={Lemma A}]
This Lemma has a title but no reference.
\end{lemma}
\begin{theorem}[reference={Reference B}]
This Theorem has no title but a reference.
\end{theorem}
\begin{corollary}[title={Corollary C},reference={Reference D}]
This Corollary has both a title and a reference.
\end{corollary}
\end{minipage}
\end{document}

1

4
  • I don't think there's anything wrong with your code. Using \csname...\endcsname is just how you do this in classic tex. You can use expl3 (also l3keys) for nicer constructs if you want to be modern
    – mbert
    Commented Oct 17 at 13:50
  • Though, I'm not sure why you need #1@title, you could just define \smiley@title locally for each. Also probably not a good idea to use \title as a variable
    – mbert
    Commented Oct 17 at 13:52
  • @mbert What's wrong with using \title? Isn't it just a local variable which shadows the global variable?
    – Smiley1000
    Commented Oct 17 at 14:11
  • 2
    It's probably fine here but I think its good practice not to use standard latex commands as variable names. Since \title is unlikely to appear inside a theorem it shouldn't matter here
    – mbert
    Commented Oct 17 at 14:14

2 Answers 2

1

There is probably a way to simplify this so you don't need an auxiliary environment, but here is a quick demonstration that you don't need to define new keys and variables each time you define a theorem.

\documentclass[border={10pt 10pt 10pt 10pt}]{standalone}

\usepackage{keyval}
\usepackage{etoolbox}
\usepackage{amsthm}
\usepackage{thmtools}
\makeatletter
\def\smiley@title{}
\def\smiley@reference{}
\define@key{smiley@keys}{title}{\def\smiley@title{#1}}
\define@key{smiley@keys}{reference}{\def\smiley@reference{#1}}
\newcommand{\HelperDeclareTheorem}[4]{
  \declaretheorem[
    numberlike=subsubsection,
    name=#3,
    refname={#1, #2},
    Refname={#3, #4},
    style=definition
  ]{#1aux}
  \newenvironment{#1}[1][]{
    \setkeys{smiley@keys}{##1}
    \ifdefempty\smiley@title{
      \ifdefempty\smiley@reference{
        \begin{#1aux}
      }{
        \begin{#1aux}[\smiley@reference]
      }
      \addcontentsline{toc}{subsubsection}{\protect\numberline{\thesubsubsection} #3}
    }{
      \ifdefempty\smiley@reference{
        \begin{#1aux}[\smiley@title]
      }{
        \begin{#1aux}[\smiley@title \  (\smiley@reference)]
      }
      \addcontentsline{toc}{subsubsection}{\protect\numberline{\thesubsubsection} #3 (\smiley@title)}
    }
  }{
    \end{#1aux}
  }
}
\makeatother
\HelperDeclareTheorem{definition}{definitions}{Definition}{Definitions}
\HelperDeclareTheorem{lemma}{lemmas}{Lemma}{Lemmas}
\HelperDeclareTheorem{theorem}{theorems}{Theorem}{Theorems}
\HelperDeclareTheorem{corollary}{corollaries}{Corollary}{Corollaries}

\begin{document}
\begin{minipage}{\textwidth}

\tableofcontents
\section{Section 1}
\subsection{Subsection 1.1}
\begin{definition}[]
This Definition has neither a title nor a reference.
\end{definition}
\begin{lemma}[title={Lemma A}]
This Lemma has a title but no reference.
\end{lemma}
\begin{theorem}[reference={Reference B}]
This Theorem has no title but a reference.
\end{theorem}
\begin{corollary}[title={Corollary C},reference={Reference D}]
This Corollary has both a title and a reference.
\end{corollary}
\end{minipage}
\end{document}

Just for fun, you can do this with keytheorems (disclaimer, I wrote the package) by defining your own keys and setting the appropriate preheadhook and postheadhook. Requires v0.1.8 or later. This example uses Skillmon's good suggestion of making the second and third argument optional in \HelperDeclareTheorem.

\documentclass[border={10pt 10pt 10pt 10pt}]{standalone}

\usepackage{keytheorems}

\ExplSyntaxOn
\keys_define:nn { keytheorems/thmuse }
  {
    title     .tl_set:N = \l_smiley_title_tl,
    reference .tl_set:N = \l_smiley_reference_tl,
  }
\tl_new:N \l_smiley_tempnote_tl
\NewDocumentCommand{\HelperDeclareTheorem}{m O{#1s} m O{#3s}}
  {
    \newkeytheorem{#1}[
      numberlike=subsubsection,
      name=#3,
      refname={#1, #2},
      Refname={#3, #4},
      style=definition,
      preheadhook=
        {
          \tl_if_empty:NTF \l_smiley_title_tl
            { \tl_set_eq:NN \l_smiley_tempnote_tl \l_smiley_reference_tl }
            {
              \tl_set_eq:NN \l_smiley_tempnote_tl \l_smiley_title_tl
              \tl_if_empty:NF \l_smiley_reference_tl
                { \tl_put_right:Nn \l_smiley_tempnote_tl { ~ (\l_smiley_reference_tl) } }
            }
          \tl_if_empty:NF \l_smiley_tempnote_tl
            { \keys_set:nn { keytheorems/thmuse } { note=\l_smiley_tempnote_tl } }
        },
      postheadhook=
        {
          \tl_if_empty:NTF \l_smiley_title_tl
            { \addcontentsline{toc}{subsubsection}{\protect\numberline{\thesubsubsection} #3} }
            { \addcontentsline{toc}{subsubsection}{\protect\numberline{\thesubsubsection} #3 ~ (\l_smiley_title_tl)} }
        },
    ]
  }
\ExplSyntaxOff

\HelperDeclareTheorem{definition}{Definition}
\HelperDeclareTheorem{lemma}{Lemma}
\HelperDeclareTheorem{theorem}{Theorem}
\HelperDeclareTheorem{corollary}[corollaries]{Corollary}[Corollaries]

\begin{document}
\begin{minipage}{\textwidth}
\tableofcontents
\section{Section 1}
\subsection{Subsection 1.1}
\begin{definition}[]
This Definition has neither a title nor a reference.
\end{definition}
\begin{lemma}[title={Lemma A}]
This Lemma has a title but no reference.
\end{lemma}
\begin{theorem}[reference={Reference B}]
This Theorem has no title but a reference.
\end{theorem}
\begin{corollary}[title={Corollary C},reference={Reference D}]
This Corollary has both a title and a reference.
\end{corollary}
\end{minipage}
\end{document}
1

Just to show off a different key=value package (disclaimer: of which I'm the author), the following implements \HelperDeclareTheorem with expkv-def and its data key type. It uses two simple auxiliary macros \smiley@paren (prints its arguments with a leading space and in parentheses) and \smiley@begin (reorders some arguments for \begin{#1aux}[<oarg>]).

The data handler defines the macros \smiley@title and \smiley@ref to be both a boolean in the form \<macro>{<true>}{<false>} and to store the data given. It expands to <true>{<data>} if the key was used and to <false> otherwise.

For instance \smiley@ref\smiley@paren{} expands to either \smiley@paren{<reference>} or to nothing. Similarly the statement

\smiley@title
  {\smiley@begin{#1}{\smiley@ref\smiley@paren{}}}
  {\smiley@ref{\smiley@begin{#1}{}}{\begin{#1aux}}}%

expands to either \smiley@begin{#1}{\smiley@ref\smiley@paren{}}{<title>} if it was used or to \smiley@ref{\smiley@begin{#1}{}}{\begin{#1aux}}.

This way your decision making becomes very concise.

I also changed the argument structure of \HelperDeclareTheorem to take two optional arguments which default to the singular forms with an added s (only handy for languages with a rather regular plural form like English).

\documentclass[border={10pt 10pt 10pt 10pt}]{standalone}

\usepackage{amsthm}
\usepackage{thmtools}
\usepackage{expkv-def}

\makeatletter
\ekvdefinekeys{smiley}
  {
     data title = \smiley@title
    ,data reference = \smiley@ref
  }
\newcommand\smiley@paren[1]{ (#1)}
\newcommand\smiley@begin[3]{\begin{#1aux}[#3#2]}
\NewDocumentCommand\HelperDeclareTheorem { m O{#1s} m O{#3s} }
  {%
    \declaretheorem
      [
         numberlike = subsubsection,
        ,name       = {#3}
        ,refname    = {#1, #2}
        ,Refname    = {#3, #4}
        ,style      = definition
      ]
      {#1aux}%
    \newenvironment{#1}[1][]
      {%
        \ekvset{smiley}{##1}%
        \smiley@title
          {\smiley@begin{#1}{\smiley@ref\smiley@paren{}}}
          {\smiley@ref{\smiley@begin{#1}{}}{\begin{#1aux}}}%
        \addcontentsline{toc}{subsubsection}
          {%
            \protect\numberline{\thesubsubsection} #3%
            \smiley@title\smiley@paren{}%
          }%
      }
      {\end{#1aux}}%
  }
\makeatother

\HelperDeclareTheorem{definition}{Definition}
\HelperDeclareTheorem{lemma}{Lemma}
\HelperDeclareTheorem{theorem}{Theorem}
\HelperDeclareTheorem{corollary}[corollaries]{Corollary}[Corollaries]

\begin{document}
\begin{minipage}{\textwidth}
\tableofcontents
\section{Section 1}
\subsection{Subsection 1.1}
\begin{definition}[]
This Definition has neither a title nor a reference.
\end{definition}
\begin{lemma}[title={Lemma A}]
This Lemma has a title but no reference.
\end{lemma}
\begin{theorem}[reference={Reference B}]
This Theorem has no title but a reference.
\end{theorem}
\begin{corollary}[title={Corollary C},reference={Reference D}]
This Corollary has both a title and a reference.
\end{corollary}
\end{minipage}
\end{document}

You must log in to answer this question.

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