我有一些大文件,我正在输入包含我所有文本的开头\newcommands
。它们相当多。其中大多数都不会在给定的文档中使用。但是哪些会被使用呢?
是否可以向辅助文件中写入一些内容,说明是否\newcommand
在文本中使用了定义的内容。
尽管不是很有用,但我还是添加了一个 MWE
\documentclass[12pt]{article}
\newcommand{\titi}{Hemixos castanonotus}
\newcommand{\eag}{Haliaeetus leucocephalus}
\begin{document}
I my travels, I have seen many birds of type \titi.
\end{document}
然后,辅助文件应列出已定义的命令
Defined commands
\titi
\eag
Used commands
\titi
Unused commands
\eag
我知道包定义了很多\newcommands
。但我只对用户定义的感兴趣\newcommands
。
答案1
\documentclass[12pt]{article}
\usepackage{etoolbox}
\makeatletter
% This macro will contain all the tracked commands:
\def\@mycommands{}
% These macros enable and disable tracking the commands:
\def\starttrackingnewcommands{%
\let\old@@newcommand\@newcommand
\def\@newcommand##1{%
\expandafter\def\expandafter\@mycommands\expandafter{\@mycommands\oneof@mycommands##1}%
\old@@newcommand##1%
}%
}
\def\stoptrackingnewcommands{%
\let\@newcommand\old@@newcommand
}
% These macros are used to write to the log file:
\def\mycommand@used#1{\typeout{My command `\string #1' was used.}}
\def\mycommand@unused#1{%
\GenericWarning{(mycommands)}{LaTeX Warning:
My command `\string #1' was not used!%
}%
}
% These macros mark a command as used or unused:
\def\mycommand@markunused#1{%
\expandafter\gdef\csname mycommand@status@\expandafter\@gobble\string #1\endcsname{\mycommand@unused #1}%
\pretocmd #1{\mycommand@markused #1}{}{\GenericWarning{(mycommands)}{Could not patch `\string #1' as unused!}}%
\aftergroup\mycommand@markunused\aftergroup #1%
}
\def\mycommand@markused#1{%
\expandafter\gdef\csname mycommand@status@\expandafter\@gobble\string #1\endcsname{\mycommand@used #1}%
\patchcmd #1{\mycommand@markused #1}{}{}{\GenericWarning{(mycommands)}{Could not patch `\string #1' as used!}}%
\aftergroup\mycommand@markused\aftergroup #1%
}
% This macro calls the appropriate logging macro for a command:
\def\mycommand@evaluateuse#1{%
\csname mycommand@status@\expandafter\@gobble\string#1\endcsname
}
% Mark all commands as unused at \begin{document}:
\AtBeginDocument{%
\let\oneof@mycommands\mycommand@markunused
\@mycommands
}
% Evaluate the use of the commands at \end{document}:
\AtEndDocument{%
\let\oneof@mycommands\mycommand@evaluateuse
{\let\mycommand@unused\@gobble% first, only the used commands
\@mycommands
}{\let\mycommand@used\@gobble% then, only the unused commands
\@mycommands
}%
}
\makeatother
\starttrackingnewcommands
\newcommand{\foo}{foo}
\newcommand{\baz}{bar}
\newcommand{\titi}{Hemixos castanonotus}
\newcommand{\eag}{Haliaeetus leucocephalus}
\stoptrackingnewcommands
\begin{document}
I my travels, I have seen many birds of type \titi.
\end{document}
在日志文件的末尾你会发现
My command `\titi' was used.
LaTeX Warning: My command `\foo' was not used! on input line 68.
LaTeX Warning: My command `\baz' was not used! on input line 68.
LaTeX Warning: My command `\eag' was not used! on input line 68.
一些注释
如果您的某个命令第一次在如下上下文中使用,则可能会破坏某些功能:
\def\somethingwithargument#1{expansion}
\expandafter\somethingwithargument\oneofyourcommands
也就是说,如果某个命令 ( \somethingwithargument
) 占用了某个命令扩展的开头,则在该命令开头插入某些内容以跟踪其使用情况这一事实将破坏此代码。不过,我不知道还有什么更安全的方法可以做到这一点。
我选择将未使用命令的消息格式化为警告,将使用命令的消息格式化为警告。当然,您可以选择不同的方式(或者如果您愿意,甚至可以写入完全不同的文件)。
由于这是一个相当侵入的过程(临时修改所有命令),因此可能会产生我现在无法想到的副作用。如果您发现任何副作用,请随时在此处添加。
无论如何,你应该不是将其用作序言的永久补充,仅作为快速了解您所使用的命令的一种技术。
答案2
这是显示已使用命令的方法,对于未使用的命令,我没有找到解决方案。搜索并替换命令,添加 \display,即用 \display\titi 替换 \titi
\documentclass[12pt]{article}
\newcount\commandnum
\commandnum=0
\newwrite\displayed
\immediate\openout\displayed=\jobname.dis
\def\displayedcommands#1{\vfill \section{#1} \vskip\baselineskip \immediate\closeout\displayed \input\jobname.dis}
\def\display#1{\advance\commandnum by 1 #1\textsuperscript{(\the\commandnum)\ }\immediate\write\displayed{\noindent #1 P.\thepage\ called by (\the\commandnum)\ \noexpand\string\noexpand#1'' \vskip0.2\baselineskip}}
\newcommand{\titi}{``Hemixos castanonotus''}
\newcommand{\eag}{``Haliaeetus leucocephalus''}
\begin{document}
\section{Test}
In my travels, I have seen many birds of type \display\titi
In my travels, I have seen many birds of type \display\eag
In my travels, I have seen many birds of type \display\eag
\displayedcommands{Used Commands}
\end{document}
答案3
我脑海中浮现的另一个选择取决于您问题的诊断目的... 可能感兴趣的不仅仅是知道使用了哪些命令,而且知道这些命令的使用频率。为此,请考虑以下内容:
\documentclass[12pt]{article}
\usepackage{etoolbox}
\newcommand{\displayTracked}{}
\makeatletter
\newcommand{\trackedCommand}[2]{% This will define a tracked command.
% Define the command as it was original intended.
\expandafter\newcommand\csname#1\endcsname{#2 \refstepcounter{#1Count}}
% Define a counter to track that specific command.
\newcounter{#1Count}
\setcounter{#1Count}{0}% Initialize it to zero as the command hasn't been used yet.
% Update the display command to include the new command counter.
\csappto{displayTracked}{The command #1 has been used \arabic{#1Count} times \\}
}
\makeatother
\trackedCommand{titi}{Hemixos castanonotus}
\trackedCommand{eag}{Haliaeetus leucocephalus}
\trackedCommand{anothercommand}{This command won't be used at all, but still tracked.}
\begin{document}
I my travels, I have seen many birds of type \titi. What about \titi or \eag or just \titi ?
\displayTracked
\end{document}
比我更擅长 LaTeX 的人可能能够让命令trackedCommand
接受 csname 而不是文本名称(即允许您\newcommand
使用\titi
而不是来定义与语法相同的命令titi
),但我无法在我愿意为此努力的时间范围内找到一个好的解决方案。值得注意的是,该\trackedCommand
命令将接受非标准命令名称(例如带有空格或阿拉伯数字的命令名称);此外,您可以决定是否要单独跟踪每个命令,而不是始终跟踪每个命令(以防您已经知道某些命令使用频繁或很少使用,并且不需要显示统计信息)。
此外,这\displayTracked
是为您提供输出的内容,因此只需注释掉(或不包括)该命令即可让您仅在需要时获取跟踪信息。您还可以使用该命令并将其通过管道传输到辅助文件或乳胶警告或您可能需要的其他任何内容。