% \iffalse meta-comment % % Copyright (C) 2005-7 by Ulrich M. Schwarz % % This file may be distributed and/or modified under the conditions of % the LaTeX Project Public License, either version 1.3a or, at your % option, any later version. The latest version of this license is in % % http://www.latex-project.org/lppl.txt % % \fi % %\iffalse %<*driver> \documentclass{ltxdoc} \usepackage[l2tabu]{nag} \GetFileInfo{nag.sty} \typeout{\fileversion} \usepackage[T1]{fontenc} %\usepackage{bera}% much smaller pdf now. \usepackage{fourier} \usepackage[scaled=0.87]{luximono} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{nag.dtx} \end{document} % %<*nagdemo> %% Test document: finding and complaining about obsolete macros. %% \RequirePackage[l2tabu, orthodox, experimental]{nag}[2007/04/23] \documentclass{article} %% some usual culprits \usepackage{times, a4wide, epsfig, palatino} %% some fancy packages \usepackage{subfig, topcapt, caption, hyperref} \begin{document} \typeout{Next: no complaint because frontmatter is not defined} \ifx\frontmatter\undefined \else \typeout{FAILURE! I shouldn't know frontmatter!} \fi \typeout{Next: no complaing about label outside float not preceded by caption} \section{Tests}\label{sec:tests} \typeout{Next: it and bf complaints} {\it italics {\bf not bold italics}} \typeout{Next: not-an-env complaints} \begin{Large} \begin{sffamily} Large and sans. \end{sffamily} \end{Large} \typeout{Next: center in float complaint} \begin{figure} \begin{center} Center in float. \end{center} \caption{\label{fig}Figs and dates.} \end{figure} \typeout{Next: no complaints: manually fake caption} \begin{figure} I have a caption, you just can't see it. \makeatletter\nag@hascaptiontrue\makeatother \label{date} \end{figure} \typeout{Next: no complaing about label outside float not preceded by caption} \section{More Tests}\label{sec:tests2} \typeout{Next: put-label-after-caption complaint} \begin{figure} \label{coconut}\caption{Preceded, not followed, by label.} \end{figure} \typeout{Next: no-caption complaint} \begin{figure} No caption, even a fake one. \end{figure} \typeout{Next: no complaint about subfloat and topcapt} \begin{figure} \subfloat{\label{sf:1}Subfig number~\ref{sf:1} with label.} \subfloat[\label{sf:17}Strange subfig]{Subfig~\ref{sf:17} with label elsewhere.} \caption{Figure} \end{figure} \begin{figure} \topcaption{A topcaption.} \subfloat{\label{sf:2}Subfig~\ref{sf:2} with label, but no caption.} \end{figure} \typeout{Next: no robustness issues} \begin{minipage}{5cm} foo\footnote{bar} \end{minipage} \typeout{Shouldn't cause trouble to have dollars in headings.} \section{Maths tests, like if $1+1=2$} \typeout{Next: three complaints in total concerning $$ end eqnarray} A \TeX-style displayed equation: $$ 1+1=2 $$ Not an equation at all: $ $ 1+1=2 $ $ An in line equation: $1+1=2$ Two inline equations, double dollar is dollar dollar in resticted horizontal mode (onlyamsmath gets this wrong): $a+b=c$$1+1=2$ An eqnarray: \begin{eqnarray} 1+1 &=& 2 \end{eqnarray} A bracket-style equation: \[1+1=2\] A starred eqnarray: \begin{eqnarray*} 1+1 &=& 2 \end{eqnarray*} A double-dollar in a hbox: \hbox{$$} \typeout{Next: appendix complaints} \begin{appendix} \begin{center} It's a center environment. \end{center} \typeout{Next: no over complaint, centerline complaint, no frac complaint} Over etc. warning removed for compatibility with \LaTeX\ without amsmath. \centerline{Furthermore, $4\over 2=2$.} $\frac 42$ \end{appendix} \typeout{Next: unmatched endflushright} This is not flushright, in spite of a endflushright coming up. \endflushright \typeout{Next: unclosed center} {\center Smack in the middle, but center used as a switch\par} \typeout{Next: mismatched endflushright} Another endflushright, this is brace-mismatched and otherwise totally unsuited for closing the center command above. \endflushright \AtEndDocument{\typeout{You should get 20 warnings.}} \end{document} % % %\fi % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} %\CheckSum{624} % %\DoNotIndex{\if,\else,\fi,\PackageWarning,\PackageWarningNoLine,\typeout} %\DoNotIndex{\@for,\addtocounter,\arabic,\centering,\csname,\CurrentOption} %\DoNotIndex{\DeclareOption,\def,\do,\endcsname,\expandafter,\ifnum,\ifx} %\DoNotIndex{\InputIfFileExists,\let,\lq,\rq,\MessageBreak,\protect} %\DoNotIndex{\space,\stepcounter,\the,\value,\relax,\ProcessOptions} %\DoNotIndex{\ifcsname,\@ifundefined,\flo,\begingroup,\endgroup} % %\changes{0.1}{2005/03/29}{First official version.} %\changes{0.2}{2005/05/08}{Rephrased umlaut.sty warning, suggested by %Patrick Happel.} %\changes{0.2}{2005/05/08}{Added abort.nag, suggested by Michael Zedler} %\changes{0.3}{2005/07/07}{New ifdefined that won't relax the commands} %\changes{0.4}{2006/04/19}{Handling command vs. environment; bugfixes} % \changes{0.5}{2006/07/08}{Handle the case that somebody else relaxes % the ver@-commands. Stack-based NotASwitch.} %\changes{0.55}{2007/03/31}{Some spaces crept in in 0.5} % %\GetFileInfo{nag.sty} %\newcommand\pkg[1]{\textsf{#1}} %\title{The \pkg{nag} package\ignorespaces% % \thanks{This document corresponds to \pkg{nag}~\fileversion, % dated~\filedate. Other versions can be found at http://absatzen.de/}} % \author{Ulrich Michael Schwarz\ignorespaces% % \thanks{\texttt{ulmi@absatzen.de}}} % % \maketitle % % \begin{abstract} % Old habits die hard. All the same, there are commands, classes and % packages which are outdated and superseded. \pkg{nag} provides % routines to warn the user about the use of those. As an example, we % provide an extension that detects many of the ``sins'' described in % \pkg{l2tabu}. % \end{abstract} % % \tableofcontents % % \section{User-side considerations.} % % \subsection{Installation.} % % Process \texttt{nag.ins} with \LaTeX\ to obtain some files: % \texttt{nag.sty} and \texttt{nag-l2tabu.cfg} et al. must go to a place where % \LaTeX\ will find them, like the local TEXMF tree. (If all else fails and % you need it to work \emph{right now}, having them in the same % directory as the \LaTeX\ file you want to use them on may work under % many circumstances.) You can, as usual, run \LaTeX\ on % \texttt{nag.dtx} to obtain this documentation, including the % implemenation docs. (This is recommended if you plan to extend % \pkg{nag} to handle your own packages.) \texttt{nagdemo.tex} is % a horrible document that will show you many of the warnings that % \pkg{nag} can generate. % % \subsection{Usage.} % % Add the following to the beginning your main document (Comments and % |\listfiles| can be safely left before it, though): % \begin{verbatim} % \RequirePackage[l2tabu, orthodox]{nag}\end{verbatim} % This will check for many common mistakes, and give some hints on what % to use instead. However, you should always refer to l2tabu for a more % detailed explanation of the whats and whys: it gives more information % than can be possibly pressed into two lines of error message. % Orthodox checks for pitfalls that are not technically incorrect. If % you know what you're doing, omit orthodox. % % \subsection{\texttt{nag-l2tabu.cfg}} % % In a nutshell, \texttt{nag-l2tabu.cfg} detects the following: % \begin{itemize} % \item Usage of the 2.09-style font commands |\it|, |\bf|, |\rm|, % |\sc|, |\sl|, |\tt| and |\cal|. % \item Usage of |\centerline|. % \item Usage of the outdated packages \pkg{epsfig}, \pkg{psfig}, % \pkg{epsf}, \pkg{doublespace}, \pkg{fancyheadings}, \pkg{scrpage}, % \pkg{umlaut}, \pkg{isolatin}, \pkg{isolatin1}, \pkg{t1enc}, % \pkg{caption2}, \pkg{psfonts}, \pkg{mathptm}, \pkg{times}, % \pkg{palatino}, \pkg{mathpple}, \pkg{euler} and \pkg{utopia}, and of % the outdated class \pkg{scrlttr}. % \item Figures and tables without caption (this is not technically % in l2tabu, but the people who have floats without captions tend % to ask ``Why is \LaTeX\ moving my pictures away from where I % put them?''), labels within floats % that do not reference the caption, and usage of the center % environment within floats. %\end{itemize} % % It is beyond the possibilities of this package to detect things like % use of \TeX\ assignment syntax, or direct change of paper % parameters, or reliable detection of user-issued |\sloppy|. % eqnarray is handled as of 0.60alpha4, and there is code for \$\$ in % experimental since 0.60alpha4, which has been moved to l2tabu in 0.60. % % {\bfseries\label{disclaimer} Be warned, that this package will possibly balk at % legitimate use, and not find illegitimate use in all cases. It is a % tool, not a replacement for study of \pkg{l2tabu}.} % % \begin{macrocode} %<*l2tabunag> \ProvidesFile{nag-l2tabu.cfg} [2007/06/10 v2.0 l2tabu rules for nag.sty (ulmi)] %% %% The sins. %% %% Section numbers refer to l2tabuen 1.7 revised/enlarged dated 2004OCT24 %% \S 1.1 \ObsoletePackage{a4wide}{the \lq a4paper\rq\space class option} \ObsoletePackage{a4}{the \lq a4paper\rq\space class option} %% \S 1.2--1.5 cannot reasonably be checked programmatically %% \S 1.6 % \end{macrocode} % Hacking galore ahead! We will make the dollar active. Since unlike % \pkg{onlyamsmath}, we do not change the user's command to \LaTeX\ or % \pkg{amsmath} commands, we need to store the old double dollar % sequence as well as the single dollar. % \begin{macrocode} \def\nag@doubledollar{$$}%$$ \def\nag@singledollar{$}%$ % \end{macrocode} % This is used to hide our redefinition in unprotected expanding % context. This should not happen: you are expected to \emph{always} % use protected means of expansion in \LaTeX, but fecal matter % happens. See below for a good trick to distinguish expansion from % executing context. % \begin{macrocode} \def\nag@expanding@voodoo#1#2#3{\relax\relax\nag@singledollar} \def\nag@maybedispmath{% \texorpdfstring{% %% in TeX context, do tricky stuff. \ifinner\expandafter\@firstoftwo \else\expandafter\@secondoftwo\fi {%% in inner mode, $$ is an empty formula, so no testing wanted. \nag@singledollar}% {%% \ifx\protect\@typeset@protect\expandafter\@firstoftwo \else\expandafter\@secondoftwo\fi {%% normal case: looks like typesetting %% protect against strictly expanding context %% like TeX' \message: the first expanding voodoo will expand, %% removing the rest, inserting \relax\relax$ instead. This is %% not totally transparent, but \let\relax\relax is as close %% to a no-op as we can get. \let\nag@expanding@voodoo\nag@expanding@voodoo \protect\nag@maybe@dispmath}% {%% some other case, hide ourselves \nag@singledollar}% }% }{% %% in pdf context, just be a math shift. This creates the "math %% shift not allowed" warnings we all love. \nag@singledollar }% } % \end{macrocode} % If the user doesn't load \pkg{hyperref}, we have to fake its % \cmd{\texorpdfstring} command. Note that this will break any package that % is foolish enough to detect \pkg{hyperref} by testing for % definedness of \cmd{\texorpdfstring}. % \begin{macrocode} \AtBeginDocument{\providecommand\texorpdfstring{\@firstoftwo}} \AtBeginDocument{\catcode`$\active}%$ % \end{macrocode} % Now, the proper testing. (Yes, the above is just the % technicalities.) We use the kernel's \cmd{\@ifnextchar} to look for % a possible second dollar. Note however, this would allow skipping of % spaces between them, and \$\_\$ is not a displayed equation start in % \TeX. We work around this by re\cmd{\let}ting \cmd{\@sptoken} to % something that cannot legally appear in the source. % \begin{macrocode} \bgroup \catcode`$\active%$ \gdef\nag@maybe@dispmath{% \bgroup \let\@sptoken\nag@quark% prevent skipping of spaces \@ifnextchar${%$% \ifmmode % we already warned upon entering. \else \nag@warn{% \nag@doubledollar...\nag@doubledollar\space is obsolete.\MessageBreak Use \string\[...\string\] et al. instead}% \fi \egroup\expandafter\nag@doubledollar\@gobble }{% \egroup\nag@singledollar }% } % we do the assignment here, which means any package that redefines % \$ as well will silently disable us. This is a feature. \global\let$\nag@maybedispmath%$ \egroup %% \S 1.7 cannot reasonably be checked programmatically %% \S 1.8 \sloppy is called by parbox, among others, and would %% give many spurious warnings. %% \S 2.1.1 \ObsoleteCS[an old LaTeX 2.09 command]{bf} {\protect\bfseries\space or \protect\textbf} \ObsoleteCS[an old LaTeX 2.09 command]{it} {\protect\itshape\space or \protect\textit} \ObsoleteCS[an old LaTeX 2.09 command]{rm} {\protect\rmfamily\space or \protect\textrm} \ObsoleteCS[an old LaTeX 2.09 command]{sc} {\protect\scshape\space or \protect\textsc} \ObsoleteCS[an old LaTeX 2.09 command]{sf} {\protect\sffamily\space or \protect\textsf} \ObsoleteCS[an old LaTeX 2.09 command]{sl} {\protect\slshape\space or \protect\textsl} \ObsoleteCS[an old LaTeX 2.09 command]{tt} {\protect\ttfamily\space or \protect\texttt} \ObsoleteCS[an old LaTeX 2.09 command]{cal} {\protect\mathcal}% Hmm, this is not in l2tabu? %% \S 2.1.2 %% Gone with 1.8 because this never worked for the kernel \frac anyway. %% \ObsoleteCS[TeX]{over}{\protect\frac} %% \ObsoleteCS[TeX]{choose}{\protect\frac\space or amsmath's \protect\binom} %% \S 2.1.3 \ObsoleteCS[TeX]{centerline}{\protect\centering\space or center environment} %% \S 2.2.1 \ObsoleteClass{scrlettr}{the scrlttr2 package} %% \S 2.2.2 \ObsoletePackage{epsf}{the graphicx package} \ObsoletePackage{psfig}{the graphicx package} \ObsoletePackage[deprecated]{epsfig}{the graphicx package directly} %% \S 2.2.3 \ObsoletePackage{doublespace}{the setspace package} %% \S 2.2.4 \ObsoletePackage{fancyheadings}{the fancyhdr or scrpage2 packages} \ObsoletePackage{scrpage}{the scrpage2 package} %% \S 2.2.5 \ObsoletePackage{isolatin}{the inputenc package with option latin1} \ObsoletePackage{umlaut}{the inputenc package with suitable option (latin1, utf8 ...)} \ObsoletePackage{isolatin1}{the inputenc package with option latin1} %% \S 2.2.6 \ObsoletePackage{t1enc}{the fontenc package with option T1} %% \S 2.2.7 we don't check for bst yet. %% (This is in l2tabu 1.8) \ObsoletePackage{caption2}{the caption package v3.0 or later} %% \S 2.3.1-3 \ObsoletePackage{times} {the mathptmx, helvet (option scaled=.9), courier packages} \ObsoletePackage{pslatex} {the mathptmx, helvet (option scaled=.9), courier packages} \ObsoletePackage{mathptm} {the mathptmx package} %% \S 2.3.4-5 \ObsoletePackage{palatino} {the mathpazo, helvet (option scaled=.95), courier packages} \ObsoletePackage{mathpple}{the mathpazo package} %% \S 2.3.6 can't be checked %% \S 2.3.7 \ObsoletePackage{euler}{the eulervm package} \ObsoletePackage{utopia}{the fourier package} %% \S 3.1 \NagDeclareFloat{figure}\NagDeclareFloat{table}% \g@addto@macro\nag@labels{,label}% % \changes{0.60}{2007/03/31}{alternate center-in-float check, doesn't % take up as many macro names} \nag@prepend{endcenter}{% \ifx\@captype\@undefined\else \nag@warn{\lq center\rq\space environment in \@captype.\MessageBreak Maybe you want \protect\centering\space instead}% \fi }% %% The latter two are used by KOMA-Script, the last by hypcap. % \changes{0.53}{2007/03/21}{hypcap support. (H.G.Krauth\"auser)} % \changes{0.53}{2007/03/21}{topcapt support.} \g@addto@macro\nag@captions{,caption,captionabove,captionbelow,hc@caption,topcaption}% %% \S 3.2 \NotAnEnvironment{appendix}% %% In the same vein: \@for\sectioning:=frontmatter,mainmatter,backmatter\do{% \expandafter\NotAnEnvironment\expandafter{\sectioning}% } %% \S 3.3 %% It's more trouble than it's worth to have another warning for %% align*, since it passes through align. \ObsoleteEnv{eqnarray}{amsmath's align} %% \S 3.4 -- nothing to be done -- % % \end{macrocode} % % \subsection{\texttt{nag-orthodox.cfg}} % \texttt{nag-orthodox.cfg} warns about usage that is not technically % incorrect, but will mostly do things an unwary user may not expect. % This includes in particular the usage of font size and style switches % as environments (line spacing will be off if the environment does not % contain a trailing \string\par, spurious spaces might occur since the % switches don't \string\ignorespaces), and, conversely, the usage of % center etc. environments as unclosed switches. (Detection of the % latter might still be somewhat brittle.) % \begin{macrocode} %<*orthodoxnag> \ProvidesFile{nag-orthodox.cfg} [2006/04/19 v1.8 strict rules for nag.sty (ulmi)] \@for\fontcmd:=tiny,small,footnotesize,normalsize,large,Large,% LARGE,huge,Huge\do{% \expandafter\NotAnEnvironment\expandafter{\fontcmd}% }% \@for\fontcmd:=sffamily,rmfamily,ttfamily,% bfseries,mdseries,scshape,% itshape,upshape\do{% \expandafter\NotAnEnvironment\expandafter{\fontcmd}% }% \@for\justsw:=centering,raggedleft,raggedright,% RaggedLeft,RaggedRight\do{% \expandafter\NotAnEnvironment\expandafter{\justsw}% } \@for\justenv:=center,flushleft,flushright\do{% \expandafter\NotASwitch\expandafter{\justenv}% } % % \end{macrocode} % % \subsection{\texttt{nag-abort.cfg}} % Requesting this nag file will turn all complaints into errors. % % \begin{macrocode} %<*abortnag> \ProvidesFile{nag-abort.cfg} [2005/05/08 v0.1 treat complaints as errors (ulmi)] \renewcommand\nag@warn[1]{% \addtocounter{nag@sins}{1}% \PackageError{nag}{#1}{#1}% } \renewcommand\nag@warnNoLine[1]{% \addtocounter{nag@sins}{1}% \PackageError{nag}{#1}{#1}% } % % \end{macrocode} %<*experimentalnag> %\subsection{\texttt{nag-experimental.cfg}} % Functionality that needs more testing. % \begin{macrocode} \ProvidesFile{nag-experimental.cfg} [2007/06/10 v0.1b experimental additions to nag (ulmi)] % \end{macrocode} % % %<*nag> % \section{Author-side considerations and implementation.} % If you are a package or class author and want to extend the range % of \pkg{nag} (or prevent \pkg{nag} from criticizing % your macros), please see the description below, in % sections~\ref{sec:obsol-cmds} and following. It is % probably wise to group new rules in a seperate nag file: % users can request nag files by passing their name as a package % parameter, as shown above for the example of l2tabu. % % \subsection{Low-level tools.} % Identify ourselves. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{nag}[2007/06/10 0.60 warning about old commands (ulmi)] \let\@xa\expandafter \let\@nx\noexpand % \end{macrocode} % First of all, two counters we need. The first is used to % generate running numbers for replacement macros, the latter is % stepped for each complaint we have, so that the user gets a % frighteningly high number, showing how sinful he or she is. % \begin{macrocode} \newcounter{nag@c} \newcounter{nag@sins} % \end{macrocode} % % \begin{macro}{\nag@prepend} % |\nag@prepend|\marg{cs}\marg{something}: % Prepend \meta{something} to the macro definition of |\|\meta{cs}. % % In reality, we do call indirection: save old macro away, % redefine macro to do the something, call old macro. % (With thanks to Juergen Goebel, Heiko Oberdiek and Rolf Niepraschk % (\pkg{savesym})) % % From $0.60\alpha_2$ on, nag is more robust about not defining % commands that are not there. Now, they're not even relaxed. % \begin{macrocode} \newcommand\nag@ifundefined[1]{% \begingroup \@ifundefined{#1}{\endgroup\@firstoftwo}{\endgroup\@secondoftwo}% } % \end{macrocode} % \changes{0.51}{2006/10/21}{bugfix} % Don't define the macro if it's not there. This confuses caption, % which loads ragged2e AtBeginDocument, at which point, RaggedLeft % et al. were already defined by us. % \changes{0.52}{2007/02/25}{info} % \changes{0.60alpha2}{2007/04/08}{don't even relax unknown % commands (J.Sommer)} % \dots but \emph{do} log a message. % \begin{macrocode} \newcommand\nag@prepend[2]{% \nag@ifundefined{#1}{% % if it doesn't exist, don't do anything. \PackageInfo{nag}{% Command \@backslashchar#1\space not defined, skipping amendment% }% }{% \@xa\let \csname nag@@#1@\thenag@c\@xa\endcsname \csname #1\endcsname \@xa\nag@pr@p@nd\csname #1\@xa\endcsname \csname nag@@#1@\thenag@c\endcsname{#2}% % \end{macrocode} % Fun with scoping: one might think we can get away with a (non-local) % |\advance\c@nag@c 1\relax| here. This would lead to less hashtable % usage. Problem: if a nag@@foo@17 macro ever escapes its scope, it % might be bound to something else entirely. This might occur with % some of the fancier table packages which use external files? % \begin{macrocode} \stepcounter{nag@c}% }% } \newcommand\nag@pr@p@nd[3]{% \def#1{#3#2}% } % \end{macrocode} % \end{macro} % \begin{macro}{\nag@warn} % All complaints to the user run through one of these two macros, % with or without source line. % \begin{macrocode} \newcommand\nag@warn{% \addtocounter{nag@sins}{1}% \PackageWarning{nag}% } \newcommand\nag@warnNoLine{% \addtocounter{nag@sins}{1}% \PackageWarningNoLine{nag}% } % \end{macrocode} % \end{macro} % % \subsection{Obsoletifying commands.}\label{sec:obsol-cmds} % % (No, I do not think that is a proper word either.) % % \begin{macro}{\ObsoleteCS} % Usage: |\ObsoleteCS|\oarg{reason}\marg{CS}\marg{suggestions} % Mark |\|\meta{CS} as obsolete. \meta{reason} defaults to % obsolete. When the macro is used anyway, the following % warning is logged: % % \noindent|Command \|\meta{CS}| is |\meta{reason}|. Use |\meta{suggestions}| instead.| % \begin{macrocode} \newcommand\ObsoleteCS[3][obsolete]{% \AtBeginDocument{% \nag@prepend{#2}{% \nag@warn{% Command \@backslashchar#2 is #1. \MessageBreak Use #3 instead}% }% }% } % \end{macrocode} % \end{macro} % % \begin{macro}{\ObsoleteEnv} % \changes{0.60alpha4}{2007/04/23}{There was no ObsoleteEnv?!} % \begin{macrocode} \newcommand\ObsoleteEnv[3][obsolete]{% \AtBeginDocument{% \nag@prepend{#2}{% \nag@warn{% Environment #2 is #1. \MessageBreak Use #3 instead}% }% }% } % \end{macrocode} % \end{macro} % % \subsection{Obsoletifying packages and classes.} % % Checking for packages and classes is done by looking for % |ver@foo.sty|, which holds the version information that is also % displayed by |\listfiles|. This means that we're out of luck if % fontenc ever becomes obsolete, because that won't be detected. % % First, define a macro to check if a control sequence is defined. % Unlike |\@ifundefined|, this will not define the control sequence % to |\relax|, but the arguments will be executed in a group. For % our purposes, this doesn't matter, because we only give a warning % (and |\addtocounter| already is |\global|). % \begin{macrocode} \newcommand\nag@ifcsname[3]{% \begingroup\@ifundefined{#1}{#3}{#2}\endgroup } % \end{macrocode} % Just because we can, use $\epsilon$\TeX' |\ifcsname| if we can. This % bootstrapping gives me a big grin\dots Note we add an extra group % for compatibility with the non-$\epsilon$ case. % \changes{0.52}{2007/02/25}{made eTeX-ifcsname more robust} % \begin{macrocode} \nag@ifcsname{ifcsname}{% \renewcommand*\nag@ifcsname[3]{% \begingroup % assume it won't be there. \let\tmp@a\@secondoftwo \ifcsname #1\endcsname % It still might be relax from some other test. Thanks to J\"org % Sommer for finding this bug. \expandafter\ifx\csname #1\endcsname\relax \else % it's there after all \let\tmp@a\@firstoftwo \fi \fi \tmp@a{#2}{#3}% \endgroup }% % \end{macrocode} % This way of escaping the grouping gives me an even % bigger grin. % \begin{macrocode} \global\let\nag@ifcsname\nag@ifcsname }{} % \end{macrocode} % % \begin{macro}{\ObsoletePackage} % Usage: |\ObsoletePackage|\oarg{reason}\marg{package}\marg{% % alternative}. Mark \meta{package} as obsolete. \meta{reason} defaults % to obsolete. If the \meta{package} is used anyway, at the end of % the compilation, the following warning will be displayed: % % \noindent|Package |\meta{package}| is |\meta{reason}|. Use | % \meta{alternative}| instead.| % \begin{macrocode} \newcommand\ObsoletePackage[3][obsolete]{% \AtEndDocument{% % |\@clsextension| is onlypreamble, for some reason. \nag@ifcsname{ver@#2.sty}{% \nag@warnNoLine{% Package #2 is #1.\MessageBreak Use #3 instead}% }{}% }% } % \end{macrocode} % \end{macro} % % \begin{macro}{\ObsoleteClass} % Usage: |\ObsoleteClass|\oarg{reason}\marg{class}\marg{% % alternative}. Mark \meta{class} as obsolete. \meta{reason} defaults % to obsolete. If the \meta{class} is used anyway, at the end of % the compilation, the following warning will be displayed: % % \noindent|Class |\meta{class}| is |\meta{reason}|. Use | % \meta{alternative}| instead.| % \begin{macrocode} \newcommand\ObsoleteClass[3][obsolete]{% \AtEndDocument{% % |\@clsextension| is onlypreamble, for some reason. \nag@ifcsname{ver@#2.cls}{% \nag@warnNoLine{% Class #2 is #1.\MessageBreak Use #3 instead}% }{}% }% } % \end{macrocode} % \end{macro} % % \subsection{Common float errors and no-nos.} % % We do the following: % \begin{itemize} % \item check for presence of a caption % \item check for absence of the center environment % \item check that a label comes only after a caption % \end{itemize} % % First of all, we define two ifs to memorize whether we have a % label and/or a caption in the float already. Package writers may % want to set these manually behind \pkg{nag}'s back. In this % way, they can suppress possible warnings if they know what % they're doing -- we only check at the end of the float % environment, which gives them plenty of time to call % |\csname nag@haslabeltrue\endcsname| et al. % (Thanks to Markus Kohm for pointing out this need.) % We initialize |\nag@hascaption| to be true because since 0.60, % |\label| always checks if it's after a caption, even outside of % floats. % \begin{macrocode} \newif\ifnag@haslabel \newif\ifnag@hascaption\nag@hascaptiontrue % \end{macrocode} % Now, to the work proper: as of 0.60, it is sufficient to set the % label and caption flags to false. |\endcenter| now always checks % if it is inside a float (looking at |\@captype|). The label and % caption commands are amended only once. This should be % sufficient: captions are not handled by letting |\caption| to the % proper command upon float entry, so we assume nobody redefines % |\caption| at runtime, or they provide more entries to % |\nag@captions|. Similar for |\label|, and we do not care about % the flag setting outside of floats. % \begin{macrocode} \newcommand\nag@hackfloat[1]{% \nag@prepend{#1}{% \global\nag@haslabelfalse\global\nag@hascaptionfalse }% \nag@prepend{end#1}{% \ifnag@hascaption\relax\else \nag@warn% {#1 with no \protect\caption}% \fi % labels outside floats shouldn't complain: \global\nag@hascaptiontrue % (we do this always because it needs to be global) }% } % \end{macrocode} % Add checks to all macros named by |\nag@labels| % and |\nag@captions|, respectively. % \changes{0.3}{2005/07/07}{Fixed missing globals} % Scoping of presence-of-caption information: % \changes{0.4}{2006/04/19}{bugfix} % Well, maybe I should do it the way the kernel does, which means % a label is just as local as |\refstepcounter|'s |\@currentlabel| % information as of v0.4. I think we can leave captions global. % \changes{0.60}{2007/03/31}{Captions/Labels now done only once, and not every time % we enter a float} % \changes{0.60}{2007/03/31}{@preamblecmds} % Big old hack: we do this at |\@preamblecmds|-time, which is after % |\AtBeginDocument|, since hyperref loads nameref ABD, and nameref % steps all over label. \emph{Note:} We cannot use |\nag@prepend| % for this, since it would break the pkgindoc package, which nobody % has ever heard of, but it's in the kernel and relies on certain % tokens being present in the expansion of |\@preamblecmds|. Now, % you pretty much cannot get any later than this. % % \emph{Note:} we cannot exchange the order of the for loops here: % if a cs generates both a label and a caption, it shouldn't get % complained about. % \begin{macrocode} \AtBeginDocument{% \g@addto@macro{\@preamblecmds}{% \@for\labelprovider:=\nag@labels\do{% \ifx\labelprovider\@empty\else \nag@prepend{\labelprovider}% {\nag@captioncheck\nag@haslabeltrue}% \fi }% \@for\captionprovider:=\nag@captions\do{% \ifx\captionprovider\@empty\else \nag@prepend{\captionprovider}{\global\nag@hascaptiontrue}% \fi }% }% } \newcommand\nag@captioncheck{% \ifnag@hascaption\else \nag@warn{\protect\label\space in float, but not after \protect\caption}% \fi } % \end{macrocode} % Define the lists of commands that are floats, generate labels, % and generate captions, respectively. We don't start with defined % floats (that is for nag-l2tabu.cfg to set up). Since v0.52, we handle % an empty name, so the lists may be empty. Also, no labels and % captions are provided by default since v0.52. This has been moved % to nag-l2tabu.cfg. % See also % |\NagDeclareFloat|, which is the user-level wrapper for new % floats. Since there are no packages to define new % caption or label commands on an user level, there is no wrapper % for those. % \begin{macrocode} \def\nag@floats{} \def\nag@labels{} \def\nag@captions{} % \end{macrocode} % % We call the above for each float environment named via % |\nag@floats|: % \begin{macrocode} \newcommand\nag@floatsetup{% \@for\flo:=\nag@floats\do{% \ifx\flo\@empty\else \@xa\nag@hackfloat\@xa{\flo}% \fi }% } % \end{macrocode} % but only after all other packages get their chance to add to the % list: % \begin{macrocode} \AtBeginDocument{% \nag@floatsetup } % \end{macrocode} % % At the very end, we will display a running total of complaints. % \begin{macrocode} \AtBeginDocument{% \AtEndDocument{% \ifnum\value{nag@sins}>0% \PackageWarningNoLine{nag}{\arabic{nag@sins} complaints in total}% \else \typeout{No complaints by nag.}% \fi }% } % \end{macrocode} % % \section{Switch vs. Environment} % % People often use switches as environments and vice versa. This is % dangerous in because it tends to \emph{almost} work. % (Consider font size commands in particular, but also |\centering| % vs. |center| environment.) As usual, ``it's not an error if you % know what you're doing''. In particular, it is perfectly valid % code to use the |\foo|\dots|\endfoo| syntax. So, |\NotASwitch| % needs to trace the calls to |\foo| and see if they match with % corresponding |\endfoo|s with its own stack. This might still be % brittle. Fortunately, it is currently only needed for % nag-orthodox, where it checks for the justification environments. % % First of all, a helper macro we hinge upon: % \changes{0.53}{2007/03/20}{bugfix: more Robustness. (J\"org Sommer)} % \begin{macrocode} \DeclareRobustCommand\nag@ifCurrentEnvironment[3]{% \bgroup \def\tmp@a{#1}% \ifx\@currenvir\tmp@a #2% \else #3% \fi \egroup } % \end{macrocode} % And now, the two variations there are: % \begin{macro}{\NotAnEnvironment} % Usage:|\NotAnEnvironment|\marg{command} % Issue an error if the user calls |\begin{command}| and not % |\command| directly. % \begin{macrocode} \newcommand\NotAnEnvironment[1]{% \AtBeginDocument{% \nag@prepend{#1}{% \nag@ifCurrentEnvironment{#1}{% \nag@warn{% There is no environment ``#1''.\MessageBreak Maybe you want a grouped \@backslashchar#1 }% }{% OK case. }% }% }% } % \end{macrocode} % \end{macro} % |\NotASwitch| is a bit more involved: % \begin{macro}{\NotASwitch} % Usage:|\NotASwitch|\marg{command} % Issue an error if the user calls |\command| and not % |\begin{command}| and mis-nests calls or doesn't call % |\endcommand| at all. % \changes{0.54}{2007/03/27}{bugfix: can't get around the token register. (J\"org Sommer)} % \begin{macrocode} % we need to maintain a stack of environments that are used in the % \foo...\endfoo way. \newcommand\nag@envstack{\relax} \DeclareRobustCommand\nag@beginenv[1]{% % push a begin-entry onto the stack. Form is % |{\foo{lineno}}| for environment foo. \bgroup \@xa\toks@\@xa{\nag@envstack}% \xdef\nag@envstack{% \@nx{% \@xa\@nx\csname #1\endcsname \@nx{\the\inputlineno\@nx}% \@nx}% \the\toks@ }% \egroup } \DeclareRobustCommand\nag@endenv[1]{% % extract the first entry. \@xa\nag@end@nv\nag@envstack\@nil #1\@nil } \def\nag@end@nv#1#2\@nil #3\@nil{% \def\tmp@a{#1}% \def\tmp@b{\relax}% \ifx\tmp@a\tmp@b % This was the end-of-stack flag. \nag@warn{``\@backslashchar end#3'' without matching ``\@backslashchar #3''} \else % We may assume this is a proper entry. See if the begin-token on % the stack matches what |\nag@endenv| was passed. \@xa\ifx\csname #3\@xa\endcsname\@firstoftwo #1% %OK case, just pop the entry. \gdef\nag@envstack{#2}% \else % error case \nag@warn{% You cannot close ``\@xa\string\@firstoftwo #1'' on line \@secondoftwo #1 with ``\@backslashchar end#3''% }% % leave it on the stack. Some case of misnesting will always cause % horrible amounts of follow-up errors. Also, scare them! \fi \fi } % \end{macrocode} % At the end, we complain about all the entries that are still on % the stack. % \begin{macrocode} \AtEndDocument{% \@xa\@tfor\@xa\looseends\@xa:\@xa=\nag@envstack\do{% \@xa\ifx\looseends\relax\else \nag@warnNoLine{Unmatched ``\@xa\@xa\@xa\string\@xa\@firstoftwo\looseends'' command on line \@xa\@xa\@xa\string\@xa\@secondoftwo\looseends% }% \fi }% } % \end{macrocode} % \end{macro} % Now, the user-side command is easy. % \begin{macrocode} \newcommand\NotASwitch[1]{% \AtBeginDocument{% \nag@prepend{#1}{% \nag@beginenv{#1}% }% \nag@prepend{end#1}{% \nag@endenv{#1}% }% }% } % \end{macrocode} % % \section{Compatibility issues} % \subsection{The \pkg{caption} package} % Axel Sommerfeldt's \pkg{caption} package loads the \pkg{ragged2e} % package AtBeginDocument (regardless of whether it is needed). % This is too late for us to amend the |\RaggedFoo| commands with % |\NotAnEnvironment|. Since v0.51 of \pkg{nag}, they will then be % skipped (with information in the log). Earlier versions would % fail because by time \pkg{ragged2e} was loaded, the commands were % already defined by the amendment process. To make sure the % commands \emph{are} amended, load \pkg{ragged2e} explicitly % yourself. % % \subsection{The \pkg{subfig} package} % Starting with v0.52 of \pkg{nag}, we recognize the fact that the % |\subfloat| command from Steven D. Cochran's \pkg{subfig} package % is a caption-provider for its fourth argument. Earlier versions % would flag use of |\label| as inappropriate. The current % implementation works with versions close enough to v1.3 of % \pkg{subfig}. Since the change is a one-liner, I hope it will be % integrated into future versions of \pkg{subfig}. % \changes{0.52}{2007/02/25}{twiddle subfig's bowels} % \begin{macrocode} \AtBeginDocument{% \nag@ifcsname{ver@subfig.sty}{% \PackageInfo{nag}{Attempting subfig hack\@gobble}% \nag@maybehacksubfig }{% }% } \def\nag@maybehacksubfig{% % % of course, i need to touch the single longest definition in % subfig.sty, to amend one single command... % % The definition is taken from subfig.sty 1.3 dated 2005/07/05 by % S.D. Chochran, where it is called sf@@@subfloat, and appears here % under the conditions of section 6 of the LPPL 1.3. The subfig % package is available on a CTAN mirror near you. % \long\def\nag@@original@@sf@@@subfloat##1[##2][##3]##4{% \@ifundefined{FBsc@max}{% }{% \FB@readaux{\let\FBsuboheight\relax}% }% \@tempcnta=\@ne \if@minipage \@tempcnta=\z@ \else\ifdim \lastskip=\z@ \else \@tempcnta=\tw@ \fi\fi \ifmaincaptiontop \sf@top=\sf@nearskip \sf@bottom=\sf@farskip \else \sf@top=\sf@farskip \sf@bottom=\sf@nearskip \fi \leavevmode \setbox\@tempboxa \hbox{% ##4}% \@tempdima=\wd\@tempboxa \@ifundefined{FBsc@max}{% }{% \global\advance\Xhsize-\wd\@tempboxa \dimen@=\ht\@tempboxa \advance\dimen@\dp\@tempboxa \ifdim\dimen@>\FBso@max \global\FBso@max\dimen@ \fi }% \vtop\bgroup \vbox\bgroup \ifcase\@tempcnta \@minipagefalse \or \vskip\sf@top \or \ifdim \lastskip=\z@ \else \@tempskipb\sf@top\relax\@xaddvskip \fi \fi \sf@ifpositiontop{% \ifx \@empty##3\relax \else \sf@subcaption{##1}{##2}{##3}% \vskip\sf@capskip \vskip\sf@captopadj \fi\egroup \hrule width0pt height0pt depth0pt \box\@tempboxa }{% \@ifundefined{FBsc@max}{% \box\@tempboxa }{% \ifx\FBsuboheight\relax \box\@tempboxa \else \vbox to \FBsuboheight{\FBafil\box\@tempboxa\FBbfil}% \fi}% \egroup \ifx \@empty##3\relax \else \vskip\sf@capskip \hrule width0pt height0pt depth0pt \sf@subcaption{##1}{##2}{##3}% \fi }% \vskip\sf@bottom \egroup \@ifundefined{FBsc@max}{% }{% \addtocounter{FRobj}{-1}% \ifnum\c@FRobj=0\else \subfloatrowsep \fi }% \ifmaincaptiontop\else \global\advance\@nameuse{c@\@captype}\m@ne \fi \endgroup\ignorespaces}% % \expandafter\ifx\csname sf@@@subfloat\endcsname\nag@@original@@sf@@@subfloat % yup, that's it. \PackageInfo{nag}{OK, equivalent to subfig 1.3, redefining \@backslashchar sf@@@subfloat\@gobble}% \global\long\def\sf@@@subfloat##1[##2][##3]##4{% \@ifundefined{FBsc@max}{% }{% \FB@readaux{\let\FBsuboheight\relax}% }% \@tempcnta=\@ne \if@minipage \@tempcnta=\z@ \else\ifdim \lastskip=\z@ \else \@tempcnta=\tw@ \fi\fi \ifmaincaptiontop \sf@top=\sf@nearskip \sf@bottom=\sf@farskip \else \sf@top=\sf@farskip \sf@bottom=\sf@nearskip \fi \leavevmode \setbox\@tempboxa \hbox{% %% ulmi: new 2007/02/25: #4 may contain label command \csname nag@hascaptiontrue\endcsname %% and that was it. ##4}% \@tempdima=\wd\@tempboxa \@ifundefined{FBsc@max}{% }{% \global\advance\Xhsize-\wd\@tempboxa \dimen@=\ht\@tempboxa \advance\dimen@\dp\@tempboxa \ifdim\dimen@>\FBso@max \global\FBso@max\dimen@ \fi }% \vtop\bgroup %% ulmi: new 2007/05/10: #2, #3 may contain label command \csname nag@hascaptiontrue\endcsname %% and that was it. \vbox\bgroup \ifcase\@tempcnta \@minipagefalse \or \vskip\sf@top \or \ifdim \lastskip=\z@ \else \@tempskipb\sf@top\relax\@xaddvskip \fi \fi \sf@ifpositiontop{% \ifx \@empty##3\relax \else \sf@subcaption{##1}{##2}{##3}% \vskip\sf@capskip \vskip\sf@captopadj \fi\egroup \hrule width0pt height0pt depth0pt \box\@tempboxa }{% \@ifundefined{FBsc@max}{% \box\@tempboxa }{% \ifx\FBsuboheight\relax \box\@tempboxa \else \vbox to \FBsuboheight{\FBafil\box\@tempboxa\FBbfil}% \fi}% \egroup \ifx \@empty##3\relax \else \vskip\sf@capskip \hrule width0pt height0pt depth0pt \sf@subcaption{##1}{##2}{##3}% \fi }% \vskip\sf@bottom \egroup \@ifundefined{FBsc@max}{% }{% \addtocounter{FRobj}{-1}% \ifnum\c@FRobj=0\else \subfloatrowsep \fi }% \ifmaincaptiontop\else \global\advance\@nameuse{c@\@captype}\m@ne \fi \endgroup\ignorespaces}% \else \PackageInfo{nag}{Not redefining sf@@@subfloat, it looks odd\@gobble} \fi } % \end{macrocode} % % \subsection{The \pkg{float} package} % Sorry, there is no way for \pkg{nag} to automatically add new % float types to check them for captions. However, since v0.52, % there is an user-level command |\NagDeclareFloat| that will do % the bookkeeping for you, i.e. after your call to |\newfloat|, you % call |\NagDeclareFloat| with the first argument to |\newfloat|. % \changes{0.52}{2007/02/25}{Command NagDeclareFloat added} % \begin{macrocode} \newcommand*\NagDeclareFloat[1]{\g@addto@macro\nag@floats{,#1}} % \end{macrocode} % % \subsection{The \pkg{topcapt} package and the \pkg{subfig} package} % nagdemo exhibits an error when topcapt and subfig are used % together, i.e. \pkg{subfig} thinks the caption has not been % stepped already. This is not a bug in \pkg{nag}. % % \subsection{The \pkg{rotating} package} % \pkg{rotating} uses \cmd{\centerline} to place rotated floats. As % far as I can see, the usage is legitimate there, and using % \cmd{\centering} instead would change behaviour when the float's % dimension are larger than the text body. (Currently, the height % of the figure may exceed \cmd{\textwidth} without warning.) If this % bothers you, go read the warning on p.~\pageref{disclaimer} again. % % % \section{Loading extensions} % Finally, we deal with package options. % This is simple: just try to input appropriate nag files. % \changes{0.4}{2006/04/19}{config file names changed to free extension} % \begin{macrocode} \DeclareOption*{% \InputIfFileExists{nag-\CurrentOption.cfg}{% \PackageInfo{nag}{% Loaded nag-\CurrentOption.cfg } }{% \InputIfFileExists{\CurrentOption.nag}{% \PackageWarningNoLine{nag}{% Loaded old-style config file \CurrentOption.nag.\MessageBreak Consider renaming the file to nag-\CurrentOption.cfg }% }{% \PackageWarningNoLine{nag}{Required ruleset \CurrentOption, and it wasn't there} }% } } \ProcessOptions* % \end{macrocode} % % \PrintChanges %\PrintIndex %\Finale %\iffalse %%X Local Variables: %%X mode: latex %%X End: %\fi