与本网站上的大多数问题不同,我的问题是我的代码编译时没有错误,但我不希望这样。
我希望能够检查是否\command
已定义,如果已定义则执行某些操作,如果未定义则不执行任何操作。如果未定义则不想\command
设置\relax
。如果未定义则我不希望代码产生任何效果。
这是一个例子。在这种情况下,很容易解决这个问题,所以这只是为了说明目的。也就是说,这个特定案例本身并不是一个问题——它只是一个用来说明问题的简单例子。
\documentclass{article}
\makeatletter
\@ifundefined{chapter}{}{\renewcommand\chapter[1]{turtles}}
\makeatother
\usepackage{kantlipsum}
\begin{document}
\chapter{a}
\kant[1-10]
\end{document}
正如我所提到的,在这种特殊情况下,有一个简单的解决方法:我可以检查是否\@chapter
已定义,并使用其定义作为的代理\chapter
。
但是有没有办法检查是否\chapter
已定义,而无需将其设置为\relax
未定义或仅使用代理间接检查?
编辑
这是讨论中提到的第三个案例哪里\ifdefined...\fi
会出现问题,但该\ifdef{}{}{}
方法可以很好地替代\@ifundefined{}{}{}
原始方法。由提供要求。
\documentclass{article}
\makeatletter
% \usepackage{etoolbox}% for \ifdef method
% \ifdef{\chapter}{% Werner's comment on Alan Munn's answer - this method works well
\@ifundefined{chapter}{}{% original - works but \chapter no longer gives an error as it is set to \relax
% \ifdefined\chapter%ref.: Alan Munn's answer at https://tex.stackexchange.com/a/268467/ - unfortunately does not work here (at least, not with the knowledge I have to implement it)
\renewcommand\chapter{%
\if@openright
\cleardoublepage
\else
\clearpage
\fi
\thispagestyle{plain}%
\global\@topnum\z@
\@afterindentfalse
\secdef\@chapter\@schapter}% end \renewcommand\chapter
\def\@chapter[#1]#2{%
\ifnum \c@secnumdepth >\m@ne
\if@mainmatter
\refstepcounter{chapter}%
\typeout{\@chapapp\space\thechapter.}%
\addcontentsline{toc}{chapter}%
{\protect\numberline{\thechapter}#1}%
\else
\addcontentsline{toc}{chapter}{#1}%
\fi
\else
\addcontentsline{toc}{chapter}{#1}%
\fi
\chaptermark{#1}%
\addtocontents{lof}{\protect\addvspace{10\p@}}%
\addtocontents{lot}{\protect\addvspace{10\p@}}%
\if@twocolumn
\@topnewpage[\@makechapterhead{#2}]%
\else
\@makechapterhead{#2}%
\@afterheading
\fi}% end definition of \@chapter
\def\@makechapterhead#1{%
\vspace*{50\p@}%
{%
\parindent \z@ \raggedright \normalfont
\ifnum \c@secnumdepth >\m@ne
\if@mainmatter
\fontsize{\@xivpt}{14}\mdseries\centering\scshape{\@chapapp\space \thechapter}%
\par\nobreak
\vskip 20\p@
\fi
\fi
\interlinepenalty\@M
\fontsize{\@xivpt}{18}\bldsc\centering #1\par\nobreak
\vskip 40\p@
}%
}% end definition \@makechapterhead
\def\@schapter#1{%
\if@twocolumn
\@topnewpage[\@makeschapterhead{#1}]%
\else
\@makeschapterhead{#1}%
\@afterheading
\fi}% end definition \@schapter
\def\@makeschapterhead#1{%
\vspace*{50\p@}%
{%
\parindent \z@ \raggedright
\normalfont
\interlinepenalty\@M
\fontsize{\@xivpt}{18}\bldsc\centering #1\par\nobreak
\vskip 40\p@
}%
}% end definition \@makeschapterhead
}% end of stuff to do only if \chapter is defined - \@ifundefined method
% }{}% \ifdef method
% \fi% \ifdefined method
\makeatother
\begin{document}
\chapter{a}
\end{document}
答案1
最简单的方法是使用 e-TeX\ifdefined
宏:
\documentclass{article}
\ifdefined\chapter\renewcommand\chapter[1]{turtles}\fi
\usepackage{kantlipsum}
\begin{document}
\chapter{a}
\kant[1-10]
\end{document}
如果其中有其他条件,则此方法将不起作用(因此是更大问题的根源),在这种情况下,etoolbox
最好使用 Werner 的解决方案:
\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\ifdef{\chapter}{
\renewcommand{\chapter}[1]{%
\if@openright
\cleardoublepage
\else
\clearpage
\fi
turtles}
}{}
\makeatother
\usepackage{kantlipsum}
\begin{document}
\chapter{a}
\kant[1-10]
\end{document}
答案2
当然,你会失去可扩展性,但这是“简单”的方法:
\documentclass
%{book}
{article}
\makeatletter
\begingroup
\@ifundefined{chapter}{\endgroup}{\endgroup\renewcommand\chapter[1]{turtles}}
\makeatother
\usepackage{kantlipsum}
\begin{document}
\chapter{a}
\kant[1-10]
\end{document}
如果命令已经出现在的范围内,则带有\ifdef
from 的方法可能会给出错误的结果,因此它与 等同。etoolbox
\@ifundefined
\relax
可扩展测试应该以\ifdefined
和为分支,在本例中,查看命令是否等同于\relax
。
\makeatletter
\newcommand{\x@ifundefined}[3]{%
\ifcsname #1\endcsname
%either defined or \relax
\expandafter\@firstoftwo
\else
%undefined
\expandafter\@secondoftwo
\fi
{\x@ifrelax{#1}{#2}{#3}}{#2}%
}
\newcommand{\x@ifrelax}[3]{%
\expandafter\ifx\csname #1\endcsname\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#2}{#3}%
}
\makeatletter
测试表明我们没问题:
\makeatletter
\edef\foo{\x@ifundefined{bbcccddd}{undef}{def}}\show\foo
\edef\foo{\x@ifundefined{relax}{undef}{def}}\show\foo
\edef\foo{\x@ifundefined{mbox}{undef}{def}}\show\foo
\show\bbcccddd
\makeatother
将输出
> \foo=macro:
->undef.
l.26 ...fundefined{bbcccddd}{undef}{def}}\show\foo
?
> \foo=macro:
->undef.
l.27 ...x@ifundefined{relax}{undef}{def}}\show\foo
?
> \foo=macro:
->def.
l.28 ...\x@ifundefined{mbox}{undef}{def}}\show\foo
?
> \bbcccddd=undefined.
l.29 \show\bbcccddd