%%% ====================================================================
%%%  @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}
%</driver>
% \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
