Exam class: best way to redefine \question command to apply custom formatting

EDIT: In summary the answer really turned out elegant and sipmle. Thanks to all the answers below!

\usepackage{etoolbox}
%...
\renewcommand\questionshook{\preto{\question}{\large\bfseries}}

% If we don't want the question's parts to be huge as well!
%\renewcommand\partshook{\normalsize\normalfont}


Shortly, I want to generate a custom exam sheet document class based on the exam class to use in a group of colleagues. For the purpose, I want to redefine the default \question command to apply some custom formatting.

Suppose I want to make the default \question section large and bold. What I'm now doing is the following:

\newcommand\lquestion{\large\bfseries\question}


So, in order to use my custom formatting, I have to write the following in my documents instead:

\begin{lquestion}
A large and bold question: what is the mass of the sun?
\end{lquestion}


(I've read that using commands as environments is okay in LaTeX, but correct me if that hides some underwater stones.)

What would be the best way to redefine the question command, which comes from exam.cls, as an environment so that I don't have to prepend that bonus l at the beginning of the environment and can use the default contained name question instead?

EDIT: A minimal working example:

\documentclass{exam}
\usepackage[utf8]{inputenc}

\title{MWE}
\author{John Doe}
\date{November 2020}

%print solutions by default (for MWE's sake)
% do not put a box/frame around printed solutions
\unframedsolutions

\begin{document}

\maketitle

\begin{questions}
%this is basically what I want the result to look like:
{\large\bfseries
\question My large and bold question:
\begin{parts}
\part First part
\part Second part
\end{parts}
}
%but instead of this rather inconvenient form, I want to define an environment {question} with the same effect and use it like:
%
% \begin{question}
% My large and bold question:
% \begin{parts}
%     \part First part
%     \part Second part
% \end{parts}
% \end{question}

\begin{solution}
My general solution prerequisite.
\begin{parts}
\part My first part solution
\part My second part solution
\end{parts}
\end{solution}
\end{questions}

\end{document}



The \question's definition can be found on line 2845 in exam.cls inside the questions environment:


\newenvironment{questions}{%
%.... lots of code here
\def\question{%
\@bonusfalse
\def\thequestiontitle{\csname p@question\endcsname
\csname thequestion\endcsname}%
\process@question
}%
%.... lots of other code here
%and waaaaay down on line 3143
}% End of the second argument of \newenvironment{questions}


• You can simply use {\large\bfseries \question My large and bold question:}. It has no effect on the rest of the code. \question is implemented as an \item in a list, not an environment or macro with an argument. – John Kormylo Nov 12 '20 at 17:43
• @JohnKormylo That's exactly what I was initially doing, but I wanted to shorten it and make this behaviour default, whilst also using question as an environment for a somewhat more obvious encapsulation of sections. Are there any downsides to what I've gone with as stated in my last edit? – D. Petrov Nov 12 '20 at 18:46
• The real question is what is it that needs to NOT be \large\bfseries? – John Kormylo Nov 12 '20 at 20:53
• @JohnKormylo Well, initially I wanted the parts to also be formatted, then I saw your suggestion and thought that sometimes that'd be ugly, but now I can even smoothly choose between turning that on and off. So, I'm happy with the result. – D. Petrov Nov 12 '20 at 21:46

It seems you've already found that you can use a command as an environment, so your question is really "how can I redefine the question command so that it has \large\bfseries at the beginning". The problem that you've uncovered is that the questions environment defines the \question command. In which case, I think your example works with

\usepackage{etoolbox}
\appto{\questions}{%
\preto{\question}{\large\bfseries}%
}


I'm not happy with needing to have \printanswers in there, but the solutions disappear otherwise. So you may be stuck needing to keep track of two different \printanswers commands.

As to the environment question: \begin{myenv}...\end{myenv} becomes \begingroup\myenv ...\endmyenv\endgroup, (where \endmyenv won't cause an error if it doesn't exist). The upshot is that you automatically group your \large\bfseries so that it doesn't alter the rest of your document.

• Thank you for the additional info! As I found out, \question is not actually a \newcommand from within the package, but rather a \def\question and so on... So with this code I get LaTeX Error: Command \question undefined. – D. Petrov Nov 11 '20 at 21:37
• It's not that it's def or newcommand. The problem is that \question doesn't exist outside of the questions environment. – Teepeemm Nov 11 '20 at 22:07
• @D.Petrov I've updated my attempt. I don't suppose you could edit an example into your original post that we could work with? – Teepeemm Nov 11 '20 at 22:15
• I'm sorry I didn't think of that! An example has been included for better understanding and playing around. P.S. Your proposal failed with weird errors, but I'll leave the practical testing to you to see for yourself. – D. Petrov Nov 11 '20 at 22:39
• Glad you were able to figure it out. Unfortunately, I'm not able to enlighten you about why it ended up working the way it did. – Teepeemm Nov 12 '20 at 1:37

Actually, one can use \questionshook, \partshook and \SolutionEmphasis to handle formatting changes.

\documentclass{exam}
\usepackage[utf8]{inputenc}

\title{MWE}
\author{John Doe}
\date{November 2020}

%print solutions by default (for MWE's sake)
% do not put a box/frame around printed solutions
\unframedsolutions

\renewcommand\questionshook{\large\bfseries}
\renewcommand\partshook{\normalsize\normalfont}
\SolutionEmphasis{\normalsize\normalfont}

\begin{document}

\maketitle

\begin{questions}
\question %\begingroup ... \endgroup not needed
My large and bold question:
\begin{parts}
\part First part
\part Second part
\end{parts}

\begin{solution}
My general solution prerequisite.
\begin{parts}
\part My first part solution
\part My second part solution
\end{parts}
\end{solution}
\end{questions}

\end{document}

• So I took the time to read almost all of etoolbox's documentation, but didn't really think of checking for hooks in the exam documentation... Really helpful insight and elegant solution! Thank you! The only problem is that it affects my document outside the 'question' environment as well, more precisely it makes my solutions main part (before the parts initiation) also large and bold. You can see my post edited with the options for a solution. – D. Petrov Nov 12 '20 at 11:20
• It doesn't leak, it just applies to everything in the questions or parts environments. There is also a fix for solutions. – John Kormylo Nov 12 '20 at 17:12

The most basic way to create an environment is using \newenvironment{<name>}{<begin code>}{<end code>}. So in your case, this would just be \newenvironment{\lquestion}{\large\bfseries\question}{} You could add anything else that you like into the begin or end code. The begin code is what happens at \begin{lquestion} tag and the end code is what happens at the \end{lquestion} tag. There are more advanced ways to do this of course but this is the most simple method and there is no need for something more complex in this case.

• Thank you for the suggestion, but I'm familiar with that. The problem is I want my environment to be called question, but that name is already in use and the compilation throws a bunch of errors... – D. Petrov Nov 11 '20 at 21:08
• @D. Petrov My apologies. I've seen the issue that you had with the other solution as well. I believe that the other solution would likely work if you replaced \renewcommand with \def or perhaps one of the versions of that like \xdef. – Bryce Nov 11 '20 at 21:43
• I really tried to play around with that, but the problem is that the \question's management inside of exam.cls is somewhat more complex and I really can't cope with redefining it. So I guess the question narrows itself down to: can one define an environment with an already \def'd name, just like in this case? – D. Petrov Nov 11 '20 at 21:59