# \global\renewcommand equivalent of \global\def

The following MWE works just fine, but I had to resort to using \global\def (not that there's anything wrong with it). The intent of the MWE is to provide access to the value of macro as set in an external file, but don't want it to effect the current values that have been set in the parent file via the same macro.

I would like to know how to replace the

\global\def\ExternalPropertyAValue{#1}


with something more LaTeXish as in:

\global\renewcomand{\ExternalPropertyAValue}{#1}


which compiles, but does not yield the proper result. Only need to look at last line in output which should be:

## Code:

\documentclass{article}
\usepackage{parskip}% formatting only (no issues here)

\usepackage{filecontents}
\begin{filecontents*}{foo.tex}
\SetPropertyAValue{FoobarA}
\end{filecontents*}

\newbox{\MyBox}

\newcommand{\GetPropertyAValue}{No Value}%
\newcommand{\ExternalPropertyAValue}{No Value}%


\begin{document}
\section{This works just fine}
\verb|\GetPropertyAValue|=\GetPropertyAValue

\SetPropertyAValue{BarA}
\verb|\GetPropertyAValue|=\GetPropertyAValue

\section{How get the setting PropertyA but not effect PropertyAValue }
\verb|\GetPropertyAValue|=\GetPropertyAValue (should be \verb|BarA|)\par
\verb|\ExternalPropertyAValue|=\ExternalPropertyAValue (should be \verb|No Value|)\par

\global\sbox{\MyBox}{%
\renewcommand{\SetPropertyAValue}[1]{\global\def\ExternalPropertyAValue{#1}}
% How do I replace the above line with something like:
%\renewcommand{\SetPropertyAValue}[1]{\global\renewcomand{\ExternalPropertyAValue}{#1}}
\input{foo.tex}%
}
\verb|\GetPropertyAValue|=\GetPropertyAValue (should be \verb|BarA|)\par
\verb|\ExternalPropertyAValue|=\ExternalPropertyAValue (should be \verb|FoobarA|)\par
\end{document}

-
LaTeX2e does not provide a full set of 'programming' tools: there is no global version of \newcommand. That's why programming LaTeX2e requires quite a bit of TeX, and why the LaTeX3 work has focussed on a programming layer. – Joseph Wright Apr 13 '12 at 6:21

## Simple version

Just hook on the (complicated) definition of \renewcommand:

\makeatletter
\def\gnewcommand{\g@star@or@long\new@command}
\def\grenewcommand{\g@star@or@long\renew@command}
\def\g@star@or@long#1{%
\@ifstar{\let\l@ngrel@x\global#1}{\def\l@ngrel@x{\long\global}#1}}
\makeatother



CAUTION: As David comments, this won't work with commands defined with optional arguments: so \grenewcommand{\foo}[1][bar]{#1} will not work.

## Full version

Here's a version that should work fully

\usepackage{etoolbox}
\makeatletter
\def\gnewcommand{\g@star@or@long\gnew@command}
\def\grenewcommand{\g@star@or@long\grenew@command}
\def\g@star@or@long#1{%
\@ifstar{\let\l@ngrel@x\global#1}{\def\l@ngrel@x{\long\global}#1}}
\def\gnew@command#1{\@testopt{\@gnewcommand#1}0}
\def\@gnewcommand#1[#2]{%
\kernel@ifnextchar [{\@gxargdef#1[#2]}%
{\@argdef#1[#2]}}
\let\@gxargdef\@xargdef
\patchcmd{\@gxargdef}{\def}{\gdef}{}{}
\let\grenew@command\renew@command
\patchcmd{\grenew@command}{\new@command}{\gnew@command}{}{}
\makeatother

-
I don't think that works for optional argument forms though, as you need to make both two commands global in that case and only the internal command gets made long with the star or long code. – David Carlisle Apr 13 '12 at 9:36
@DavidCarlisle You're right; I've added a corrected version. – egreg Apr 13 '12 at 9:59

It's a bit tricky as for optional argument forms you need to make sure that both the top level command (that just applies protection and checks for [) needs to be global and the internal command. this seems to work:

\documentclass{article}

\makeatletter
\def\reset@l@texglobal{\let\l@texglobal\relax}
\reset@l@texglobal
\def\latexglobal{\let\l@texglobal\global}
\long \def \@yargd@f#1#2{%
\def \reserved@a ##1#1##2##{%
\expandafter\def\expandafter#2\reserved@b ##1#1%
}%
\afterassignment\reset@l@texglobal
\l@texglobal\l@ngrel@x \reserved@a 0##1##2##3##4##5##6##7##8##9###1%
}

\long\def\@xargdef#1[#2][#3]#4{%
\@ifdefinable#1{%
\l@texglobal\expandafter\def\expandafter#1\expandafter{%
\expandafter
\@protected@testopt
\expandafter
#1%
\csname\string#1\endcsname
{#3}}%
\expandafter\@yargdef
\csname\string#1\endcsname
\tw@
{#2}%
{#4}}}

\makeatother

\begin{document}

\newcommand\abc{abc}

\begin{center}

\latexglobal
\newcommand\hohum[3][\textbf{hello}]{[#1][#2][#3]}

\hohum{one}{two}

\hohum[aaa]{three}{four}

\latexglobal\renewcommand\abc{xyz}

\abc

\renewcommand\abc{rst}

\abc

\end{center}

\hohum{one}{two}

\hohum[aaa]{three}{four}

\abc

\end{document}

-

\renewcommand\SetPropertyAValue[1]{...}

This may have adverse effects on the "save stack" usage: with \def\x{a}{\def\x{b}\global\let\x\x} and \tracingrestores=1 the log file shows {retaining \x=macro:->b} so some space is the save stack is wasted. – egreg Apr 13 '12 at 9:21
I can't quite get this to work. Can you try to delete the \renewcommand and replace the commented line in the MWE with this and see if you can get the last line to be as shown in the question. Sorry about my code not being clear: I want to know what is defined in the external file for one particular macro and ignore everything else in the file. – Peter Grill Apr 13 '12 at 15:29