2

I think it's fairly common to redefine macros. And I'm creating two functions to help storing and restoring these redefined macros.

And so I tried using the following:

\documentclass{article}
\usepackage{letltxmacro}

\makeatletter
\newcommand{\storecommand}[1]
    {%
        \LetLtxMacro{\\env@#1}{\\#1}%
    }
\newcommand{\restorecommand}[1]
    {%
        \LetLtxMacro{\\#1}{\\env@#1}%
    }
\makeatother

% Example usage

\begin{document}
    \noindent
    \makeatletter
    Expected:\\
    \newcommand{\foo}{bar}%
    \foo\\
    \LetLtxMacro{\env@foo}{\foo}%
    \renewcommand{\foo}{baz}%
    \foo\\
    \LetLtxMacro{\foo}{\env@foo}%
    \foo\\
    \makeatother

    \noindent
    Actual:\\
    \renewcommand{\foo}{bar}%
    \foo\\
    \storecommand{foo}%
    \renewcommand{\foo}{baz}%
    \foo\\
    \restorecommand{foo}%
    \foo
\end{document}
Expected:
bar
baz
bar

Actual:
bar
nv@foo=efoobaze oo=fenv@foobaz

I hoped that it'd know when I call it to expand the #1 and then take the entire thing as the command. However it doesn't.

How can I get storecommand to work the way I want?


To prevent an XY question:

I'm trying to make an environment that reverts to the previous state when it ends. Wiping all commands that have been made.

David Carlisle
  • 757,742
Peilonrayz
  • 1,136
  • almost all definitions are local so automatically restore at the end of an environment – David Carlisle Nov 10 '19 at 22:15
  • the argument to \LetLtxMacro needs to be a command name token but you are passing \LetLtxMacro{\\foo} which is the newline command \\ followed by the text foo – David Carlisle Nov 10 '19 at 22:16
  • probably you want \expandafter\LetLtxMacro\csname env@#1\expandafter\endcsname\csname #1\endcsname but just restoring via TeX grouping would normally be easier. – David Carlisle Nov 10 '19 at 22:20

1 Answers1

2

enter image description here

\documentclass{article}
\usepackage{letltxmacro}

\makeatletter
\newcommand{\storecommand}[1]
    {%
        \expandafter\LetLtxMacro\csname env@#1\expandafter\endcsname\csname #1\endcsname
    }
\newcommand{\restorecommand}[1]
    {%
       \expandafter\LetLtxMacro\csname #1\expandafter\endcsname\csname env@#1\endcsname
    }
\makeatother

% Example usage

\begin{document}
    \noindent
    \makeatletter
    Expected:\\
    \newcommand{\foo}{bar}%
    \foo\\
    \LetLtxMacro{\env@foo}{\foo}%
    \renewcommand{\foo}{baz}%
    \foo\\
    \LetLtxMacro{\foo}{\env@foo}%
    \foo
    \makeatother

\bigskip

    \noindent
    Actual:\\
    \renewcommand{\foo}{bar}%
    \foo\\
    \storecommand{foo}%
    \renewcommand{\foo}{baz}%
    \foo\\
    \restorecommand{foo}%
    \foo


\bigskip
    \noindent
    Using a group:\\
    \renewcommand{\foo}{bar}%
    \foo\\
    \begin{empty}
    \renewcommand{\foo}{baz}%
    \foo\\
    \end{empty}
    \foo


\end{document}

If you do use \LetLtxMacro (and it isn't clear it is needed here) you need to pass a csname token to each argument, \LetLtxMacro{\\foo}{..} the first argument is the \\ command followed by the text foo, so 4 tokens not 1.

David Carlisle
  • 757,742