如果尚未定义宏,我想定义一个宏。我可以按照下面的示例内联执行此操作。但我希望有一个宏可以帮我实现此功能。我尝试让它工作DefineMacroIfUndefined
,但不确定如何调整它以使其工作。
我已经注释掉了对它的调用,DefineMacroIfUndefined
因为否则无法编译。
\documentclass{article}
\newcommand{\CheckIfCommandDefined}{
\ifdefined\MyNewCommand
MyNewCommand is defined.\par%
\else
MyNewCommand is not defined.\par%
\fi
}
% Define macro to the given value if not already defined
\newcommand{\DefineMacroIfUndefined}[2]{
% #1 is name of macro
% #2 is value to be assigned if this macros is not already defined.
\ifdefined\csname#1\endcsname
% Do nothing since it is already defined
\else
\newcommand{\csname#1\endcsname}{#2}
\fi
}
\begin{document}
% This works great.
\ifdefined\MyNewCommand
% Do nothing since it is already defined
\else
\newcommand{\MyNewCommand}{true}
\fi
\CheckIfCommandDefined
\let\MyNewCommand\undefined % Undefine \MyNewCommand
\CheckIfCommandDefined
% But want to be able to do the above thru a macro
%\DefineMacroIfUndefined{MyNewCommand}{true}
\CheckIfCommandDefined
\end{document}
答案1
您可以简单地使用\providecommand
而不是\newcommand
。它具有相同的语法,但仅在尚未定义时才定义宏。
如果您想手动执行此操作,则需要\expandafter
在之前使用\newcommand
以确保\csname ...\endcsname
在它之前展开。在这种情况下,{ }
应该简单地删除。
% Define macro to the given value if not already defined
\newcommand{\DefineMacroIfUndefined}[3][0]{%
% #1 is the optional argument
% #2 is name of macro
% #3 is value to be assigned if this macros is not already defined.
\ifcsname#2\endcsname
% Do nothing since it is already defined
\else
\expandafter\newcommand\csname#2\endcsname[#1]{#3}%
%or: \expandafter\newcommand\expandafter{\csname#2\endcsname}[#1]{#3}%
\fi
}
答案2
以下是我使用的一整套宏。它具有完整的错误检查功能,并将所有内容写入日志文件!!!如果您尝试覆盖现有命令,它将因错误而停止。
它给你三个命令\TestedNameLet
,\TestedNameDef
并且\TestedNameRobustDef
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatletter
% You will probably put this inside a package
\newcommand*\my@pkgname{mypackage}
\def\my@ifundefined#1{%-- Better than standard latex (eTex has better tests than this)
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname#1\endcsname\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\long\def\my@ifnamedefinable #1{%-- Test and write info to log
\edef\reserved@a{#1}%
\my@ifundefined\reserved@a
{\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%
\ifx \reserved@b\@qend \my@notdefinable\else
\ifx \reserved@a\@qrelax \my@notdefinable\else
\PackageInfo{\my@pkgname}{\@backslashchar\reserved@a\space created}%
\fi
\fi}%
\my@notdefinable}
\gdef\my@notdefinable{%-- Error message
\PackageError{\my@pkgname}{%
Command \@backslashchar\reserved@a\space
already defined.\MessageBreak
Or name \@backslashchar\@qend... illegal.%
}{%
If \@backslashchar\reserved@a\space is not important\MessageBreak
then \protect\let\@backslashchar\reserved@a%
=\protect\relax,\MessageBreak
else use a different \@backslashchar name.}}
%%% Base level commands %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand*{\my@namelet}[1]{\expandafter\let\csname #1\endcsname}
\newcommand*{\my@nameuse}[1]{\csname #1\endcsname}
\newcommand*{\my@namedef}[1]{\expandafter\def\csname #1\endcsname}
\newcommand*{\my@robustnamedef}[1]{%
\expandafter\edef\csname #1\endcsname{%
\noexpand\protect\my@nameuse{#1 }}%
\my@namedef{#1 }}
%%% These are the commands to use %%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand*{\TestedNameLet}[1]{%
\my@ifnamedefinable{#1}\my@namelet{#1}}
\newcommand*{\TestedNameDef}[1]{%
\my@ifnamedefinable{#1}\my@namedef{#1}}
\newcommand*{\TestedNameRobustDef}[1]{%
\my@ifnamedefinable{#1}\my@robustnamedef{#1}}
\makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
使用示例如下:
\newcommand\CreateRef[2]{%
\TestedNameDef{#1Ref}##1{#2\ref{##1}}}
这可用于动态创建你自己的参考命令
\CreateRef{Fig}{Figure~}
这将创建一个命令\FigRef{lab} -> Figure~\ref{lab}