%%% ==================================================================== %%% @LaTeX-file{ % filename = "cmdtrack.dtx", %%% filename = "cmdtrack.sty", %%% version = "1.06", %%% date = "2012/12/18", %%% author = "Michael John Downes", %%% copyright = "Copyright 1999 Michael John Downes. %%% Copyright 2012 TeX Users Group. %%% This work may be distributed and/or modified under the %%% conditions of the LaTeX Project Public License, either version 1 %%% of this license or (at your option) any later version. %%% The latest version of this license is in %%% http://www.latex-project.org/lppl.txt %%% and version 1.3 or later is part of all distributions of LaTeX %%% version 2003/12/01 or later. %%% ", % keywords = "newcommand", % abstract = "This is a LaTeX package that aids in the task % of checking whether a command defined in a % document preamble is actually used somewhere % in the document.", %%% } %%% ==================================================================== % \iffalse %<*driver> \NeedsTeXFormat{LaTeX2e} \documentclass{amsdtx} \begin{document} \title{The \pkg{cmdtrack} package} \author{Michael Downes} \date{Version \fileversion, \filedate} \hDocInput{cmdtrack.dtx} \end{document} % % \fi % % \maketitle % \section{Introduction} % This package is released under the \LaTeX\ Project Public License. % % The \pkg{cmdtrack} package aids in the task of checking whether a % command defined in a document preamble is actually used somewhere % in the document. If you add a statement % \begin{verbatim} % \usepackage{cmdtrack} % \end{verbatim} % in the preamble of your document, all \cs{newcommand} and similar % statements between that point and \verb'\begin{document}' will be % marked for logging. At the end of the document a report of the % command usage will be printed in the \TeX{} log, for example: % \begin{verbatim} % "mdash" was used on line 25 % "ndash" was never used % "gar " was used on line 26 % "math character ?" was used on line 26 % \end{verbatim} % In this list, a command \cn{foo} is normally listed as % \verb'"foo"'; however if it was defined with an optional argument, % it will be listed as \verb'"\foo"', and if defined with % \cn{DeclareRobustCommand} it will be listed as % \texttt{"foo\symbol{32}"} (with an extra space). This has to do % with the way \latex/ deals with such definitions behind the scenes. % Twiddling the behavior to get more consistent treatment of the % command names looked hard, so I didn't do it. If you can send % actual code to remedy this deficiency, it will be welcome. I do not % plan on trying to fix it myself until after I have dealt with all % the other, more interesting or more pressing, problems in my queue. % % Certain kinds of commands are inherently untrackable due to the way % they are used (counters, lengths, and other variables that may % appear on the right-hand of an assignment statement; commands whose % first use is in the argument of \cs{label}, and so on.) Tracking % for commands of this sort can be turned off by moving their % definitions earlier (before the load statement of the cmdtrack % package), or by listing them in the argument of an \cs{untrack} % statement at the end of your document preamble, for example: % \begin{verbatim} % \untrack{\foo,\bar,\blub,...} % \end{verbatim} % % \section{Limitations} % \begin{itemize} % \item Only commands defined with \cs{newcommand}, \cs{newenvironment}, % \cs{newtheorem}, \cs{DeclareMathSymbol}, \cs{DeclareMathOperator}, % and their variants are logged. Commands will not be logged if they % are defined with \cs{def} instead of \cs{newcommand}, % \cs{mathchardef} instead of \cs{DeclareMathSymbol}, etc. % % \item \qq{Commands} defined with \cs{newlength}, \cs{newsavebox}, % \cs{newcounter}, \cs{newcount}, \cs{newtoks}, etc., will not be % logged because it cannot be done without disrupting their normal % use. % % \item Commands defined with \cs{DeclareTextSymbol}, % \cs{DeclareTextAccent}, \cs{DeclareMathRadical}, % \cs{DeclareMathAlphabet}, and various other things will not be % logged because I was starting to doze off on the keyboard after % adding the support for \cs{DeclareMathSymbol}. Any volunteers? % % \item The definitions of the commands that are to be logged must fall % between \verb'\usepackage{cmdtrack}' and \verb'\begin{document}'. % For problem commands, try moving their definitions before the % \verb'\usepackage{cmdtrack}' line, or use the \cs{untrack} command % to cancel tracking for selected commands at the end of the % preamble. % % \item The \pkg{cmdtrack} package should be the last package loaded % (or, the later-loaded packages will have their commands tracked as % well, if that is what you want). % % \item A command definition starting with \cs{multicolumn} will cause % trouble (unless it is never used). % % \item Large number of \cs{newcommands} (200+, say) might lead to an % error message \qq{\TeX{} capacity exceeded (hash size \ldots)}. % Depends on the capacity of your \TeX{} system. % % \end{itemize} % % \StopEventually{} % % \section{Embedded documentation} % % The following material comes into play only when the \verb'?' % package option is used. % % \begin{macrocode} %% Self-documenting section \ifcat ?$\relax{\catcode37=7 \catcode127=9 \def\0{\@sanitize\catcode}\fi %%? \endlinechar125\catcode127=13\def%%?{\typeout}\037=7 %%?{==================================================================== %%?{ With the cmdtrack package, all commands and environments defined %%?{ between \usepackage{cmdtrack} and \begin{document} will be marked %%?{ for logging. A report on the usage of the marked commands will be %%?{ printed in the LaTeX log file. Standard LaTeX methods must be used %%?{ for defining the commands (things defined with \def, for example, %%?{ won't be logged). Use \untrack{\cmd,\othercmd,...} just before %%?{ \begin{document} to turn off tracking for selected commands. %%?{ %%?{ Package options: %%?{ %%?{ ? Causes this information to be shown on-screen. %%?{ %%?{ morose Opposite of verbose: causes the brief message about the ? %%?{ option to be suppressed. %%?{ %%?{ Support for the following is not [yet] provided: %%?{ \DeclareTextSymbol, \DeclareMathRadical, \DeclareMathAlphabet, and %%?{ some others. %%?{ %%?{ More comprehensive documentation for cmdtrack.sty may be found in %%?{ cmdtrack.dtx. %%?{==================================================================== %%?{}}\endinput\bgroup %% % \end{macrocode} % % \section{Implementation} % Standard declaration of package name and date. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{cmdtrack}[2012/12/18 v1.06] % \end{macrocode} % % The \pkg{cmdtrack} package works by hooking into the internal % \LaTeX{} function \cs{@yargdef}. When processing something like % \verb'\newcommand{\foo}{...}', there is a point where \LaTeX{} % runs, essentially, % \begin{verbatim} % \def\foo{...} % \end{verbatim} % Just as \LaTeX{} is about to carry out that assignment, we jump % in and substitute a different control sequence in place of % \cs{foo}! Our substituted control sequence has the same name but % with an extra double-quote character \verb'"' added at the % beginning: i.e., \verb'\"foo' instead of \cs{foo}. Thus \cs{"foo} % gets the real definition, and we are free to give \cs{foo} some % other definition for logging purposes. Obviously it should end by % calling the real definition. And here is how we arrange that. % % \begin{enumerate} % \item \cs{foo} expands to \verb'\logcmd \"foo \foo'. % % \item \cs{logcmd} redefines \cs{foo} to take on the meaning of % \cs{"foo}. % % \item \cs{logcmd} adds \cs{"foo} to a used-commands list, and records % the current line number with it. % \end{enumerate} % % Then when we reach the end of our document, we need to find some % way of looking through all of our marked commands and reporting % which ones were used. During the processing of the preamble, the % marked commands were stored in a list \cs{commandlist}. % Furthermore, when \cs{logcmd} redefined \cs{"foo}, it put in a % special marker character along with the line number. Then when we % reach the end of our document, we can iterate over the command list % with a function that checks for that special character in the % \cs{meaning} of each command. % % Alternatively one could imagine adding the used commands to a % separate list. At one point I started doing that but it got a % little messy so I abandoned the idea. Besides, this way the report % comes out with the commands in the same order as they were defined % in the preamble (except that newtheorem commands gravitate toward % the end of the list). % % \begin{macrocode} \let\commandlist\@empty % \end{macrocode} % % \begin{macrocode} \AtEndDocument{\report@command@usage} % \end{macrocode} % % The \LaTeX{} kernel doesn't provide this. % \begin{macrocode} \edef\@quotechar{\string"} % \end{macrocode} % % The \cs{untrack} command could just redefine \cs{logcmd} and run % through its argument list, but if the user accidentally leaves in % some command that is no longer defined (or defined before the % \pkg{cmdtrack} package is loaded) then some kind of error is % likely. So we check specifically for the string \verb"\logcmd" at % the beginning of each command's \cs{meaning} string. % \begin{macrocode} \newcommand{\untrack}[1]{% \begingroup \def\logcmd##1##2{\global\let##1=##2% \xdef##2{\@percentchar\the\inputlineno}% }% \untrack@a#1{,\@gobble}\endgroup } % \end{macrocode} % % \begin{macrocode}i \def\untrack@a#1{% \ifx,#1\@gobbletwo\expandafter\@gobble \else \expandafter\untrack@b\meaning#1\@nil#1% \fi \untrack@a } % \end{macrocode} % % \begin{macrocode} \def\untrack@b#1->#2#3#4#5#6#7#8#9\@nil{% \expandafter\ifx\csname #3#4#5@#6#7#8\endcsname\log@cmd \else \def\@tempa##1{% \PackageWarningNoLine{cmdtrack}{% Command \protect##1 does not have tracking turned on}% }% \expandafter\@tempa \fi } % \end{macrocode} % % One branch of providecommand processing uses \cs{reserved@a} in a % way that will fail unless we watch out for it. % \begin{macrocode} \def\@isreserved@a#1\reserved@a#2#3@{#2} % \end{macrocode} % % \begin{macrocode} \let\@hash@\relax \def\log@cmd#1#2{% \if\@isreserved@a#2T\reserved@a F@T% \endgroup \else \toks@\expandafter{\commandlist#1}% \xdef\commandlist{\the\toks@}% \endgroup \def#2{\logcmd#2#1}% \fi \let\@hash@##% \l@ngrel@x\expandafter\def\expandafter#1\reserved@a } % \end{macrocode} % % \begin{macrocode} \def\logcmd#1#2{% \ifx\protect\@typeset@protect \global\let#1#2% \xdef#2{\@percentchar\the\inputlineno}% \else \expandafter\protect \fi #1% } % \end{macrocode} % % \begin{macrocode} \begingroup \catcode`\"=12 \gdef\cmd@check#1->#2#3-#4\@nil#5{% \if\@percentchar#2\typeout{\string#5" was used on line #3}% \else\typeout{\string#5" was never used}% \fi } \endgroup % \end{macrocode} % % \begin{macrocode} \def\report@command@usage{% \def\@tempa{\typeout{=========================================}}% \@tempa \begingroup \escapechar\m@ne \def\do##1{% \ifx\advance##1\expandafter\@gobbletwo\fi {\expandafter\cmd@check\meaning##1->@-\@nil##1}% \do }% \expandafter\do\commandlist \advance\z@\z@ \endgroup \@tempa } % \end{macrocode} % % \begin{macrocode} \def\testthm#1{% \expandafter\testthm@a\csname#1\expandafter\endcsname \csname\@quotechar#1\endcsname } % \end{macrocode} % % In order to avoid figuring out how to read the optional arguments % of \cs{newtheorem}, we postpone the application of \cs{log@cmd} % (actually, a slight variation thereof) until % \verb'\begin{document}'. % \begin{macrocode} \let\old@newtheorem\newtheorem \def\newtheorem#1{% \AtBeginDocument{\testthm{#1}}% \old@newtheorem{#1}% } % \end{macrocode} % % \begin{macrocode} \def\testthm@a#1#2{% \begingroup \toks@\expandafter{\commandlist#2}% \xdef\commandlist{\the\toks@}% \endgroup \let#2#1% \def#1{\logcmd#1#2}% } % \end{macrocode} % % It would be unusual for a character to be defined as a math symbol % in a document preamble. But what hey, why not support it? % \begin{macrocode} \def\set@mathchar#1#2#3#4{% \expandafter\set@mathchar@a \csname\@quotechar math character \string#2\expandafter\endcsname \expandafter{\number`#2}{#1}{#3}{#4}% }% % \end{macrocode} % % \begin{macrocode} \def\set@mathchar@a#1#2#3#4#5{% \global\mathcode#2=\@quotechar 8000 \global\mathchardef#1\@quotechar\mathchar@type#4\hexnumber@#3#5\relax \toks@\expandafter{\commandlist#1}% \xdef\commandlist{\the\toks@}% \begingroup \lccode`\.=#2\lccode`\~=#2\lowercase{\endgroup \gdef~{\global\mathcode#2=#1\logcmd#1#1}}% } % \end{macrocode} % % \begin{macrocode} \def\set@mathsymbol#1#2#3#4{% \begingroup \escapechar=`\"\relax \global\expandafter\mathchardef \csname\string#2\endcsname \@quotechar\mathchar@type#3\hexnumber@#1#4\relax \expandafter\log@cmd@a\csname\string#2\endcsname#2% } % \end{macrocode} % % \begin{macrocode} \def\set@mathaccent#1#2#3#4{% \xdef#2{\mathaccent\@quotechar\mathchar@type#3\hexnumber@#1#4\relax}% \begingroup \escapechar`\"\relax \expandafter\log@cmd@a\csname\string#2\endcsname#2% } % \end{macrocode} % % Note the use of \cs{gdef}. % \begin{macrocode} \def\log@cmd@a#1#2{% \toks@\expandafter{\commandlist#1}% \xdef\commandlist{\the\toks@}% \endgroup \gdef#2{\logcmd#2#1}% } % \end{macrocode} % % \begin{macrocode} \DeclareOption{?}{\AtEndOfPackage{\ShowPackageInfo{cmdtrack}}} % \end{macrocode} % % \begin{macrocode} \DeclareOption{morose}{} % \end{macrocode} % % \begin{macrocode} \DeclareOption{simple}{% \def\logcmd#1#2{% \ifx\protect\@typeset@protect \global\let#1#2% \begingroup \escapechar\m@ne \typeout{\string#2\string" was used on line \the\inputlineno}% \endgroup \else \expandafter\protect \fi #1% }% \AtBeginDocument{\global\let\commandlist\@empty}% \global\let\report@command@usage\relax } % \end{macrocode} % % \begin{macrocode} \ProcessOptions\relax \begingroup \catcode`\%=9 \catcode`\&=14 \catcode`\"=12 \@ifpackagewith{cmdtrack}{morose}{\catcode`\%=14 }{} \@ifpackagewith{cmdtrack}{?}{\catcode`\%=14 }{} %%\typeout{& %%Try "\string\usepackage[\string ?]{cmdtrack}" %%to see information on using this package^^J& %%[including how to turn off this "helpful" message].& %%} \endgroup % \end{macrocode} % % \begin{macrocode} \newcommand{\ShowPackageInfo}[1]{% \begingroup \catcode`\?=3 \input{#1.\@pkgextension}% \endgroup } % \end{macrocode} % % \begin{macrocode} \let\@@yargdef\@yargdef % \end{macrocode} % % Restore \cs{@yargdef} to normal at beginning of document, so that uses of % \cs{newcommand} in \cs{maketitle} (e.g.\@) are ignored. % \begin{macrocode} \AtBeginDocument{\let\@yargdef\@@yargdef} % \end{macrocode} % % \begin{macrocode} \let\@hash@\relax \def\@yargdef #1#2#3{% \@tempcnta#3\relax \advance\@tempcnta\@ne \let\@hash@\relax \edef\reserved@a{\ifx#2\tw@ [\@hash@ 1]\fi}% \@tempcntb#2% \@whilenum\@tempcntb<\@tempcnta\do{% \edef\reserved@a{\reserved@a\@hash@\the\@tempcntb}% \advance\@tempcntb\@ne }% \begingroup \escapechar=`\"\relax \expandafter\log@cmd\csname\string#1\endcsname#1% } % \end{macrocode} % % The usual \cs{endinput} to ensure that random garbage at the end of % the file doesn't get copied by \fn{docstrip}. % \begin{macrocode} \endinput % \end{macrocode} % % \Finale