7

I want to automatize some of the code that I usually include to setup my theorem environment functionality into a package. So here is what I do to control within which counter my theorems are numbered:

\RequirePackage{filecontents}

\begin{filecontents}{mytheorems.sty}
    \RequirePackage{xkeyval}
    \RequirePackage{amsthm}

    \DeclareOptionX{numberwithin}{%
        \theoremstyle{plain}%
        \newtheorem{theorem}{Theorem}[#1]%
    }
    \DeclareOptionX{nonumberwithin}{%
        \theoremstyle{plain}%
        \newtheorem{theorem}{Theorem}%
    }
    \ProcessOptionsX

    \theoremstyle{plain}
    \newtheorem{lemma}[theorem]{Lemma}
\end{filecontents}

\documentclass{article}

\usepackage[nonumberwithin]{mytheorems}%or use option [numberwithin=section] for example

\begin{document}
    \begin{lemma}
        content...
    \end{lemma}
\end{document}

Now I would like that the package is loaded with [nonumberwithin] if no option is given. However adding \ExecuteOptionsX{nonumberwithin} to the package won't allow [numberwithin=section] any longer because the two options clash. So what should I do?

8

In my opinion, the numberwithin etc. options should set a \if... variable and postpone the definition of the theorem according to the state of the, say, \if@numberwithin boolean. The argument of numberwithin must be stored, however.

As far as I know this is the way how standard LaTeX classes process mutually exclausive states for options.

\RequirePackage{filecontents}

\begin{filecontents}{mytheorems.sty}
    \RequirePackage{xkeyval}
    \RequirePackage{amsthm}

    \newif\if@numberwithin
    \def\@numberwithin{section}% Defining a default if needed        
    \DeclareOptionX{numberwithin}{%
      \@numberwithintrue
      \gdef\@numberwithin{#1}%
    }
    \DeclareOptionX{nonumberwithin}{%
      \@numberwithinfalse
    }
    \ExecuteOptionsX{nonumberwithin}
    \ProcessOptionsX

    \if@numberwithin
    \theoremstyle{plain}
    \newtheorem{theorem}{Theorem}[\@numberwithin]%
    \else
    \theoremstyle{plain}
    \newtheorem{theorem}{Theorem}%
    \fi

    \theoremstyle{plain}
    \newtheorem{lemma}[theorem]{Lemma}
\end{filecontents}

\documentclass{article}

%\usepackage[numberwithin=section]{mytheorems}%or use option [numberwithin=section] for example

\usepackage{mytheorems}%or use option [numberwithin=section] for example

\begin{document}
    \begin{lemma}
        content...
    \end{lemma}
\end{document}
  • Thank you. Good to know that it is common practice to only set some booleans in a package option. – John Dorian Mar 27 '18 at 10:10
  • Could you explain why you use \gdef here? In my primitive test samples, your code also works if I use \def. – John Dorian Mar 27 '18 at 10:11
  • @JohnDorian: I was unsure whether there is a grouping involved during option processing, so I used \gdef (\global\def) for 'safety' reasons. If it works with \def as well, the better – user31729 Mar 27 '18 at 10:13
3

Add a default option to numberwithin, so that calling

\usepackage[numberwithin]{mytheorems}

or

\usepackage[numberwithin=section]{mytheorems}

will be equivalent as well as \usepackage{mytheorems}, because of \ExecuteOptionsX{numberwithin}. Then delay the association of the counter after processing the options.

\ProvidesPackage{mytheorems}
\RequirePackage{xkeyval}
\RequirePackage{amsmath}
\RequirePackage{amsthm}

\DeclareOptionX{numberwithin}[section]{%
  \def\mthm@numberwithin{#1}%
}
\DeclareOptionX{nonumberwithin}{%
  \def\mthm@numberwithin{}%
}
\ExecuteOptionsX{numberwithin}
\ProcessOptionsX

\theoremstyle{plain}
\newtheorem{theorem}{Theorem}

\ifx\mthm@numberwithin\@empty\else
  \numberwithin{theorem}{\mthm@numberwithin}
\fi

\newtheorem{lemma}[theorem]{Lemma}

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.