以下 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
工作?