\global\renewcommand 相当于 \global\def

\global\renewcommand 相当于 \global\def

以下 MWE 工作得很好,但我不得不求助于使用\global\def(并不是说它有什么问题)。MWE 的目的是提供对外部文件中设置的宏值的访问,但不希望它影响通过同一宏在父文件中设置的当前值。

我想知道如何更换

\global\def\ExternalPropertyAValue{#1}

使用更 LaTeXish 的形式,例如:

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

编译通过,但结果不正确。只需查看输出中的最后一行,它应该是:

在此处输入图片描述

代码:

\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}%

\newcommand{\SetPropertyAValue}[1]{\renewcommand{\GetPropertyAValue}{#1}}%

\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}

答案1

简易版

只需勾勒出(复杂的)定义\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

Now 的\grenewcommand语法与 相同\renewcommand,但其作用是全局的。后面的第一行\makeatother还定义了 的全局版本\newcommand

警告:正如 David 所评论的,这不适用于使用可选参数定义的命令:\grenewcommand{\foo}[1][bar]{#1}所以不是工作。


完整版

这是一个可以完全运行的版本

\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

答案2

对于可选参数形式,这有点棘手,您需要确保顶级命令(仅应用保护并检查[)都需要是全局的,并且是内部命令。这似乎有效:

在此处输入图片描述

\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}

答案3

我必须承认我没有严格遵守你的代码,但不应该

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

工作?

相关内容