使用\@ifdefined
(在 LaTeX 中),我们可以检查命令是否已定义。
使用\meaning
,我们可以得到命令的定义。
我们还可以获取有关在哪里定义了命令吗?例如,根据源文件和行号?TeX 会跟踪这些信息吗?
我们可以grep
通过源文件,但是对于像这样的构造\csname
,不能保证定义会出现。
答案1
哦,我找到了一个更好的方法来做到这一点,也借助了filehook
(代码有点棘手):
\documentclass{article}
\usepackage{filehook,currfile}
\newwrite\finder
\immediate\openout\finder=\jobname.fnd
\def\searchmacro#1{
\AtBeginOfFiles{%
\ifdefined#1
\expandafter\def\csname \currfilename:found\endcsname{}%
\fi}
\AtEndOfFiles{%
\ifdefined#1
\unless\ifcsname \currfilename:found\endcsname
\immediate\write\finder{found in '\currfilename'}%
\fi\fi}}
\searchmacro\url
\usepackage{hyperref}
\begin{document}
dummy
\end{document}
编译后,我们将得到
found in 'url.sty'
found in 'hyperref.sty'
在 中\jobname.fnd
。也就是说,\url
定义在 中url.sty
,由 来输入hyperref.sty
。
答案2
Leo 的回答filehook
让currfile
我想到将这些技术纳入 v1.2 中latexdef
工具(Perl 脚本)。它将报告定义给定宏的第一个包。
例子:
显示加载“booktabs”和“graphicx”包后 \relax、\toprule 和 \includegraphics 的定义和位置:
# latexdef -p booktabs -p graphicx -f relax toprule includegraphics
\relax is defined by (La)TeX.
\relax:
\relax
\toprule first defined in "booktabs.sty".
\toprule:
macro:->\noalign {\ifnum 0=`}\fi \@aboverulesep =\abovetopsep \global \@belowrulesep =\belowrulesep \global \@thisruleclass =\@ne \@ifnextchar [{\@BTrule }{\@BTrule [\heavyrulewidth ]}
\includegraphics first defined in "graphics.sty".
\includegraphics:
macro:->\@ifstar {\Gin@cliptrue \Gin@i }{\Gin@clipfalse \Gin@i }
答案3
那么如何使用trace
包并在日志文件中查找宏呢?filehook
包可以帮助我们在日志文件中添加文件名标签。例如:
\usepackage[logonly]{trace}
\usepackage{filehook}
\AtBeginOfFiles{\wlog{INFILE:<#1>}}
\AtEndOfFiles{\wlog{OUTFILE:<#1>}}
\traceon
\usepackage{amsmath}
\traceoff
然后我们可以发现\subarray
在中定义amsmath.sty
。由于
{into \subarray=\long macro:#1->\vcenter \bgroup \Let@ \restore@math@cr \ETC.}
出现在 之后INFILE:<amsmath.sty>
,但不出现在 之后OUTFILE:<amsmath.sty>
。这需要一些手动工作,我使用 vim 来搜索模式。
警告:这可能会产生极其巨大的日志文件。大多数时候,我认为简单的二分法就可以解决这个问题。
答案4
全部基本 LaTeX 命令在属于基本目录的文件(位于 )中定义$TEXMF/tex/latex/base
。如果命令未在此处找到,则该命令是所谓的 TeX 原语或在附加加载包之一中定义。主要基本文件是latex.ltx
和fontmath.ltx