5

I created a class file named class.cls as follows:

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{class}
\LoadClass{report}

\RequirePackage{indentfirst}

\DeclareOption{withinchap}{% \newcounter{exercounter}[chapter]% \setcounter{exercounter}{0}}

\DeclareOption{withinsec}{% \newcounter{exercounter}[section]% \setcounter{exercounter}{0}}

\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}} \ExecuteOptions{withinchap} \ProcessOptions\relax

\newenvironment{exercise}% {\stepcounter{exercounter}\par\textbf{\theexercounter.}}% {\ignorespacesafterend}

What I want to achieve is to settle a pair of class options withinchap(default) and withinsec. If using withinchap(default) option, the exercise counter exercounter is reset to zero when a new chapter starts. If using withinsec option, the exercise counter exercounter is reset to zero when a new section starts. But when I use withinsec option in the test.tex file as follows:

\documentclass[withinsec]{class}
\usepackage{showframe}
\begin{document}

\chapter{AAAAA} \section{aaaaa}

\begin{exercise} This is an exercise. \end{exercise}

\begin{exercise} This is another exercise. \end{exercise}

\begin{exercise} This is the third exercise. \end{exercise}

\section{bbbbb}

\begin{exercise} This is the fourth exercise in chapter one. \end{exercise}

\begin{exercise} This is the fifth exerecise in chapter one. \end{exercise}

\end{document}

After running pdflatex test in windows terminal, I got an error message

! LaTeX Error: Command \c@exercounter already defined.
               Or name \end... illegal, see p.192 of the manual.

See the LaTeX manual or LaTeX Companion for explanation. Type H <return> for immediate help. ...

l.18 \ProcessOptions\relax

? ! Emergency stop. ...

l.18 \ProcessOptions\relax

! ==> Fatal error occurred, no output PDF file produced! Transcript written on test.log.

Type H <return> for immediate help. ...

l.18 \ProcessOptions\relax

?

I want to know the reason of the error.

Stephen
  • 3,826
  • 1
    By the time the non-default option, i.e., withinsec, gets processed, the default option, i.e., withinchap, has already been processed, and the counter named exercounter has been set up. That is why \newcounter{exercounter}[section] generates an error message. What you need, then, is \renewcounter{exercounter}[section]. That, or go with @egreg's answer and use the \counterwithin approach. – Mico Jan 30 '22 at 10:00

1 Answers1

5

You are doing \newcounter{exercounter} multiple times. You can use \counterwithin instead.

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{class}
\LoadClass{report}

\RequirePackage{indentfirst}

\newcounter{exercounter}

\DeclareOption{withinchap}{\counterwithin{exercounter}{chapter}} \DeclareOption{withinsec}{\counterwithin{exercounter}{section}} %\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}}

\ExecuteOptions{withinchap}

\ProcessOptions\relax

\newenvironment{exercise}% {\stepcounter{exercounter}\par\textbf{\theexercounter.}}% {\ignorespacesafterend}

Output with the withinchap option

enter image description here

Output with the withinsec option

enter image description here

Note that the commented line in the class code does nothing, because the class report has already been loaded.

In order to pass options to it, you need to delay the code.

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{class}

\newcounter{exercounter}

\DeclareOption{withinchap}{\def\exercounter@within{chapter}} \DeclareOption{withinsec}{\def\exercounter@within{section}} \DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}}

\ExecuteOptions{withinchap} \ProcessOptions\relax

\LoadClass{report} % should go after processing options

\RequirePackage{indentfirst}

\newcounter{exercounter} \counterwithin{exercounter}{\exercounter@within}

\newenvironment{exercise}% {\stepcounter{exercounter}\par\textbf{\theexercounter.}}% {\ignorespacesafterend}

If you just want the exercise number, use \counterwithin*.

egreg
  • 1,121,712