4

When posting snippets of latex code that define or modify commands containing @, one commonly includes the \makeatletter...\makeatother wrapper that's necessary if pasting the snippet into an ordinary document. However, such pasting then has bad effects if it happens to occur somewhere that \makeatletter is already in effect. Is there a good way to "save the state of 'at'", execute some code, and then restore the original state, whatever it might have been?

(Yes, I know that \makeatletter/\makeatother are local to groups. However, certain code doesn't work the same way inside a group, e.g. macro definitions are local to the group by default, so it would be better to avoid having to enclose the whole snippet in a group.)

  • Where are you putting these commands? Unless you are misusing them, I'd think it'd be hard to get confused as to whether you need to use them or not? (E.g., don't use them in a .sty file.) – jon Oct 21 '16 at 4:13
  • Think to \makeatletter and \makeatother as ”snippet delimiters“ – egreg Oct 21 '16 at 7:42
  • To be honest, I don't actually have a use in mind for such commands. I was just curious if it was easy to do, because it seemed to me as though it would have been better if this is what \makeatletter and \makeatother actually did. – Mike Shulman Oct 21 '16 at 8:33
5

This is what—in some situations—I do:

\begingroup
\makeatletter
\@firstofone{%
  \endgroup
  ⟨Stuff/macro-definitions whose tokenizing needs to
   take place while `@` is of category-code 11(letter)
   but whose processing/carrying-out/running/execution
   is to take place while the category-code of `@` is
   what it was before encountering \makeatletter.⟩
}%

The argument of \@firstofone will be read and tokenized within a local scope where @ is of category-code 11(letter) and where therefore @ either can be part of the name of control-word-tokens or will be tokenized as an explicit character-token of category-code 11(letter).
When processing/carrying out/running/executing those tokens that came into being due to reading and tokenizing the argument of \@firstofone takes place, the first \endgroup will terminate that local scope, resetting the category code of @ to whatever it was before calling \makeatletter.
Thus processing/carrying out/running/executing the remaining tokens of \@firstofone's argument does not take place within that local scope where the category-code of @ is changed but with the category-code-régime that was in effect before processing the \makeatletter-token.

| improve this answer | |
4

You could define a new macro to store the current catcode of @ and restore it using this macro later on:

\documentclass{article}

\def\safemakeatletter#1{%
    \edef#1{\catcode`@=\the\catcode`@\relax}%
    \makeatletter
}

\def\testat{catcode of \texttt{@} is: \the\catcode`@\relax\par}

\begin{document}

\catcode`@=10\relax
\testat
\makeatletter
\testat
\makeatother
\testat

\medskip

\catcode`@=10\relax
\testat
\safemakeatletter\safemakeatother
\testat
\safemakeatother
\testat

\end{document}

As you can see in the output, \makeatother incorrectly restores the catcode in the first part, while \safemakeatother doesn't:

enter image description here

| improve this answer | |
  • Please see Why should the minimal class be avoided?. – Peter Grill Oct 21 '16 at 4:36
  • @PeterGrill Thanks, I'll keep that in mind, though it makes no difference in this particular case, as far as I can see. – siracusa Oct 21 '16 at 4:40
  • Yeah, I just wanted to have that there so that others who see this don't think that the minimal class shoudl be used for MWEs. – Peter Grill Oct 21 '16 at 4:41

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.