Jul 04

# Changing parts of already existing commands and environments in LaTeX

In using the exam document class, I thought it would be nice to be able to include a new page at the end of every solution. The solutions I had in this particular document were long, and to separate the solutions from the next questions, I thought this would be nice. The nicest way would be to redefine the solution environment to include a \newpage at the end…but then wouldn’t I have to know the entire definition of the solution enviroment and do it exactly the same? Seems there should be a better way…and there is.

\let\oldendsolution\endsolution \def\endsolution{\oldendsolution\newpage}

Nice and short and easy. \endsolution is a command that returns what is in the end of the solution environment.  It seems that this works with any environment, that is, if you define a new environment \newenvironment{NAME}{START}{END} then \endNAME will return END.  Similarly, using the name of the environment as a command gets the beginning: \NAME will return START.

Similarly, you can define a command that uses itself. This is referred to as “patching exiting commands” in the UK List of TeX Frequently Asked Questions. It’s pretty easy for basic commands, but using the exam documentclass, lets say you wanted to add the words “THIS ONE IS HARD” to every question on an exam. Apparently (as explained in the above link) due to the fact that the question command has an optional parameter, you must do the following: first, in your preamble, type

\usepackage{letltxmacro}

Then, put this code inside your question environment:

\LetLtxMacro{\oldquestion}{\question} \renewcommand{\question}[1][]% {\oldquestion[{#1}] \textbf{THIS ONE IS HARD!}}

Here is a sample tex file showing how to do this in a more general context:

 Source code
\documentclass{article}

\usepackage[margin=1in]{geometry}

\newenvironment{test}{\begin{center}\bfseries %
}{\end{center}}

\newcommand{\mysectionbreak}[1][1in]{\vspace*{6pt}\centerline{\rule{#1}{1pt}}\vspace*{6pt}}

\parindent 0in

\usepackage{mdframed}

\begin{document}

Here is test environment number 1:

\begin{test}
This is the first test environment
\end{test}

Here is \verb"\test": \fbox{\meaning\test}

Here is \verb"\endtest": \fbox{\meaning\endtest}

\mysectionbreak

I will redefine the test environment to finish with some text.

\let\oldendtest\endtest
\def\endtest{\textit{\Large ...and this is at the end!}\oldendtest}

Here is test environment number 2:

\begin{test}
This is the second test environment
\end{test}

Here is \verb"\test": \fbox{\meaning\test} (unchanged)

Here is \verb"\endtest": \fbox{\meaning\endtest}

Here is \verb"\oldendtest": \fbox{\meaning\oldendtest}

\mysectionbreak[1cm]

Lets update the section break command...

\let\oldsectionbreak\mysectionbreak
\renewcommand{\mysectionbreak}{\oldsectionbreak[1cm] \oldsectionbreak[1in] \oldsectionbreak[1cm]}

Done. Let's do it..

\mysectionbreak

Here is \verb"\mysectionbreak": \fbox{\meaning\mysectionbreak}
Here is \verb"\oldsectionbreak": \fbox{\meaning\oldsectionbreak}
Now lets make the environment enclosed in a box and add some spacing before and after it.

\let\oldstarttest\test
\def\test{\vspace*{1in}\begin{mdframed}[backgroundcolor=yellow]\oldstarttest}
\def\endtest{\oldendtest\end{mdframed}\vspace*{1in}}

Here is test environment number 3:

\begin{test}
This is the third test environment
\end{test}

Here is \verb"\test": \fbox{\meaning\test}

Here is \verb"\endtest": \fbox{\meaning\endtest}

\end{document}

Enjoy and keep learning! -Rob