\documentclass[full]{l3doc}

\usepackage{mkessler-todo}

\title{%
   The \pkg{groupthm} package \\
   Theorem Groups and Families
}

\author{%
          Maximilian Keßler
}

\date{Released 2022-01-17}

\NewDocumentCommand{\kw}{m}
{%
  \texttt{#1}%
}

\NewDocumentCommand{\vocab}{m}
{%
  \emph{#1}%
}

\begin{document}
\maketitle

\begin{documentation}

\tableofcontents
  
A central thing in \LaTeX is the usage of \enquote{theorems}.
With \enquote{theorems} we actually mean \enquote{environments} that typically
have a title, some style applied to their contents and are numbered throughout 
the document, often later referenced by number and / or name.

Mechanisms for generating such environments are packages like
\pkg{amsthm}, \pkg{ntheorem}, \pkg{thmtools}.

While the mechanism in \pkg{thmtools} are pretty versatile and suffice
for almost all needs, it is pretty time-consuming to largely change
the behavior of environments, or have small variants of these.

This package aims at both providing a versatile mechanism, \meta{theorem group}s,
to structure theorems into groups that can subsequently easily altered,
as well as a mechanism for easily generating \meta{theorem families}.

As the author is of the opinion that of the mentioned theorem controlling packages
\pkg{thmtools} provides the most versatile interface, the \pkg{groupthm}
will be working on top of \pkg{thmtools} and use this as a backend for declaring
the \meta{theorem}s themselves.

Thus, any styles supported by \pkg{thmtools} will be supported by \pkg{groupthm}
as well, by passing them to \pkg{thmtools}.

\section{Concepts}

\subsection{Theorem groups}
\label{sec:theorem-groups}
A \meta{theorem group} is some named group holding some properties for
the \meta{theorem}s that are contained in this group.
Each \meta{theorem} can, when declared, be part of arbitrarily many \meta{theorem group}s,
and will be subject to the styles these groups defined.

This enables to group similar \meta{theorem}s and alter them at a late stage of
document development in a unique manner, by only having to change the
definition of the \meta{theorem group}, and not all \meta{theorem}s separately.

The properties. such a \meta{theorem group} can hold are as follows


\begin{description}
  \item[\kw{prename}] A prefix (any \meta{token list}) that will be inserted
    before the theorem name of each member of this \meta{theorem group}.
  \item[\kw{postname}] A suffix (any \meta{token list}) that will be
    inserted before the theorem name for each member of this \meta{theorem group}.
    This could be e.g.~some \enquote{$\star$} appended to the name to indicate
    variants of environments.
  \item[\kw{mapname}] A \meta{function} (some macro that takes exactly one argument)
    that is applied to the \kw{name}.
  \item[\kw{thmtools}] A \meta{clist} of key-value pairs that are passed to the underlying
    \pkg{thmtools} backend of the \meta{theorem}.
    This allows e.g.~to set the \kw{topskip} of a certain class of \meta{theorem}s.
\end{description}

The most versatile key here is certainly the \kw{thmtools} key,
providing the most customization to an end user (like you).

As mentioned, each \meta{theorem} can be member of arbitrary many \meta{theorem group}s,
and will posses their corresponding properties.

To adjust finer controlling of these \meta{theorem group}s, \meta{theorem group}s can inherit from each other, and \meta{theorem group}s are subject to a hierarchy that controls precedence in case
of conflicting properties of different \meta{theorem group}s a \meta{theorem} may be part of.

This hierarchy can of course be controlled by the user.

\subsection{Grouped theorems}

A \meta{grouped theorem} is just a theorem that is a member of
a given set of groups (possibly empty).
It behaves just a regular theorem, except that by changing the definition of
its theorem groups, we can alter its behavior.


It is the core concept of the \pkg{groupthm} package.
For brevity, we will often talk about \enquote{theorems},
although in fact we mean \enquote{grouped theorems}.

\subsection{Theorem families}
Often, one needs some small \meta{theorem variant}s of some \meta{theorem}, the most typical
example being \vocab{starred} version of \meta{theorem}s that are not numbered
in contrast to their counterparts.

\begin{verbatim}
  \begin{theorem}
    This theorem is numbered.
  \end{theorem}

  \begin{theorem*}
    This theorem is not numbered.
    Probably because we do not want a reference to it.
  \end{theorem*}
\end{verbatim}
\todo{insert code example output}

\pkg{groupthm} extends this idea and provides a versatile mechanism to define a
\meta{theorem family}, which is based on some \meta{theorem name} and
parses additional arguments / syntax to control the \meta{theorem groups}
that this environment is a part of.

So, in addition the name of a \meta{theorem}, the corresponding environment will
accept some options and toggle the membership of certain \meta{theorem groups},
thus further customizing its appearance.

This can lead e.g.~to usages like the following:

\begin{verbatim}
  \begin{theorem}*
    This theorem has a visual * at its name.
  \end{theorem}
\end{verbatim}
\todo{code}

Providing this consists of two parts:
declaring the \meta{theorem family} by listing the groups that can be toggled
by this \meta{theorem family}, and declaring the actual option parsing
of the \meta{theorem family}, which then controls the membership in these groups
(and of course prior to this the definition of the desired \meta{theorem group}s).



\subsection{General notions}

In many cases, there are a number of variants of some command,
call it for example \cs{Foo}.
Then the documentation will look like
%
\begin{function}{\NewFoo, \RenewFoo, \ProvideFoo, \DeclareFoo}
  Defines some \kw{foo} \ldots
\end{function}
%
and will not mention anything about the variants.
This follows some general naming convention that also \pkg{xparse} uses,
and is the following:

  \begin{description}
    \item[\cs{NewFoo}]

      Defines \kw{foo} if not defined already.
      This emits an error in case it has been defined yet.

    \item[\cs{RenewFoo}]

      Redefines \kw{foo} if defined already.
      This emits an error in case it has \emph{not} been defined yet.

    \item[\cs{ProvideFoo}]

      Defines \kw{foo} if it is not defined already.
      This does not emit an error if \kw{foo} is already defined
      (and has no effect in this case).

    \item[\cs{DeclareFoo}]

      Defines \kw{foo} in disregard of any
      existing definitions. Any old definition will be overwritten (if present).
  \end{description}
%
  The documentation margin will list all variants that are available,
  they follow their respective conventions.


  \begin{texnote}
    The \pkg{thmtools} package, unfortunately, dose not follow this convention,
    as its \cs{declaretheorem} command actually behaves like a \cs{newtheorem}.
    The reason for this is that \pkg{amsthm} already defines \cs{newtheorem}.

    Thus, actually, calls to \cs{NewGroupedTheorem} will have an underlying
    \cs{declaretheorem}, but you do not have to bother with this.
  \end{texnote}

\section{Theorem groups}

\subsection{Defining theorem groups}

\begin{function}{\NewTheoremGroup, \RenewTheoremGroup, \ProvideTheoremGroup, \DeclareTheoremGroup}
  \begin{syntax}
    \cs{NewTheoremGroup}[\meta{keys}]\{\meta{theorem group}\}
  \end{syntax}
  
  This introduces a new \meta{theorem group} with the given name.
  The \meta{keys} available are the same as introduced in \autoref{sec:theorem-groups}:

  \begin{description}
    \item

      \kw{prename} = \meta{token list}.
      Insert the \meta{token list} in front of the theorem name.

    \item

      \kw{postname} = \meta{token list}.
      Insert the \meta{token list} after the theorem name.

    \item

      \kw{mapname} = \meta{function}.
      Apply this \meta{function} to the theorem name.

    \item

      \kw{thmtools} = $\{$\meta{clist}$\}$.
      Pass these options to \pkg{thmtools}.

  \end{description}

  For uniqueness of the given options, the \meta{clist} given to the \kw{thmtools} key
  has to be surrounded by a pair of braces.

  \begin{texnote}
    The \kw{mapname} is expected to be a function of \cs{fun:n}.
    It is subject to an \kw{x}-type expansion prior to being passed further to \pkg{thmtools}.
  \end{texnote}

\end{function}

\subsection{Controlling theorem group precedence}

\begin{function}{\DeclareTheoremGroupRule}
    \begin{syntax}
\cs{DeclareTheoremGroupRule}[\meta{keyname}]%
\{\meta{theorem group 1}\}\{\meta{relation}\}\{\meta{theorem group 2}\}
    \end{syntax}
  
  This declares some relation between the two theorem groups,
  controlling their order of application in case a theorem is member
  of both groups.

  The \meta{keyname} can be one of \kw{prename}, \kw{postname}, \kw{mapname}, \kw{thmtools}.
  If present, it declares the corresponding relation only for this subkey.
  This can lead to \meta{theorem group 1} overwriting \meta{theorem group 2} when given
  contradictory \pkg{thmtools} options, but the \kw{prename} of \meta{theorem group 1}
  being applied after the one of \meta{theorem group 2}.
  When the \meta{keyname} is not given, this applies to all keywords.

  \begin{texnote}
    The \meta{keyname} is just passed to the corresponding argument
    of the \kw{lthooks} package.
    If the option argument is not present, \kw{??} is used, this has the described effect.
  \end{texnote}

  The behavior of the relations is based on the \cs{DeclareHookRule} command
  from the \pkg{xparse} package, and all respective keys are in fact available,
  but typically not needed, so the reader of this manual is referred to the
  \todoref{lthooks} packages documentation for a list of the full keys.
  For us, the following list will suffice:

  \begin{description}
    \item[\kw{higher} or \kw{after} or \kw{\string>}]
      
      \meta{theorem group 1} takes precedence over \meta{theorem group 2}.
      Its \kw{prename} is applied after the one of \meta{theorem group 2}.

    \item[\kw{lower} or \kw{before} or \kw{\string<}]

      \meta{theorem group 2} takes precedence over \meta{theorem group 1}.
      Its \kw{prename} is applied after the one of \meta{theorem group 1}.

  \end{description}

  \begin{texnote}
    The \meta{relation} is first stripped,
    then checked if it matches either \kw{higher} or \kw{lower}
    and in this case replaced by the corresponding \pkg{lthooks} variant
    of the relation.
    The rest is passed as is to \pkg{lthooks} and thus subject to the usual
    normalization process of \pkg{lthooks}.
  \end{texnote}

\end{function}


\subsection{Inheritance of theorem groups}
\begin{function}{\AddTheoremGroupParent}
  \begin{syntax}
    \cs{AddTheoremGroupParent}\{\meta{theorem group 1}\}\{\meta{theorem group 2}\}
  \end{syntax}
  Declares \meta{theorem group 1} to \enquote{inherit} all properties
  of \meta{theorem group 2}.
  In other words, \meta{theorem group 2} is a parent of \meta{theorem group 1}
  in a usual inheritance graph.

  The definitions of the groups themselves are unchanged,
  but each new theorem defined with \meta{theorem group 1} will also
  have the properties of \meta{theorem group 2}.

  Inheritance is transitive, when defining a new theorem, we just flatten out the
  inheritance graph and apply all properties.

  Inheritance is subject to the usual theorem group hierarchies as discussed in \todoref.
  This can even yield to situations, where \meta{theorem group 1} inherits
  from \meta{theorem group 2}, but \meta{theorem group 2} overwrites
  \meta{theorem group 1}.
\end{function}

\subsection{Appending to theorem groups}
\begin{function}{\AppendToTheoremGroup}
  \begin{syntax}
    \cs{AppendToTheoremGroup}[\meta{keys}]\{\meta{theorem group}\}
  \end{syntax}
  Adds the properties given as \meta{keys} to the theorem group.
  The syntax for the \meta{keys} is the same as in \cs{NewTheoremGroup}.
\end{function}

\subsection{Default theorem groups}

There are a number of theorem groups that \pkg{group them} will initially declare
and that have certain special treatment in some places.

\begin{function}{all}
  Every declared grouped theorem is a member of this group.

  Initially, this group has no effect (i.e.~an empty property list).
  It can be redefined by the user to alter the behavior of all grouped theorems
  in a unified way.

  It is the lowest theorem group in the hierarchy by default.
\end{function}

\begin{function}{starred}
  This is group that shall represent the standard variant of theorems that
  are called with a \enquote{*} in the environment name.
  Theorems of this group are not numbered.

  The user should not add theorems to this group by hand,
  as this is handled in a unified way by default.
  \todoref{}

  It is the highest theorem group in the hierarchy by default,
  except for \cs{unnumbered},
   with which it has no relation.
\end{function}
\addtocounter{footnote}{-1}

\begin{function}{unnumbered}
  Theorems in this group are not numbered.

 It is the highest theorem group in the hierarchy by default,
 except for \cs{starred},
 with which it has no relation.
\end{function}

The reason for the two groups \kw{starred} and \kw{unnumbered}
to both exist is that the \kw{starred} group is \emph{meant} to be applied
to theorems that were called with a \enquote{*} in their name (thus the name),
whereas the \enquote{unnumbered} group \emph{means} that the environment
is 'just unnumbered'.

This has two reasons:
First, this enables more fine-tuning of the behavior of the theorems in post-processing
of a document.
Second, more importantly, this distinguishes semantically between the environments
\kw{theorem} and \kw{theorem*}, even if \kw{theorem} is in the \kw{unnumbered} group.

So assuming that \kw{theorem} is member of the \kw{unnumbered} group, both calls

\begin{verbatim}
  \begin{theorem}
    This is not numbered.
  \end{theorem}
  \begin{theorem*}
    This is not numbered.
  \end{theorem*}
\end{verbatim}

are defined and will produce the same result by default, but we could still
change the definition of the \kw{starred} group later to do anything we want.

\begin{texnote}
  The mentioned hierarchies are kept intact for newly defined theorem groups,
i.e.~for each new such group, two theorem group rules are created.
\end{texnote}

\section{Grouped Theorems}

\subsection{Defining grouped theorems}

\begin{function}{\NewGroupedTheorem, \ProvideGroupedTheorem}
  \begin{syntax}
    \cs{NewGroupedTheorem}[\meta{keys}]\{\meta{theorem name}\}
  \end{syntax}
  This defines \meta{theorem name}  as a new theorem environment.
  Its properties can be set by the following keys:

  \begin{description}

    \item

      \kw{name} $=$ \meta{displayed name}.
      If given, this is the displayed name of the environment in the document.
      If not present, the \meta{theorem name} is also used as the \meta{displayed name}
      in capitalized form.

    \item

      \kw{group} $=$ \{\meta{clist}\}

      Makes this theorem a member of the listed groups.
      It will inherit all respective properties of these groups.

      If groups are present more than one time, this has no (additional) effect.

    \item

      \kw{thmtools} = \{\meta{clist}\}

      Passes these option to the \pkg{thmtools} environment that is declared internally.
    
  \end{description}
\end{function}

\begin{function}{\NewGroupedTheorem*,\ProvideGroupedTheorem*}
  \begin{syntax}
    \cs{NewGroupedTheorem*}[\meta{keys}]\{\meta{theorem name}\}
  \end{syntax}
  Behaves the same as \cs{NewGroupedTheorem},
  but also adds the theorem to the default \kw{unnumbered} group,
  thus resulting in the environment not being numbered.

  This is thus equivalent to using \cs{NewGroupedTheorem} and adding the
  \kw{unnumbered} group.
\end{function}

\begin{function}{\NewTheorem, \ProvideTheorem}
  \begin{syntax}
    \cs{NewTheorem}[\meta{keys}]\{\meta{theorem name}\}
  \end{syntax}

  This behaves essentially the same as \cs{NewGroupedTheorem},
  but will define two grouped theorems, namely \meta{theorem name} and \meta{theorem name*}.

  The \meta{theorem name*} environment has the same properties as the \meta{theorem name},
  but will be member of the \kw{starred} theorem group.
  It is thus not recommended to call \cs{NewTheorem}
  with an actual \enquote{*} in the environment name, since both environments
  will be generated.
\end{function}

\begin{function}{\NewTheorem*, \ProvideTheorem*}
  \begin{syntax}
    \cs{NewTheorem}[\meta{keys}]\{\meta{theorem name}\}
  \end{syntax}
  Combines the behavior of \cs{NewGroupedTheorem*} and \cs{NewTheorem}, thus
  declaring \meta{theorem} to (additionally) be member of the \kw{unnumbered}
  and \meta{theorem*} to (additionally) be member of the \kw{starred} group.

  As mentioned in \todoref, by default both environments will behave the same.
\end{function}

\subsection{Defining families of grouped theorems}

\begin{function}{\NewGroupedTheoremFamily, \ProvideGroupedTheoremFamily}
  \begin{syntax}
    \cs{NewTheoremFamily}[\meta{keys}]\{\meta{theorem name}\}
  \end{syntax}

  Defines a family of grouped theorems.
  The \meta{keys} accept the same arguments as the \cs{NewGroupedTheorem} macro.
  However, for each \emph{subset} of the given groups,
  a grouped theorem is defined.

  These grouped theorems are not meant to be accessed directly (but could),
  so we omit their actual (internal) names here.
  To call these, some \kw{GroupedTheoremFamilyOptions} have to specified,
  see \cs{NewGroupedTheoremFamilyOptions}.
\end{function}

\begin{function}{\NewGroupedTheoremFamily*, \ProvideGroupedTheoremFamily*}
  Behaves the same as \cs{NewGroupedTheoremFamily}, but also adds each variant
  to the default \kw{unnumbered} group, thus resulting in the environments not being
  numbered.

  This is \emph{almost} equivalent to calling \cs{NewGroupedTheoremFamily}
  with the \kw{unnumbered} group being present, as it does not generate the variants
  where the \kw{unnumbered} group is not present.
\end{function}

\begin{function}{\NewTheoremFamily, \ProvideTheoremFamily}
  This behaves essentially the same as \cs{NewGroupedTheoremFamily},
  but will add the \kw{starred} group to the list of groups and also generate variants
  for these.

  It is thus not recommended to call \cs{NewTheoremFamily} with the \kw{starred}
  group explicitly given, since this is added anyways.
\end{function}

\begin{function}{\NewTheoremFamily*, \ProvideTheoremFamily*}
  Combines the behavior of \cs{NewGroupedTheoremFamily*} and \cs{NewTheoremFamily}, thus
  declaring all variants to (additionally) be member of the \kw{unnumbered}
  group, and also generates definitions with and without the \kw{starred} group.

  As mentioned in \todoref, by default both environments will behave the same.
\end{function}


\begin{function}{\AddTheoremToGroup}
  \begin{syntax}
    \cs{AddTheoremToGroup}\{\meta{theorem group}\}
  \end{syntax}
  
  Means that the current invocation of a theorem family should
  call the theorem variant with the given group.

  Can only be used in the body of \cs{NewGroupedTheoremFamilyOptions} or similarly.
\end{function}

\begin{function}
{
  \NewGroupedTheoremFamilyOptions, \RenewGroupedTheoremFamilyOptions,
  \ProvideGroupedTheoremFamilyOptions, \DeclareGroupedTheoremFamilyOptions
}
\begin{syntax}
  \cs{NewGroupedTheoremFamilyOptions}\{\meta{theorem name}\}\{\meta{argument specifiation}\}%
  \{\meta{selection body}\}
\end{syntax}

Defines a new environment with options, given by \meta{theorem name}.
The \meta{argument specification} can be any valid \pkg{xparse} argument specification.

The \meta{selection body} is there to process the options of
the \meta{argument specification} and select which variant of the \meta{theorem name}
to enter.
The arguments are available as usual with \pkg{xparse} by \kw{\#1}, \kw{\#2}, \ldots

The body may also call any number of \cs{AddTheoremToGroup} calls,
which enables the corresponding groups.

When the environment is called within the document, the options are parsed
as with \pkg{xpars} and the \meta{selection body} is executed.
Immediately after, the theorem variant of \meta{theorem name} with the specified groups
by \cs{AddTheoremToGroup} is called.

At the end of the environment, the \meta{selection body} is executed again and the
called theorem variant is ended again.

The possible theorem variants that the newly declared environment will call
\emph{have to be generated subsequently} by a call to the \cs{NewGroupedTheoremFamily}
function.
  
\end{function}

\begin{function}
  {
    \NewGroupedTheoremFamilyOptions*, \RenewGroupedTheoremFamilyOptions*,
    \ProvideGroupedTheoremFamilyOptions*, \DeclareGroupedTheoremFamilyOptions*
  }
  \begin{syntax}
  \cs{NewGroupedTheoremFamilyOptions*}\{\meta{theorem name}\}\{\meta{argument specifiation}\}%
  \{\meta{selection body}\}
  \end{syntax}
  
  Does the same as \cs{NewGroupedTheoremFamilyOptions},
  but calls the variants with the additional \kw{unnumbered} group.

  The possible theorem variants have to be generated
  with the \cs{NewGroupedTheoremFamily*} command before.

\end{function}

\begin{function}
  {
    \NewTheoremFamilyOptions, \RenewTheoremFamilyOptions,
    \ProvideTheoremFamilyOptions, \DeclareTheoremFamilyOptions
  }
  \begin{syntax}
  \cs{NewTheoremFamilyOptions}\{\meta{theorem name}\}\{\meta{argument specifiation}\}%
  \{\meta{selection body}\}
  \end{syntax}

  This behaves essentially the same as \cs{NewGroupedTheoremFamilyOptions},
  but also declares the environment \meta{theorem name*},
  which behaves the same but calls the theorem variants with the additional \kw{starred}
  subgroup.

  The possible theorem variants have to be generated with the \cs{NewTheoremFamily}
  command before.
  
\end{function}

\begin{function}
  {
    \NewTheoremFamilyOptions*, \RenewTheoremFamilyOptions*,
    \ProvideTheoremFamilyOptions*, \DeclareTheoremFamilyOptions*
  }

  Combines the behavior of \cs{NewGroupedTheoremFamilyOptions*} and \cs{NewTheoremFamilyOptions},
  thus declaring both \meta{theorem name} and \meta{theorem name*} environments,
  the latter calling the \kw{starred} variants of the theorem family,
  and both of them calling \kw{unnumbered} variants of the family.

  The possible theorem variants have to be generated with the \cs{NewTheoremFamily*}
  command before.

\end{function}

%\section{\LaTeX3 interface}

\end{documentation}

\PrintIndex
\end{document}
