diff options
author | Karl Berry <karl@freefriends.org> | 2009-02-26 00:49:14 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-02-26 00:49:14 +0000 |
commit | ddbbbe630665e57743e59ca5df71b2d054bd5d81 (patch) | |
tree | 760ddab647b788ce4dd070cea41c3a926720ba98 /Master/texmf-dist | |
parent | d1dd837a14e1be294dc54fc334a94e2c1a1dfffd (diff) |
new latex package silence (24feb09)
git-svn-id: svn://tug.org/texlive/trunk@12234 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/latex/silence/README | 15 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/silence/silence-doc.pdf | bin | 0 -> 256188 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/silence/silence-doc.dtx | 1854 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/silence/silence.ins | 31 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/silence/silence.sty | 652 |
5 files changed, 2552 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/silence/README b/Master/texmf-dist/doc/latex/silence/README new file mode 100644 index 00000000000..06919d397ae --- /dev/null +++ b/Master/texmf-dist/doc/latex/silence/README @@ -0,0 +1,15 @@ +This is the file README for silence.sty. You'll find complete documentation in silence-doc.pdf. + +This package allows you to filter out error messages and warnings sent by LaTeX, +packages and classes. + + +To produce the documentation: run LaTeX on silence-doc.dtx. +To produce the .sty file: run LaTeX on silence.ins. + + +Licensing of this package is covered by LPPL. + +Any reaction is welcome: zappathustra@free.fr + +Paul Isambert diff --git a/Master/texmf-dist/doc/latex/silence/silence-doc.pdf b/Master/texmf-dist/doc/latex/silence/silence-doc.pdf Binary files differnew file mode 100644 index 00000000000..98bc5163c99 --- /dev/null +++ b/Master/texmf-dist/doc/latex/silence/silence-doc.pdf diff --git a/Master/texmf-dist/source/latex/silence/silence-doc.dtx b/Master/texmf-dist/source/latex/silence/silence-doc.dtx new file mode 100644 index 00000000000..2d8dcaa5cb6 --- /dev/null +++ b/Master/texmf-dist/source/latex/silence/silence-doc.dtx @@ -0,0 +1,1854 @@ +% \iffalse meta-comment +% ****************************************************************************** +% ****************************************************************************** +% ** ** +% ** silence v.1.1 by Paul Isambert ** +% ** See the documentation for a comment on the implementation. ** +% ** ** +% ** This set of macros is published under the LaTeX Project Public License: ** +% ** ** +% ** Do whatever you want to that software, ** +% ** but if you modify it, change its name to avoid confusion, ** +% ** and if you copy part of the code please mention where it comes from. ** +% ** ** +% ** Comments, suggestions and bugs: ** +% ** ** +% ** zappathustra@free.fr ** +% ** ** +% ** http://paulisambert.free.fr/ ** +% ** ** +% ** Enjoy! ** +% ** ** +% ****************************************************************************** +% ****************************************************************************** +% \fi + +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e} +%<package>\ProvidesPackage{silence}[2009/02/20 v1.1 Selective filtering of warnings and error messages] +%<*driver> +\documentclass[a4paper]{ltxdoc} +\usepackage[T1]{fontenc} +\usepackage{silence} +\usepackage[left=5cm,textwidth=14cm,textheight=23cm]{geometry} +\RecordChanges +\begin{document} +\DocInput{silence-doc.dtx} +\end{document} +%</driver> +% \fi +% +% \def\vbskip{\vskip.5em\noindent} +% \WarningFilter{latex}{Marginpar on page} +% \MakeShortVerb{"} +% \def\vbopt#1{\noindent\llap{\textbf{#1}\enspace}\ignorespaces} +% \GetFileInfo{silence.sty} +% \title{Filtering messages with "silence"\\\Large\fileversion} +% \date{\filedate} +% \author{Paul Isambert\\"zappathustra@free.fr"} +% +% \maketitle +% \vskip1em +% \bgroup +% \raggedleft +% \small +% \textit{`Errare humanum est, perseverare diabolicum'}\\ Proverb (attributed to Seneca) +% +% \textit{`Marginpar on page 3 moved.'}\\\LaTeX +% +% \egroup +% \vskip3em +% +%\begin{abstract} +%This package is designed to filter out unwanted warnings +%and error messages. Entire packages (including \LaTeX) +%can be censored, but very specific messages can be +%targeted too. \TeX's messages are left untouched. +%\end{abstract} +% +% \tableofcontents +% +%\section{Introduction} +%When working with \LaTeX, messages are utterly important. +% +%Ok, this was the well-behaved \LaTeX\ user's offering to +%the gods. Now, the fact is, when processing long +%documents, repeated messages can really get boring, +%especially when there's nothing you can do about them. +%For instance, everybody knows the following: +%\vbskip +%\hfil\emph{Marginpar on page \emph{x} moved.} +%\vbskip +%When you encounter that message, it means that you +%have to keep in mind for the next compilations that +%`there is a warning that I can ignore,' which sounds +%pretty paradoxical. When your +%document is 5 pages long, it doesn't matter, but when +%you're typesetting a book-length text, it's different, because +%you can have tens of such messages. And if you're +%hacking around, error messages might also appear +%that you don't want to consider. This package is +%meant to filter out those unwanted messages. +% +%You probably know all there is to know about +%warnings and errors, in which case you may want +%to skip this paragraph. If you don't, here's some +%information. When \LaTeX\ processes your document, +%it produces error messages and warnings, and packages +%and the class you're using do too. Errors generally +%refer to wrong operations such that the desired result +%won't be attained, while warnings usually inform you +%that there might be unexpected but benign modifications. +%Those messages are sent to the "log" file along with +%other bits of information. You're probably using +%a \LaTeX-oriented text editor to create your document +%and at the end of a compilation, it certainly gives you +%the number of errors and warnings encountered. +%Hopefully, your editor also has a facility to browse +%errors and warnings. With "silence", unwanted messages +%won't appear anymore. +% +%Those messages always have one of the following structures: +% +%\vbskip +%"Package" \meta{Name of the package} "Error:" \meta{message text} +%\vbskip +%or +%\vbskip +%"Class" \meta{Name of the class} "Error:" \meta{message text} +%\vbskip +%or +%\vbskip +%"LaTeX Error:" \meta{message text} +%\vbskip +%Replace \emph{Error} with \emph{Warning} and you have +%warnings. The important part for "silence" is \meta{Name of the +%package} or \meta{Name of the class}, because the information +%is needed when filtering messages. In case of a \LaTeX\ message, +%\meta{Name of the package} is supposed to be "latex". For filters, +%\meta{message text} will be crucial too. +% +%If a message doesn't begin as above, but displays its text +%immediately, then it has been sent by \TeX; "silence" cannot +%filter it out, and anyway it would probably be a very bad +%idea. For instance, there's nothing you can do about +%something like: +% +%\vbskip +%"Missing number, treated as zero." +%\vbskip +%and the only thing you want to do is correct your mistake. +% +%Another very bad idea is to forget the following: +%\emph{"silence" does not fix anything}. +% +% +% +%\section{Usage} +%\subsection{Calling the package} +% +%The package may be called as any other +%package with: +% +%\vbskip +%"\usepackage"\oarg{options}"{silence}" +%\vbskip +%and as any other package it will be effective only +%after it has been called, which means that messages +%issued before will not be filtered. So put it at the +%very beginning of your preamble. However, if you also +%want to catch a message issued by the class when it +%is specified with "\documentclass", you can't say +% +%\vbskip +%"\usepackage"\oarg{options}"{silence}"\\ +%\meta{filters}\\ +%"\documentclass{article}" +%\vbskip +%but instead +% +%\vbskip +%"\RequirePackage"\oarg{options}"{silence}"\\ +%\meta{filters}\\ +%"\documentclass{article}" +%\vbskip +%because "\usepackage" is not allowed before +%"\documentclass". This way, you can filter for +%instance a warning issued by the "memoir" class +%according to which you don't have "ifxetex", although +%you have it... +% +% +% +% +%\subsection{The brutal way} +% +%\DescribeMacro{\WarningsOff\oarg{list}}\DescribeMacro{\WarningsOff*} +%\DescribeMacro{\ErrorsOff\oarg{list}}\DescribeMacro{\ErrorsOff*} +%There is one very simple and very effective way to +%get rid of messages: "\WarningsOff" and "\ErrorsOff". In their +%starred versions, no warning or error will make it to your log +%file. Without a star, and without argument either, they filter +%out all messages except \LaTeX's. Finally, you can specify +%a list of comma-separated packages whose messages you don't want. +% For that purpose, \LaTeX\ is considered a package whose name is "latex". +%For instance "\WarningsOff[superpack,packex]" will remove all +%warnings issued by the "superpack" and "packex" packages. Messages +%issued by classes are also accessible in the same way, so to +%avoid the warning mentioned above, you can say: +% +%\vbskip +%"\RequirePackage"\oarg{options}"{silence}"\\ +%"\WarningsOff[memoir]"\\ +%"\documentclass{memoir}" +%\vbskip% +%If you want to filter out \LaTeX's warnings only, you can +%say "\WarningsOff[latex]". Note that issuing "\WarningsOff[mypack]" +%after "\WarningsOff", for instance, is useless, because all +%warnings are already filtered out. But this won't be mentioned to you. +%And "silence" won't check either whether a censored package exists +%or not. So if you say "\WarningsOff[mypak]" and mean "\WarningsOff[mypack]", +%this will go unnoticed. +% +%\DescribeMacro{\WarningsOn\oarg{list}}\DescribeMacro{\ErrorsOn\oarg{list}} +%These commands allow messages to be output again. If there is no \meta{list}, +%all packages are affected, otherwise only specified packages are affected. +%So, for instance +% +%\vbskip +%"\WarningsOff"\\ +%"Blah blah blah..."\\ +%"\WarningsOn[superpack,packex]"\\ +%"Blah blah blah..." +%\vbskip +%will have all warnings turned off, except those issued by \LaTeX\ (because +%"\WarningsOff" has no star) and by "superpack" and "packex" in the second +%part of the document. +% +%Note that the command described in this section are independant of the +%filters described in the following one, and vice-versa. That is, +%"\WarningsOn" has no effect on the filters, and if you design a filter +%to avoid a specific message issued by, say, "superpack", "\WarningsOn[superpack]" +%will not deactivate that filter and that one message will still be +%filtered out. +% +% +% +% +% +% +%\subsection{The exquisite way} +% +%Turning off all messages might be enough in many cases, especially if +%you turn them on again rapidly, but it is a blunt approach and it can lead +%to unwanted results. So "silence" allows you to create filters to target +%specific messages. +% +%\DescribeMacro{\WarningFilter\oarg{family}\\\marg{package}\marg{message}} +%\DescribeMacro{\ErrorFilter\oarg{family}\\\marg{package}\marg{message}} +%These commands will filter out messages issued by \meta{package} and beginning with \meta{message}. +%The optional \meta{family} specification is used to create groups of filters +%that will be (de)activated together. If there is no family, the filter will be immediately +%active and you won't be able to turn if off. So, for instance: +% +%\vbskip +%"\WarningFilter{latex}{Marginpar on page}" +%\vbskip +%will filter out all \LaTeX\ warnings beginning with `"Marginpar on page"'. On the other +%hand, +% +%\vbskip +%"\WarningFilter[myfam]{latex}{Marginpar on page}" +%\vbskip +%will filter out those same warnings if and only if "myfam" filters are active (but +%see the "immediate" package option below). +% +%You can be quite specific with the text of the message. For instance, +% +%\vbskip +%"\WarningFilter{latex}{Marginpar on page 2 moved}" +%\vbskip +%will filter out marginpar warnings issued on page 2. +% +%In this version (contrary to the starred version below), \meta{message} should +%reproduce the (beginning of) the displayed message. For instance, suppose +%that you have the following error message: +% +%\vbskip +%"Package superpack Error: The command \foo should not be used here." +%\vbskip +%To filter it out, you can simply say: +%\vbskip +%"\ErrorFilter"\oarg{family}"{superpack}{The command \foo should not}" +%\vbskip +%although you might know that "superpack" didn't produce it so easily, +%but instead must have said something like: +%\vbskip +%"\PackageError{superpack}{The command \string\foo\space should not be used here}{}" +%\vbskip +%Here, you don't have to know how the message was produced, but simply what +%it looks like. The starred versions of those commands below work differently. +% +%\DescribeMacro{\ActivateWarningFilters\\\oarg{list}} +%\DescribeMacro{\ActivateErrorFilters\\\oarg{list}} +%These macros activate the filters which belong to the families specified +%in \meta{list}. If there is no such list, all filters are activated. Indeed, +%unless the "immediate" option is turned on (see below), filters are not active +%when created, except those that don't belong to a family. Note that \meta{list} +%contains the name of the family specified in "\WarningFilter"\oarg{family}\marg{package}\marg{message} +%(and similarly for "\ErrorFilter") and not the name of the package (i.e. \meta{package}), +%although you can freely use the same name for both. So for instance: +% +%\vbskip +%"\WarningFilter[myfam]{packex}{You can't do that}"\\ +%"\ActivateWarningFilters[packex]" +%\vbskip +%will not activate the desired filter, but instead will try to activate the filters +%belonging to the "packex" family. If this family doesn't exist, you won't be warned.\footnote{You +%won't be warned either that the \texttt{packex} family will really be active, which +%means that if you create (warning) filters with that family name afterwards, they will +%take effect immediately, even if you're not in \texttt{immediate} mode.} +%So the proper way instead is: +%\vbskip +%"\WarningFilter[myfam]{packex}{You can't do that}"\\ +%"\ActivateWarningFilters[myfam]" +%\vbskip +%Finally, if a filter is created while its family is active, it will be active itself +%from its creation. +% +%\DescribeMacro{\DeactivateWarningFilters\\\oarg{list}} +%\DescribeMacro{\DeactivateErrorFilters\\\oarg{list}} +%These are self-explanatory. Once again, if there is no list, all filters are +%deactivated. Note that the "immediate" option implicitly turns on families +%associated with the filters that are created, so: +% +%\vbskip +%"\WarningFilter[myfam]{packex}{You can't do that}"\\ +%"\DeactivateWarningFilters[myfam]"\\ +%"\WarningFilter[myfam]{superpack}{This is very bad}" +%\vbskip +%will make all filters belonging to "myfam" active if "immediate" is on. +%In this example, both filters will be active, although one might have +%intended only the second one to be. +% +%\DescribeMacro{\ActivateFilters\oarg{list}} +%\DescribeMacro{\DeactivateFilters\oarg{list}} +%I bet you know what I'm going to say. These two macros activate +%or deactivate all filters, or all filters belonging +%to the specified families in case there's an argument. So +%you can create error filters and warning filters with the +%same family name and control them all at once. Isn't it +%amazing? Note that, just like above, "\ActivateFilters[myfam]" +%won't complain if there's no "myfam" family, or if there's +%just a warning family and no error family, and so on and +%so forth. +% +%\DescribeMacro{\WarningFilter*\oarg{family}\\\marg{name}\marg{message}} +%\DescribeMacro{\ErrorFilter*\oarg{family}\\\marg{name}\marg{message}} +%These are the same as the starless versions above, except that they +%target the message not as it appears in the log file but as it was produced. +%For instance, suppose you have an undefined citation, that is you +%wrote "\cite{Spinoza1677}" and \LaTeX\ complains as follows: +% +% +%\vbskip +%\bgroup +%\hfuzz=1cm +%"LaTeX Warning: Citation `Spinoza1677' on page 4 undefined on input line 320." +% +%\egroup +%\vbskip +%You know you have to bring your bibliography up to date, but right now you're +%working on a terrific idea and you don't have time to waste. So you say: +% +%\vbskip +%"\WarningFilter{latex}{Citation `Spinoza1677'}" +%\vbskip +%and everything's ok (since you've turned on the "save" option---see below---you +%will not forget to fix that reference). So you go on but then, as you're +%trying to link string theory with german philology, you stumble on that +%paper with bold new ideas and tens of fascinating references that you can't +%read but definitely have to cite. As expected, \LaTeX\ will start whining, +%because it doesn't like undefined citations. How are you going to shut it up? +%You might try +% +%\vbskip +%"\WarningFilter{latex}{Citation}" +%\vbskip +%but that's dangerous because all warnings beginning with "Citation" will +%be filtered out, and maybe there are other types of messages which begin with +%"Citation" and that you don't want to avoid. So the solution is "\WarningFilter*". +%Indeed, you can say: +% +%\vbskip +%"\WarningFilter*{latex}{Citation `\@citeb' on page \thepage \space undefined}" +%\vbskip +%That is, you target the way the message was produced instead of the way it appears. +%Of course, you have to know how the message was produced, but that's easy to figure +%out. In case of a \LaTeX\ message, just check the source (available on the web). In +%case the message was issued by a package or a class, just give a look at the +%corresponding files. +% +%As a rule of thumb, remember that a command that appears verbatim in the message +%was probably prefixed with "\protect", "\noexpand" or "\string", and you can try +%them all. Commands that are expanded are likely to be followed by "\space", to avoid unwanted gobbling. +%So if a message says `"You can't use \foo here"', it is likely to be produced +%with `"You can't use \protect\foo here"'. +% +%Here's a comparison of starred and starless filters: +% +%\vbskip +%"\WarningFilter{latex}{Marginpar on page 3 moved}" will filter off marginpar +%warnings concerning page 3. +%\vbskip +%"\WarningFilter{latex}{Marginpar on page \thepage\space moved}" will be inefficient +%because it will search messages that actually look like the specified text. +%\vbskip +%"\WarningFilter*{latex}{Marginpar on page \thepage\space moved}" will filter off +%all marginpar warnings. +%\vbskip +%"\WarningFilter*{latex}{Marginpar on page 3 moved}" will miss everything because when +%the the warning is produced the page number is not specified. +% +%\DescribeMacro{\SafeMode}\DescribeMacro{\BoldMode} +%As you might have guessed, evaluating messages as they appear means expanding them. +%Normally, this should be harmless, but one never knows. So these two commands allow +%you to turn that process on and off. When you say "\SafeMode", messages are not +%expanded. In that case, starless filters might miss their goal if the message +%contains expanded material. Starred filters are unaffected. So if you encounter +%an avalanche of unexplained error messages, just try some "\SafeMode". "\BoldMode" +%is used to switch back to the default mode. +% +%This expansion process concerns messages, not filters. That is, there is no need +%to protect your filter definitions with "\SafeMode". Instead, use this command when +%you suspect that a message is being sent and "silence" gets everything wrong. Use +%"\BoldMode" to switch back to normal when messages are not troublesome anymore. +%Here's an example: +% +%\vbskip +%"\WarningFilter{latex}{Marginpar on page 3 moved}"\\ +%"\WarningFilter*{latex}{Citation `\@citeb' undefined}"\\ +%"..."\\ +%"\SafeMode"\\ +%"..." +%\bgroup\ttfamily\itshape\obeylines\parindent0pt% +%Here a strange message is being sent by the \emph{strangex} package. +%If \upshape"\SafeMode"\itshape\ was not active, we would be in big trouble. +%The \emph{Marginpar} warnings all go through, because our starless filter +%is too specific. Fortunately, the \emph{Citation} warnings are correctly +%avoided. +%"..." +%\egroup +%\noindent"\BoldMode"\\ +%"..."\\ +%\texttt{\emph{Everything is back to normal.}} +%\vbskip +% +% +%\section{Package options} +%Here are the options that may be loaded with the package: +% +%\vbskip +%\vbopt{debrief} At the end of the document, "silence" will output a +%warning saying how many messages were issued during the compilation +%and how many were filtered out. This warning will not appear if +%no message was output or if none were filtered out. +% +%\vbopt{immediate} Makes filters active as soon as they are created. +%This does not affect filters created without a family, since they +%always behave so. If a filter is created with family "myfam", and +%if that family has been previously deactivated, it will be reactivated. +% +%\vbopt{safe} Makes safe mode the default mode. "\BoldMode" and "\SafeMode" +%are still available. +% +%\vbopt{save} Messages that were filtered out are written to an +%external file called "jobname.sil". +% +%\vbopt{saveall} All messages, including those that were left untouched, +%are written to "jobname.sil". +% +%\vbopt{showwarnings} Warnings are left untouched. That is, "silence"'s +%commands become harmless. Note that warnings are not written to +%"jobname.sil", even if the "saveall" option is loaded. This command +%is useful if you want to recompile your document as usual. +% +%\vbopt{showerrors} Same as "showwarnings" for errors. +% +% +% +%\section{It doesn't work!} +%Messages can be tricky. This package was originally designed to take +%care of marginpar warnings, and I wanted to do something like: +% +%\vbskip +%"\WarningsOff*"\\ +%"\marginpar{A marginpar that will move}"\\ +%"\WarningsOn" +%\vbskip +%Unfortunately, this doesn't work. Indeed, marginpar warnings are not +%issued when the "\marginpar" command is used but at the output routine, +%that is when \LaTeX\ builds the page, which happens at some interesting +%breakpoint that you're not supposed to know. That's the reason why +%those messages must be filtered out with warnings that are always +%active. Of course, this means that you can't filter out just one +%particular marginpar warning, unless it's the only one on its page. +% +% +%Now, messages aren't always what they seem to be. More precisely, +%two attributes do not really belong to them: the final full stop +%and the line number (only for some warnings). For instance, the following +%message \emph{does not} containt a full stop: +%\vbskip +%"Package packex Error: You can't do that." +%\vbskip +%The full stop is added by \LaTeX. So +%\vbskip +%"\ErrorFilter{packex}{You can't do that.}" +%\vbskip +%won't do. You have to remove the stop. This goes the same with the +%phrase `\texttt{on input line} \meta{number}.' (including the stop once +%again). That is, the message +%\vbskip +%"Package superpack Warning: Something is wrong on input line 352." +%\vbskip +%was actually produced with +%\vbskip +%"\PackageWarning{superpack}{Something is wrong}" +%\vbskip +%The end of it was added by \LaTeX. You know what you have to do. +%Unfortunately, this means that warnings can't be filtered according +%to the line they refer to. +% +%Another difficulty concerns line breaking in messages. If a new line +%begins in a message, it was either explicitely created or it's a single +%line wrapped by your text editor. When properly written, messages use +%\LaTeX's "\MessageBreak" command to create new lines, which \LaTeX\ +%formats as a nicely indented line with the name of the package at the +%beginning, between parentheses. So if you encounter such a display, +%you know that there's something more behind the scene. You have two +%solutions: either you make the text of your filter shorter than +%the first line, which in most cases will be accurate enough, or +%you use a starred filter and explicitely write "\MessageBreak". +%Unfortunately, you can't use "\MessageBreak" in a starless filter. +%Note that some stupid people (including the author of this package) +%sometimes use "^^J" instead of "\MessageBreak", which is a \TeX\ +%construct to create a new line. In that case, the line break +%will be indistinguishable from a single line wrapped by your text +%editor (although no wrapping occur in the log file). +% +%The most efficient filters are the starred ones (unless +%you're aiming at a specific value for a variable) whose text has simply +%been pasted from the source. E.g., if "superpack" tells you: +% +%\vbskip +%"Package superpack Error: You can't use \@terrific@command in"\\ +%"(superpack) a \@fantastic@environment, because"\\ +%"(superpack) unbelievable@parameter is off". +%\vbskip +%this was probably produced with: +%\vbskip +%"\PackageError{superpack}{"\\ +%" You can't use \protect\@terrific@command in\MessageBreak"\\ +%" a \protect\@fantastic@environment, because\MessageBreak"\\ +%" \superparameter\space is off}"\\ +%" {}" +%\vbskip +%with "\superparameter" "\def"ined to "unbelievable@parameter" +%beforehand. So the simplest way to filter out such a message +%is to open "superpack.sty", look for it, and copy it as is +%in a starred filter. +% +% +%There remains one problematic case, if a primitive +%control sequence appears in the message to be avoided. +%Imagine for instance that a package sends the warning +%`"You can't use \def here"'. It will not be reachable +%with a starless filter, because the package may have +%said "\def" without any prefix, since primitive commands +%can be used as such in messages, where they appear verbatim. +%On the other hand, when you create a starless filter with +%a command in it, "silence" considers this command simply as a string +%of characters beginning with a backslash devoid of its +%usual `escapeness'---as are control sequences prefixed +%with "\protect", "\string" and "\noexpand" in messages. So +%"\def" won't be reached. A starred filter might do, but +%in this case you shouldn't prefix "\def" with any of the +%three commands just mentioned. Now if "\def" is the result +%of an expansion, you'll be forced to rely on the previous +%techniques. Fortunately, this is very rare. +% +%Now, in case there's a message you really can't reach, although +%you pasted it in your filter, just let me know: it's an opportunity +%to refine "silence". +% +% +% +% +% +% +% \section{Implementation} +% \subsection{Basic definitions} +% \MacrocodeTopsep.5em +% \def\macskip{\par\vskip-17.7pt\vskip0cm} +% \let\sldescribemacro\DescribeMacro +% \def\DescribeMacro{\noindent\sldescribemacro} +% The options only turn on some conditionals, except "save" and +% "saveall", which set the count "\sl@save", to be used +% in a "\ifcase" statement. +% \begin{macrocode} +\makeatletter + +\newcount\sl@Save +\newif\ifsl@Debrief +\newif\ifsl@ShowWarnings +\newif\ifsl@ShowErrors +\newif\ifsl@Immediate +\newif\ifsl@SafeMode + +\DeclareOption{debrief}{\sl@Debrieftrue} +\DeclareOption{immediate}{\sl@Immediatetrue} +\DeclareOption{safe}{\sl@SafeModetrue} +\DeclareOption{save}{\sl@Save1% +\newwrite\sl@Write% +\immediate\openout\sl@Write=\jobname.sil} +\DeclareOption{saveall}{\sl@Save2% +\newwrite\sl@Write% +\immediate\openout\sl@Write=\jobname.sil} +\DeclareOption{showwarnings}{\sl@ShowWarningstrue} +\DeclareOption{showerrors}{\sl@ShowErrorstrue} +\ProcessOptions\relax +% \end{macrocode} + +% Here are the counts, token lists and conditionals, that +% will be used by warnings and errors. +% \begin{macrocode} +\newcount\sl@StateNumber +\newcount\sl@MessageCount +\newcount\sl@Casualties + +\newtoks\sl@Filter +\newtoks\sl@Message +\newtoks\sl@UnexpandedMessage +\newtoks\sl@Mess@ge + +\newif\ifsl@Check +\newif\ifsl@Belong +\newif\ifsl@KillMessage +\newif\ifsl@SafeTest +% \end{macrocode} + +% And here are some keywords and further definitions. +% "\sl@PackageName" is used to identify the name of the +% package, but in case "\GenericError" or "\GenericWarning" +% were directly used, it would be undefined (or defined +% with the name of the last package that issued a message), +% which would lead to some trouble, hence its definition here. +% \begin{macrocode} +\def\sl@end{sl@end} +\def\sl@latex{latex} +\def\sl@Terminator{£} +\gdef\sl@active{active} +\gdef\sl@safe{safe} +\gdef\sl@PackageName{NoPackage} +\def\SafeMode{\global\sl@SafeModetrue} +\def\BoldMode{\global\sl@SafeModefalse} +\def\sl@Gobble#1sl@end,{} +% \end{macrocode} + +% \subsection{Warnings} +% Now these are the counts, token lists, conditionals and +% keywords specific to warnings. "sl@family" is +% actually the family of those familyless filters. It +% is made active as wanted. +% \begin{macrocode} +\newcount\sl@WarningCount +\newcount\sl@WarningNumber +\newcount\sl@WarningCasualties + +\newtoks\sl@TempBOW +\newtoks\sl@BankOfWarnings + +\newif\ifsl@WarningsOff +\newif\ifsl@NoLine + +\expandafter\gdef\csname sl@family:WarningState\endcsname{active} +\def\sl@WarningNames{} +\def\sl@UnwantedWarnings{} +\def\sl@ProtectedWarnings{} +% \end{macrocode} + +% \subsubsection{Brutal commands} +% \DescribeMacro{\WarningsOn} +% The basic mechanism behind "\WarningsOn" and "\WarningsOff" +% is a conditional, namely "\ifsl@WarningsOff". When a warning is sent, +% "silence" checks the value of this conditional and acts +% accordingly: if it is set to "true", then the warning is +% filtered out unless it belongs to the "\sl@ProtectedWarnings" +% list; if it is set to "false", the warning is output unless +% it belongs to the "\sl@UnwantedWarnings" list. +% +% Without argument, "\WarningsOn" empties both lists and sets +% this conditional to "false". (Emptying "\sl@ProtectedWarnings" +% is useless but it keeps the list clean.) If it has an argument, +% its behavior depends on the conditional; if it is set to +% "true", the argument is added to "\sl@ProtectedWarnings"; +% otherwise, it is removed from "\sl@UnwantedWarnings". +% +% \begin{macrocode} +\def\WarningsOn{% + \@ifnextchar[% + {\ifsl@WarningsOff% + \def\sl@next{\sl@Add\sl@ProtectedWarnings}% + \else% + \def\sl@next{\sl@Remove\sl@UnwantedWarnings}% + \fi\sl@next}% + {\global\sl@WarningsOfffalse% + \gdef\sl@ProtectedWarnings{}% + \gdef\sl@UnwantedWarnings{}}} +% \end{macrocode} + +% \DescribeMacro{\WarningsOff} +% "\WarningsOff" does the same as "\WarningsOn", but in +% the other way. If it has no star and no argument, +% "\sl@ProtectedWarnings" is overwritten with only +% "latex" in it. +% +% \begin{macrocode} +\def\WarningsOff{% + \@ifstar% + {\global\sl@WarningsOfftrue + \gdef\sl@UnwantedWarnings{}% + \gdef\sl@ProtectedWarnings{}}% + {\@ifnextchar[{% + \ifsl@WarningsOff% + \def\sl@next{\sl@Remove\sl@ProtectedWarnings}% + \else% + \def\sl@next{\sl@Add\sl@UnwantedWarnings}% + \fi\sl@next}% + {\global\sl@WarningsOfftrue% + \gdef\sl@UnwantedWarnings{}% + \gdef\sl@ProtectedWarnings{latex,}}}} +% \end{macrocode} +% +% Note that the "\WarningsOn" and "\WarningsOff" +% don't really take any argument. If an opening bracket is +% present, they launch "\sl@Add" or "\sl@Remove" on the +% adequate list. + +% \DescribeMacro{\sl@Add} +% "\sl@Add" is no more than an "\xdef" of the list +% on itself, plus the new item. +% +% \begin{macrocode} +\def\sl@Add#1[#2]{% + \xdef#1{#1#2,}} +% \end{macrocode} + +% \DescribeMacro{\sl@Remove} +% "\sl@Remove" is slightly more complicated. It stores +% the items to be removed and then +% launches the recursive "\sl@@Remove" on the expanded list, +% with a terminator to stop it. +% When "\sl@@Remove" has done its job, the list will +% be "\let" to the new one. +% +% \begin{macrocode} +\def\sl@Remove#1[#2]{% + \def\sl@Items{#2} + \def\sl@TempNewList{}% + \expandafter\sl@@Remove#1sl@end,% + \let#1\sl@TempNewList} +% \end{macrocode} + +% \DescribeMacro{\sl@@Remove} +% This macro takes each element of the list to +% be updated, checks it against the items to be +% removed, and builds a new list containing the element +% currently tested if and only if it has not been +% matched with items to be removed. +% +% First, we check the current element of the list, +% and if it's the terminator we end recursion. +% +% \begin{macrocode} +\def\sl@@Remove#1,{% + \def\sl@Tempa{#1}% + \ifx\sl@Tempa\sl@end% + \let\sl@next\relax% +% \end{macrocode} +% +% \noindent Otherwise, we launch "\sl@ListCheck" on the element. +% +% \begin{macrocode} + \else% + \sl@Checkfalse% + \expandafter\sl@ListCheck\sl@Items,sl@end,% +% \end{macrocode} +% +% \noindent If the check is positive, we do nothing. If not, +% we add the element to "\sl@TempNewList", which is +% itself repeated to keep the former elements. +% +% \begin{macrocode} + \ifsl@Check% + \else% + \xdef\sl@TempNewList{\sl@TempNewList#1,}% + \fi% + \let\sl@next\sl@@Remove% + \fi\sl@next}% +% \end{macrocode} + +% \DescribeMacro{\sl@ListCheck} +% Here's the internal checking mechanism. It takes an argument +% (from the expansion of "\sl@Items" above) and compares +% it to the element under scrutiny. In case they match, +% the proper conditional is turned to "true", and we +% launch "\sl@Gobble" to discard remaining items. Otherwise, +% we proceed to the next item. +% +% First we check for the terminator, as usual, and +% the recursion is ended in case we find it. +% +% \begin{macrocode} +\def\sl@ListCheck#1,{% + \def\sl@Tempb{#1}% + \ifx\sl@Tempb\sl@end% + \let\sl@next\relax% +% \end{macrocode} +% +% \noindent If the item is not the terminator, +% we compare it to the current element. If they +% match, we confirm the test and gobble. +% +% \begin{macrocode} + \else% + \ifx\sl@Tempa\sl@Tempb% + \sl@Checktrue + \let\sl@next\sl@Gobble% +% \end{macrocode} +% +% \noindent Otherwise we repeat. +% +% \begin{macrocode} + \else% + \let\sl@next\sl@ListCheck% + \fi% + \fi\sl@next} +% \end{macrocode} + +% \subsubsection{Filters} +% \DescribeMacro{\WarningFilter} +% Let's now turn to filters. +% When created, each warning filter is associated +% with a "\sl@WarningNumber" to retrieve it and to specify its +% status. In case of "\WarningFilter*", this status, referred to +% with "\csname\the\sl@WarningNumber:WarningMode\endcsname" (i.e. +% "\"\meta{number}":WarningMode", where \meta{number} is the unique +% number associated with the filter), is +% set to ``"safe"''. Otherwise, we don't bother to define it, +% because when evaluated the above command will then be +% equal to "\relax" (as are all undefined commands called with +% "\csname... \endcsname"). +% This will be checked in due time to know whether +% the expanded or the unexpanded version of the target message +% must be tested. +% +% \begin{macrocode} +\def\WarningFilter{% + \global\advance\sl@WarningNumber1% + \@ifstar% + {\expandafter\gdef\csname\the\sl@WarningNumber:WarningMode\endcsname{safe}% + \sl@WarningFilter}% + {\sl@WarningFilter}} +% \end{macrocode} + +% \DescribeMacro{\sl@WarningFilter} +% Once the star has been checked, we look for an optional argument. +% In case there is none, we assign the "sl@family" to the filter. +% +% \begin{macrocode} +\def\sl@WarningFilter{% + \@ifnextchar[% + {\sl@@WarningFilter}% + {\sl@@WarningFilter[sl@family]}} +% \end{macrocode} + +% \DescribeMacro{\sl@@WarningFilter} +% Here comes the big part. First, we update the list of +% filters associated with a package, stored in "\"\meta{package}"@WarningFilter". +% The list itself is a concatenation of comma-separated pairs of +% the form \meta{number}":sl@"\meta{family} referring to filters. +% When \meta{package} issues a warning, "silence" checks the filters +% contained in the associated list. \meta{number} is +% used to determine the "WarningMode" ("safe" or undefined, as noted above), so +% that the right test will be run, while \meta{family} is used +% to ensure that this family is active. +% +% First we update the list: +% +% \begin{macrocode} +\def\sl@@WarningFilter[#1]#2{% + \expandafter\ifx\csname #2@WarningFilter\endcsname\relax% + \expandafter\xdef\csname #2@WarningFilter\endcsname{\the\sl@WarningNumber:sl@#1}% + \else% + \expandafter\xdef\csname #2@WarningFilter\endcsname{% + \csname #2@WarningFilter\endcsname,\the\sl@WarningNumber:sl@#1}% + \fi% +% \end{macrocode} +% +% \noindent Now, if "\"\meta{family}":WarningState" is undefined, this means +% that this is the first time we encounter that family. So we store +% its name, which will be useful for "\ActivateWarningFilters" and +% its deactivating counterpart. +% +% \begin{macrocode} + \expandafter\ifx\csname #1:WarningState\endcsname\relax% + \sl@Add\sl@WarningNames[#1]% + \fi% +% \end{macrocode} +% +% \noindent Next, we check "WarningState" again; if it's not active, we change it, +% depending on whether we're in "immediate" mode or not. +% \begin{macrocode} + \expandafter\ifx\csname #1:WarningState\endcsname\sl@active% + \else% + \ifsl@Immediate% + \expandafter\gdef\csname #1:WarningState\endcsname{active}% + \else% + \expandafter\gdef\csname #1:WarningState\endcsname{inactive}% + \fi% + \fi% +% \end{macrocode} +% +% \noindent Finally, we prepare the storage of the filter's message. +% We open a group, and if the filter is starred, we turn "@" into +% a letter, so that it will be able to form macro names. +% If the filter has no star, we turn the escape character into +% a normal one, so that control sequences won't be formed. Messages +% will then be tested token by token, and if a message contains e.g. "\foo", +% then it has (most likely) been "\string"'ed, so it's really a sequence of characters +% with "\catcode" 12 (including the escape character) that the starless +% filter will match. +% \begin{macrocode} + \begingroup% + \expandafter\ifx\csname\the\sl@WarningNumber:WarningMode\endcsname\sl@safe% + \makeatletter% + \else% + \catcode`\\12\relax% + \fi% + \sl@AddToBankOfWarnings} +% \end{macrocode} + +% \DescribeMacro{\sl@AddToBankOfWarnings} +% Now we add the filter to the "\sl@BankOfWarnings" token list, +% delimited by "(:sl@"\meta{number}":)", where \meta{number} +% is the number assigned to it above. Thus, it might be easily +% retrieved. Following a technique explained by Victor Eijkhout +% in \emph{\TeX\ by Topic}, we make use of "\edef" to add an item +% to a token list. First, we store it in the temporary "\sl@TempBOW" +% token list. Then we "\edef" "\sl@act" such that its definition +% will be: +% +% \vbskip +% "\sl@BankOfWarnings{"\meta{previous content}"(:sl@"\meta{number}":)"\meta{filter}"(:sl@"\meta{number}":)}" +% \vbskip +% Thus, the "\sl@BankOfWarnings" token list will add the new filter +% to itself. This works because token lists prefixed with "\the" in an "\edef" +% expand to their content unexpanded, unlike normal macros. The macro +% is made "\long" just in case. +% +% \begin{macrocode} +\long\def\sl@AddToBankOfWarnings#1{% + \sl@TempBOW{#1}% + \edef\sl@act{% + \global\noexpand\sl@BankOfWarnings{% + \the\sl@BankOfWarnings% + (:sl@\the\sl@WarningNumber:)\the\sl@TempBOW(:sl@\the\sl@WarningNumber:)}}% + \sl@act% + \endgroup} +% \end{macrocode} + +% \DescribeMacro{\ActivateWarningFilters} +% \DescribeMacro{\DeactivateWarningFilters} +% This macro launches a recursive redefinition +% of its expanded argument, which is either a list +% defined by the user or the list containing +% all warning families (updated in "\WarningFilter" +% above). We set "\sl@StateNumber" to register +% what the redefinition should be: activate or deactivate "WarningState", +% or activate or deactivate "ErrorState". +% +% \begin{macrocode} +\def\ActivateWarningFilters{% + \sl@StateNumber0\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@WarningNames]}} + +\def\DeactivateWarningFilters{% + \sl@StateNumber1\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@WarningNames]}} +% \end{macrocode} + +% \DescribeMacro{\sl@ChangeState} +% \DescribeMacro{\sl@@ChangeState} +% "\sl@ChangeState" only calls "\sl@@ChangeState" on +% the expanded argument, adding a terminator. +% "\sl@@ChangeState" checks whether its argument +% is the terminator, in which case it stops, or else +% it sets its state to the appropriate value, depending +% on "\sl@StateNumber" +% +% \begin{macrocode} +\def\sl@ChangeState[#1]{% + \expandafter\sl@@ChangeState#1,sl@end,} + +\def\sl@@ChangeState#1,{% + \def\sl@Tempa{#1}% + \ifx\sl@Tempa\sl@end% + \let\sl@next\relax% + \else% + \ifcase\sl@StateNumber% + \expandafter\gdef\csname #1:WarningState\endcsname{active}% + \or% + \expandafter\gdef\csname #1:WarningState\endcsname{inactive}% + \or% + \expandafter\gdef\csname #1:ErrorState\endcsname{active}% + \or% + \expandafter\gdef\csname #1:ErrorState\endcsname{inactive}% + \fi% + \let\sl@next\sl@@ChangeState% + \fi\sl@next} +% \end{macrocode} + +% \DescribeMacro{\ActivateFilters} +% \DescribeMacro{\DeactivateFilters} +% This aren't just shorthands, something more +% is needed in case there's an argument (because we +% have to retrieve it to pass it to two macros). +% However, it's rather straightforward, we're just +% using "\sl@StateNumber" to keep track of what +% is needed. +% +% \DescribeMacro{\sl@RetrieveArgument} +% Here we just rely on the value required for +% "WarningState", i.e. 0 or 1, and the value +% for "ErrorState" follows suit. +% +% \begin{macrocode} +\def\ActivateFilters{% + \@ifnextchar[% + {\sl@StateNumber0% + \sl@RetrieveArgument}% + {\sl@StateNumber0\relax% + \sl@ChangeState[\sl@WarningNames]% + \sl@StateNumber2\relax% + \sl@ChangeState[\sl@ErrorNames]}} + +\def\DeactivateFilters{% + \@ifnextchar[% + {\sl@StateNumber1% + \sl@RetrieveArgument}% + {\sl@StateNumber1\relax% + \sl@ChangeState[\sl@WarningNames]% + \sl@StateNumber3\relax% + \sl@ChangeState[\sl@ErrorNames]}} + +\def\sl@RetrieveArgument[#1]{% + \def\sl@Argument{#1} + \ifcase\sl@StateNumber% + \sl@ChangeState[\sl@Argument]% + \sl@StateNumber2\relax% + \sl@ChangeState[\sl@Argument]% + \or% + \sl@ChangeState[\sl@Argument]% + \sl@StateNumber3\relax% + \sl@ChangeState[\sl@Argument]% + \fi} +% \end{macrocode} + +% +% +% \subsubsection{String testing} +% Now, here comes the crux of the biscuit, as some guitarist from +% California once said. Here are the macros to test the messages. +% They will be used in the redefinition of "\GenericWarning". +% +% \DescribeMacro{\sl@GetNumber} +% When packages send a warning, "silence" launches "\sl@GetNumber" +% on the expanded list of \meta{number}":sl@"\meta{family} pairs associated +% with this package (created in "\WarningFilter" above). Remember that \meta{number} +% refers to a filter and \meta{family} to its family. +% +% If \meta{number} is not 0 (which is associated with the terminator +% added when "\sl@GetNumber" is launched), +% we test whether the family is active. If so, "\sl@GetMessage" is +% called; otherwise, we proceed to the next pair. +% +% The command +% \vbskip +% "\csname #2:\ifcase\sl@StateNumber Warning\or Error\fi State\endcsname" +% \vbskip +% reduces to "\"\meta{family}":WarningState" or "\"\meta{family}":ErrorState", +% depending on the value of "\sl@StateNumber", which is turned +% to 0 if we're testing a warning or to 1 if we're testing an error. +% +% \begin{macrocode} +\def\sl@GetNumber#1:sl@#2,{% + \ifnum#1>0% + \expandafter% + \ifx\csname #2:\ifcase\sl@StateNumber Warning\or Error\fi State\endcsname\sl@active% + \sl@GetMessage{#1}% + \else% + \let\sl@next\sl@GetNumber% + \fi% + \else% + \let\sl@next\relax% + \fi\sl@next} +% \end{macrocode} + +% \DescribeMacro{\sl@GetMessage} +% \noindent Now we're going to retrieve the filter from the "\sl@BankOfWarnings" +% token list. This list has the following structure, as you might remember: +% \vbskip +% "(:sl@1:)"\meta{first filter}"(:sl@1:)(:sl@2:)"\meta{second filter}"(:sl@2:)...(:sl@n:)"\meta{\emph{n}th filter}"(:sl@n:)" +% \vbskip +% To do so, "\sl@GetMessage" defines a new macro on the fly, "\sl@@GetMessage", +% which takes three arguments, delimited by "(:sl@"\meta{number}":)", +% where \meta{numbers} depends on the pair we're in. That is, suppose +% "\sl@GetNumber" is examining the pair "15:sl@myfam" and "myfam" +% is active. Then we feed "15" to "\sl@GetMessage", which in turn +% creates "\sl@@GetMessage" with the arguments delimited by "(:sl@15:)". +% The first and the third arguments are discarded, while the second +% one, which is the message of the filter, is stored in the "\sl@Filter" +% token list, along with a terminator.\footnote{This terminator +% is the \texttt{\pounds} symbol, unfortunately totally unverbatimizable. So +% it appears as "£".} +% +% \begin{macrocode} +\def\sl@GetMessage#1{% + \def\sl@@GetMessage##1(:sl@#1:)##2(:sl@#1:)##3(:sl@end:){\sl@Filter={##2£}}% +% \end{macrocode} +% +% \noindent Now we launch this command on the bank of warnings (or errors) +% expanded one step, thanks to the same "\edef" trick as above. +% +% \begin{macrocode} + \ifcase\sl@StateNumber% + \edef\sl@act{\noexpand\sl@@GetMessage\the\sl@BankOfWarnings(:sl@end:)}% + \or% + \edef\sl@act{\noexpand\sl@@GetMessage\the\sl@BankOfErrors(:sl@end:)}% + \fi% + \sl@act% +% \end{macrocode} +% +% \noindent When a warning is sent, its message is stored in two forms, +% expanded and unexpanded. Depending on the mode we're currently in +% (safe or bold), we retrieve the right form; in safe mode, we take +% the unexpanded form; in bold mode, we take it too if the "WarningMode" +% of this particular filter is "safe" (i.e. if it was created with +% "\WarningFilter*"), otherwise we take the expanded version. +% +% "\sl@Message" is the token list containing the expanded version, +% "\sl@UnexpandedMessage" contains the unexpanded version, and "\sl@Mess@ge" +% stores the adequate version for the test to come followed by a terminator. +% +% At the end of this macro, we call the string tester. +% +% \begin{macrocode} + \ifsl@SafeMode% + \sl@SafeTesttrue% + \edef\sl@act{\noexpand\sl@Mess@ge{\the\sl@UnexpandedMessage£}}% + \else% + \expandafter% + \ifx\csname #1:\ifcase\sl@StateNumber Warning\or Error\fi Mode\endcsname\sl@safe% + \sl@SafeTesttrue% + \edef\sl@act{\noexpand\sl@Mess@ge{\the\sl@UnexpandedMessage£}}% + \else% + \sl@SafeTestfalse% + \edef\sl@act{\noexpand\sl@Mess@ge{\the\sl@Message£}}% + \fi% + \fi% + \sl@act% + \sl@TestStrings} +% \end{macrocode} + +% \DescribeMacro{\sl@TestStrings} +% This test is a recursive token by token comparison +% of "\sl@Filter" and "\sl@Message", i.e. it compares +% two strings. +% +% First we take the first token of each token list +% thanks, once again, to an "\edef". They are stored +% in "\sl@FilterToken" and "\sl@MessageToken", which +% are macros, not token lists, by the way (see below +% the definition of "\sl@Slice"). +% +% \begin{macrocode} +\def\sl@TestStrings{% + \edef\sl@act{% + \noexpand\sl@Slice\the\sl@Filter(:sl@mid:)\noexpand\sl@Filter\noexpand\sl@FilterToken% + \noexpand\sl@Slice\the\sl@Mess@ge(:sl@mid:)\noexpand\sl@Mess@ge\noexpand\sl@MessageToken}% + \sl@act% +% \end{macrocode} +% +% \noindent Then we simply run some conditional. +% If we reach the terminator in the filter, this means +% that it matches the warning (otherwise we wouldn't have +% gone so far), so we turn a very sad conditional to "true", +% stop the recursion of "\sl@TestString" (thanks to "\sl@@next") +% and gobble the remaining \meta{number}":sl@"\meta{family} pairs waiting to be evaluated +% by "\sl@GetNumber" (thanks to "\sl@next"). Our job is done, +% and "silence" grins with cruelty. +% +% \begin{macrocode} + \ifx\sl@FilterToken\sl@Terminator% + \sl@KillMessagetrue% + \let\sl@@next\relax% + \let\sl@next\sl@Gobble% +% \end{macrocode} +% +% \noindent On the other hand, if we reach the terminator in the warning text, +% this means that it is shorter than the filter (unless we also +% reach the terminator in the filter, but this was taken care of +% in the previous case), so they don't match. We stop recursion +% (there's nothing left to test) and make "\sl@GetNumber" consider +% the following pair. +% +% \begin{macrocode} + \else + \ifx\sl@MessageToken\sl@Terminator% + \let\sl@@next\relax% + \let\sl@next\sl@GetNumber% +% \end{macrocode} +% +% \noindent Now, if none of the tokens is a terminator, then we +% have to compare them. The test will depend on the value +% of "\ifsl@SafeTest" which was turned to "true" in case +% we're in safe mode or the filter is a starred one. In that +% case we run an "\ifx" test, so that even control sequences +% can be properly compared. Since the message is not expanded, +% this is vital. If the tokens match, we proceed to the next +% ones; otherwise, this means that the filter and the message +% are different, so we stop recursion (there's no reason to +% test further), and we call "\sl@GetNumber" on the next pair. +% +% \begin{macrocode} + \else% + \ifsl@SafeTest% + \ifx\sl@FilterToken\sl@MessageToken% + \let\sl@@next\sl@TestStrings% + \else% + \let\sl@@next\relax% + \let\sl@next\sl@GetNumber% + \fi% +% \end{macrocode} +% +% \noindent If we're in bold mode and the filter is starless, +% then we simply compare character codes with "\if". Thus, +% the letters of, say, "\foo", in the filter, will match +% their counterpart in the warning (where the command has +% probably been "\string"'ed), although their category codes +% are different: it's 11 in the filter (no control sequence +% was ever created: "\" was turned to a normal character +% before the filter was stored) and 12 in the message +% (like all "\string"'ed characters). +% +% \begin{macrocode} + \else% + \if\sl@FilterToken\sl@MessageToken% + \let\sl@@next\sl@TestStrings% + \else% + \let\sl@@next\relax% + \let\sl@next\sl@GetNumber% + \fi% + \fi% + \fi% + \fi\sl@@next} +% \end{macrocode} + +% \DescribeMacro{\sl@Slice} +% And here's the final cog in this testing. To put it quite +% unintelligibly, "\sl@Slice" defines its fourth argument +% to expand to the first, while the third, which is a +% token list, is set to the second, and you should not +% forget that the first two arguments are just an expansion +% of the third. Copy that? +% +% Let's get things clear. Remember that "\sl@act" at the +% beginning of "\sl@TestStrings" above was "\edef"ined to: +% \vbskip +% "\noexpand\sl@Slice\the\sl@Filter(:sl@mid:)\noexpand\sl@Filter\noexpand\sl@FilterToken" +% \vbskip +% and similarly for the message. This means that its definition +% text is: +% \vbskip +% "\sl@Slice"\meta{content of $\backslash$\texttt{\emph{sl@Filter}}}"(:sl@mid:)\sl@Filter\sl@FilterToken" +% \vbskip +% The first argument of "\sl@Slice" is undelimited. +% This means that it will be the first token of +% \meta{content of $\backslash$\texttt{\emph{sl@Filter}}}. +% Its second argument will be the rest of this content. +% Now, as explained, "\sl@Slice" defines its fourth argument, +% namely "\sl@FilterToken", to expand to its first one, namely +% the first token in the "\sl@Filter" token list, and +% sets this token list to the second argument, i.e. the to +% rest of itself. In short, we're emptying "\sl@Filter" token by +% token and we compare them along the way, as described above. +% +% \begin{macrocode} +\def\sl@Slice#1#2(:sl@mid:)#3#4{\def#4{#1}#3={#2}} +% \end{macrocode} + +% \subsubsection{Redefining warnings} +% \DescribeMacro{\sl@Belong} +% We have two more macros to create before we can redefine +% warnings themselves. +% "\sl@Belong" is used to check whether a package belongs +% to the "\sl@UnwantedWarnings" list or the "\sl@ProtectedWarnings" list +% (correspondingly for errors). Its argument is an item of those lists +% expanded, that is, the name of a package. It is +% compared to "\sl@PackageName", which is defined +% to the name of the package sending the message. +% If they don't match, we relaunch the command on +% the next item. If they do, we turn "\ifsl@Belong" +% to "true" and gobble the following items. +% +% \begin{macrocode} +\def\sl@Belong#1,{% + \def\sl@Tempa{#1} + \ifx\sl@Tempa\sl@end% + \let\sl@next\relax% + \else% + \ifx\sl@Tempa\sl@PackageName% + \sl@Belongtrue% + \let\sl@next\sl@Gobble% + \else% + \let\sl@next\sl@Belong% + \fi% + \fi\sl@next} +% \end{macrocode} + +% \DescribeMacro{\sl@StoreMessage} +% Finally, we need a mechanism to store the message +% being sent. In safe mode, we store it unexpanded. +% In bold mode, we also store it unexpanded for +% starred filters, but we also store an expanded version +% where "\protect" and "\noexpand" are "\let" to +% "\string", so that the control sequences they +% prefix will be turned into sequences of characters +% (remember that no control sequence is formed in the +% text of a starless filter, only strings of characters). +% We do this in a group because, well, you know, +% you shouldn't do that... +% +% \begin{macrocode} +\def\sl@StoreMessage#1{% + \ifsl@SafeMode% + \sl@UnexpandedMessage{#1}% + \else% + \sl@UnexpandedMessage{#1}% + \bgroup% + \let\protect\string% + \let\noexpand\string% + \edef\sl@Tempa{#1}% + \global\expandafter\sl@Message\expandafter{\sl@Tempa}% + \egroup% + \fi} +% \end{macrocode} + +% Now we're ready for the big redefinitions. +% First, if the "showwarnings" option is on, we +% simply redefine nothing, otherwise we begin by retrieving the current definitions +% of the commands used to issue warnings, in order +% to patch them. For instance, we "\let" "\sl@PackageWarning" +% to "\PackageWarning", and thus we'll be able to +% write: +% +% \vbskip +% "\def\PackageWarning#1#2{%"\\ +% " "\meta{additional code}\\ +% " \sl@PackageWarning{#1}{#2}}" +% \vbskip +% and this will launch "\sl@PackageWarning", i.e. the +% original definition of "\PackageWarning", which will +% do the job it was meant to do in the first place. +% +% For "\GenericWarning", +% this needs some hacking. Indeed "\GenericWarning" is robust, +% which means that it actually does nothing except +% calling "\protect\GenericWarning"\meta{space}, where +% "\GenericWarning"\meta{space} is defined to +% issue the warning as wanted. +% Thus, if we simply +% "\let" "\sl@GenericWarning" to "\GenericWarning" and +% write: +% +% \vbskip +% "\DeclareRobustCommand{\GenericWarning}[2]{%"\\ +% " "\meta{additional code}\\ +% " \sl@GenericWarning{#1}{#2}}" +% \vbskip +% then, because of the robust declaration, "\GenericWarning" +% will be defined to "\protect" "\GenericWarning"\meta{space}, +% whose definition is the additional code followed by +% "\sl@GenericWarning" which, because it was "\let" to +% the older version of "\GenericWarning", expands to +% "\GenericWarning"\meta{space}---that is, we enter an +% infinite loop. The solution is to "\let" "\sl@GenericWarning" +% directly to "\GenericWarning"\meta{space}. +% +% \begin{macrocode} +\ifsl@ShowWarnings +\else +\expandafter\let\expandafter\sl@GenericWarning\csname GenericWarning \endcsname +\let\sl@PackageWarning\PackageWarning +\let\sl@ClassWarning\ClassWarning +\let\sl@latex@warning\@latex@warning +% \end{macrocode} + +% \DescribeMacro{\PackageWarning} +% We redefine "\PackageWarning" so that it stores +% the name of the package calling it, and the message only +% if a certain conditional is true, that is if it +% has not been sent with "\PackageWarningNoLine" +% +% \begin{macrocode} +\def\PackageWarning#1#2{% + \def\sl@PackageName{#1}% + \ifsl@NoLine% + \sl@NoLinefalse% + \else% + \sl@StoreMessage{#2}% + \fi% + \sl@PackageWarning{#1}{#2}} +% \end{macrocode} + +% \DescribeMacro{\PackageWarningNoLine} +% For "\PackageWarningNoLine", we simply store the message +% and send it to "\PackageWarning" with an additional "\@gobble" +% to discard the `"on input line..."' phrase added by \LaTeX. +% (This "\@gobble" was already in the original definition, there +% is nothing new here.) +% +% \begin{macrocode} +\def\PackageWarningNoLine#1#2{% + \sl@StoreMessage{#2}% + \sl@NoLinetrue% + \PackageWarning{#1}{#2\@gobble}} +% \end{macrocode} + +% \DescribeMacro{\ClassWarning}\DescribeMacro{\ClassWarningNoLine} +% \DescribeMacro{\@latex@warning}\DescribeMacro{\@latex@warning@no@line} +% We do exactly the same for class warnings and \LaTeX\ warnings, except +% that in the latter case we manually set "\sl@PackageName" to "latex". +% +% \begin{macrocode} +\def\ClassWarning#1#2{% + \def\sl@PackageName{#1}% + \ifsl@NoLine% + \sl@NoLinefalse% + \else% + \sl@StoreMessage{#2}% + \fi% + \sl@ClassWarning{#1}{#2}} + +\def\ClassWarningNoLine#1#2{% + \sl@StoreMessage{#2}% + \sl@NoLinetrue% + \ClassWarning{#1}{#2\@gobble}} + +\def\@latex@warning#1{% + \def\sl@PackageName{latex}% + \ifsl@NoLine% + \sl@NoLinefalse% + \else% + \sl@StoreMessage{#1}% + \fi% + \sl@latex@warning{#1}} + +\def\@latex@warning@no@line#1{% + \sl@StoreMessage{#1}% + \sl@NoLinetrue% + \@latex@warning{#1\@gobble}} +% \end{macrocode} + +% \DescribeMacro{\GenericWarning} +% Now we can redefine "\GenericWarning". Originally, a message +% sent with, for instance, "\PackageWarning", is edited, and sent to +% "\GenericWarning", which edits it further and sends it to +% the log file. None of this is modified here, although +% some names have changed. Indeed, "\PackageWarning" +% now stores the name of the package and the message +% but then calls "\sl@PackageWarning" on them, which has +% been "\let" to the previous value of "\PackageWarning". +% So the message is formatted as usual and sent to +% "\GenericWarning" which, if the message is not filtered out, +% will launch "\sl@GenericWarning" on the same arguments +% and thus \LaTeX's original mechanism will pass unaffected---albeit +% somewhat spied upon... The original command is robust, so +% we make it robust too. +% +% First, we increment "\sl@WarningCount", which will be used +% if the "debrief" option is on. We also restore some conditional +% to their default values. +% +% \begin{macrocode} +\DeclareRobustCommand{\GenericWarning}[2]{% + \advance\sl@WarningCount1\relax% + \sl@KillMessagefalse% + \sl@Belongfalse% +% \end{macrocode} +% +% \noindent Next, we launch "\sl@Belong" on the expanded +% list of protected warnings if warnings are off, or on +% the expanded list of unwanted warnings if they're on. Depending +% on the result (see the comment on "\WarningsOn" and "\WarningsOff" +% above), we might sentence the message to death. (Turn on +% the "save" option, please, so it may live a happy afterlife +% in "jobname.sil".) +% +% \begin{macrocode} + \ifsl@WarningsOff% + \expandafter\sl@Belong\sl@ProtectedWarnings sl@end,% + \ifsl@Belong% + \else% + \sl@KillMessagetrue% + \fi% + \else% + \expandafter\sl@Belong\sl@UnwantedWarnings sl@end,% + \ifsl@Belong% + \sl@KillMessagetrue% + \fi% + \fi% +% \end{macrocode} +% +% \noindent If the preceding operation is not enough, +% we check whether some filters are associated with the +% package sending the message (in which case "\"\meta{package}"@WarningFilter" +% is defined and contains \meta{number}":sl@"\meta{family} pairs). +% If there are some, we test them with "\sl@GetNumber" as defined above. +% +% \begin{macrocode} + \ifsl@KillMessage% + \else% + \expandafter\ifx\csname\sl@PackageName @WarningFilter\endcsname\relax% + \else% + \sl@StateNumber0\relax% + \expandafter\expandafter\expandafter% + \sl@GetNumber\csname\sl@PackageName @WarningFilter\endcsname,0:sl@sl@end,% + \fi% + \fi% +% \end{macrocode} +% +% \noindent Now the message's fate is sealed. If it has +% been doomed to filtering, we grimly step a sad sad counter. +% Otherwise, we happily sends everything to "\sl@GenericWarning" +% to enlighten the user's log file. +% +% \begin{macrocode} + \ifsl@KillMessage% + \advance\sl@WarningCasualties1% + \else% + \sl@GenericWarning{#1}{#2}% + \fi% +% \end{macrocode} +% +% \noindent Finally, we consider saving it. "\sl@Save" is 0 +% by default, 1 if the "save" option is on, and 2 if "saveall" +% is on. We act accordingly: case 0 does nothing, case 1 sends +% the message to "jobname.sil" if it has been filtered out, +% and case 2 sends all messages. Instead of writing +% everything out properly, we simply `re-route' "\sl@GenericWarning" +% by "\let"ting "\@unused", \LaTeX's output stream, to "\sl@Write", +% "silence"'s output stream directed to "jobname.sil". We do this +% locally, of course. +% +% \begin{macrocode} + \ifcase\sl@Save% + \or% + \ifsl@KillMessage% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericWarning{#1}{#2}% + \egroup% + \fi% + \or% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericWarning{#1}{#2}% + \egroup% + \fi% +% \end{macrocode} +% +% \noindent Before closing, we set "\sl@PackageName" to +% "NoPackage", just in case (very unlikely, to be sure) +% a package uses "\GenericWarning" directly. Thus, the +% former value of "\sl@PackageName" won't interfere. The final +% "\fi" matches "\ifsl@ShowWarnings" some hundred lines +% above. +% +% \begin{macrocode} + \gdef\sl@PackageName{NoPackage}}% +\fi +% \end{macrocode} + + +% \subsection{Errors} +% Errors are implemented just like warnings, so I don't +% command the code. See you at the end of the package +% for the last macro. +% +% \begin{macrocode} +\newcount\sl@ErrorCount +\newcount\sl@ErrorNumber +\newcount\sl@ErrorCasualties + +\newtoks\sl@TempBOE +\newtoks\sl@BankOfErrors + +\newif\ifsl@ErrorsOff + +\expandafter\gdef\csname sl@family:ErrorState\endcsname{active} +\expandafter\gdef\csname sl@end:ErrorState\endcsname{active} +\def\sl@ErrorNames{} +\def\sl@UnwantedErrors{} +\def\sl@ProtectedErrors{} +% \end{macrocode} + +% \DescribeMacro{\ErrorsOn} +% \macskip +% \begin{macrocode} +\def\ErrorsOn{% + \@ifnextchar[% + {\ifsl@ErrorsOff% + \def\sl@next{\sl@Add\sl@ProtectedErrors}% + \else% + \def\sl@next{\sl@Remove\sl@UnwantedErrors}% + \fi\sl@next}% + {\global\sl@ErrorsOfffalse% + \gdef\sl@ProtectedErrors{}% + \gdef\sl@UnwantedErrors{}}} +% \end{macrocode} + +% \DescribeMacro{\ErrorsOff} +% \macskip +% \begin{macrocode} +\def\ErrorsOff{% + \@ifstar% + {\global\sl@ErrorsOfftrue + \gdef\sl@UnwantedErrors{}% + \gdef\sl@ProtectedErrors{}}% + {\@ifnextchar[{% + \ifsl@ErrorsOff% + \def\sl@next{\sl@Remove\sl@ProtectedErrors}% + \else% + \def\sl@next{\sl@Add\sl@UnwantedErrors}% + \fi\sl@next}% + {\global\sl@ErrorsOfftrue% + \gdef\sl@UnwantedErrors{}% + \gdef\sl@ProtectedErrors{latex,}}}} +% \end{macrocode} + +% \DescribeMacro{\ErrorFilter} +% \DescribeMacro{\sl@ErrorFilter} +% \DescribeMacro{\sl@@ErrorFilter} +% \macskip +% \begin{macrocode} +\def\ErrorFilter{% + \global\advance\sl@ErrorNumber1% + \@ifstar% + {\expandafter\gdef\csname\the\sl@ErrorNumber:ErrorMode\endcsname{safe}\sl@ErrorFilter}% + {\sl@ErrorFilter}} + +\def\sl@ErrorFilter{% + \@ifnextchar[% + {\sl@@ErrorFilter}% + {\sl@@ErrorFilter[sl@family]}} + +\def\sl@@ErrorFilter[#1]#2{% + \expandafter\ifx\csname #2@ErrorFilter\endcsname\relax% + \expandafter\xdef\csname #2@ErrorFilter\endcsname{\the\sl@ErrorNumber:sl@#1}% + \else% + \expandafter\xdef\csname #2@ErrorFilter\endcsname{% + \csname #2@ErrorFilter\endcsname,\the\sl@ErrorNumber:sl@#1}% + \fi% + \expandafter\ifx\csname #1:ErrorState\endcsname\relax% + \sl@Add\sl@ErrorNames[#1]% + \fi% + \expandafter\ifx\csname #1:ErrorState\endcsname\sl@active% + \else% + \ifsl@Immediate% + \expandafter\gdef\csname #1:ErrorState\endcsname{active}% + \else% + \expandafter\gdef\csname #1:ErrorState\endcsname{inactive}% + \fi% + \fi% + \begingroup% + \expandafter\ifx\csname\the\sl@ErrorNumber:ErrorMode\endcsname\sl@safe% + \makeatletter% + \else% + \catcode`\\12\relax% + \fi% + \sl@AddToBankOfErrors} +% \end{macrocode} + +% \DescribeMacro{\sl@AddToBankOfErrors} +% \macskip +% \begin{macrocode} +\long\def\sl@AddToBankOfErrors#1{% + \sl@TempBOE{#1}% + \edef\sl@act{% + \global\noexpand\sl@BankOfErrors{% + \the\sl@BankOfErrors% + (:sl@\the\sl@ErrorNumber:)\the\sl@TempBOE(:sl@\the\sl@ErrorNumber:)}}% + \sl@act% + \endgroup} +% \end{macrocode} + +% \DescribeMacro{\ActivateErrorFilters} +% \macskip +% \begin{macrocode} +\def\ActivateErrorFilters{% + \sl@StateNumber2\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@ErrorNames]}} +% \end{macrocode} + +% \DescribeMacro{\DeactivateErrorFilters} +% \macskip +% \begin{macrocode} +\def\DeactivateErrorFilters{% + \sl@StateNumber3\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@ErrorNames]}} + +\ifsl@ShowErrors +\else +\expandafter\let\expandafter\sl@GenericError\csname GenericError \endcsname +\let\sl@PackageError\PackageError +\let\sl@ClassError\ClassError +\let\sl@latex@error\@latex@error +% \end{macrocode} + +% \DescribeMacro{\PackageError} +% \DescribeMacro{\ClassError} +% \DescribeMacro{\@latex@error} +% \macskip +% \begin{macrocode} +\def\PackageError#1#2#3{% + \def\sl@PackageName{#1}% + \sl@StoreMessage{#2}% + \sl@PackageError{#1}{#2}{#3}} + +\def\ClassError#1#2#3{% + \def\sl@PackageName{#1}% + \sl@StoreMessage{#2}% + \sl@ClassError{#1}{#2}{#3}} + +\def\@latex@error#1#2{% + \def\sl@PackageName{latex}% + \sl@StoreMessage{#1}% + \sl@latex@error{#1}{#2}} +% \end{macrocode} + +% \DescribeMacro{\GenericError} +% \macskip +% \begin{macrocode} +\DeclareRobustCommand{\GenericError}[4]{% + \advance\sl@ErrorCount1\relax% + \sl@KillMessagefalse% + \sl@Belongfalse% + \ifsl@ErrorsOff% + \expandafter\sl@Belong\sl@ProtectedErrors,sl@end,% + \ifsl@Belong% + \else% + \sl@KillMessagetrue% + \fi% + \else% + \expandafter\sl@Belong\sl@UnwantedErrors,sl@end,% + \ifsl@Belong% + \sl@KillMessagetrue% + \fi% + \fi% + \ifsl@KillMessage% + \else% + \expandafter\ifx\csname\sl@PackageName @ErrorFilter\endcsname\relax% + \else% + \sl@StateNumber1\relax% + \expandafter\expandafter\expandafter% + \sl@GetNumber\csname\sl@PackageName @ErrorFilter\endcsname,0:sl@sl@end,% + \fi% + \fi% + \ifsl@KillMessage% + \advance\sl@ErrorCasualties1% + \else% + \sl@GenericError{#1}{#2}{#3}{#4}% + \fi% + \ifcase\sl@Save% + \or% + \ifsl@KillMessage% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericError{#1}{#2}{#3}{#4}% + \egroup% + \fi% + \or% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericError{#1}{#2}{#3}{#4}% + \egroup% + \fi% + \gdef\sl@PackageName{NoPackage}}% + \fi +% \end{macrocode} +% +% \subsection{Debrief} +% Finally, at the end of the document, we +% issue a debrief if the user requested it. +% +% A "\clearpage" is needed because we want +% the final output routine to be processed so +% we don't miss the last messages if there are +% some. +% +% \begin{macrocode} +\AtEndDocument{% + \ifsl@Debrief% + \clearpage% +% \end{macrocode} +% +% \noindent Then we do some arithmetics and if messages +% appeared and some of them were filtered out, +% we output the warning. +% +% And we say goodbye. +% +% \begin{macrocode} + \sl@MessageCount\sl@WarningCount% + \advance\sl@MessageCount\sl@ErrorCount% + \sl@Casualties\sl@WarningCasualties% + \advance\sl@Casualties\sl@ErrorCasualties% + \ifnum\sl@MessageCount>0% + \ifnum\sl@Casualties>0% + \advance\sl@WarningCount-1% + \PackageWarningNoLine{silence}{% + There were \the\sl@WarningCount\space warning(s) + and \the\sl@ErrorCount\space error(s).\MessageBreak% + \ifnum\sl@Casualties=\sl@MessageCount% + None survived. This is a violent world% + \else% + I've killed \the\sl@WarningCasualties\space warning(s) + and \the\sl@ErrorCasualties\space error(s)% + \fi}% + \fi% + \fi% + \fi} + +\makeatother +% \end{macrocode}
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/silence/silence.ins b/Master/texmf-dist/source/latex/silence/silence.ins new file mode 100644 index 00000000000..17564a3eb0e --- /dev/null +++ b/Master/texmf-dist/source/latex/silence/silence.ins @@ -0,0 +1,31 @@ +\input docstrip.tex
+\askforoverwritefalse
+\keepsilent
+\preamble
+
+******************************************************************************
+******************************************************************************
+** **
+** silence v.1.1 by Paul Isambert **
+** See the documentation for a comment on the implementation. **
+** **
+** This set of macros is published under the LaTeX Project Public License: **
+** **
+** Do whatever you want to that software, **
+** but if you modify it, change its name to avoid confusion, **
+** and if you copy part of the code please mention where it comes from. **
+** **
+** Comments, suggestions and bugs: **
+** **
+** zappathustra@free.fr **
+** **
+** http://paulisambert.free.fr/ **
+** **
+** Enjoy! **
+** **
+******************************************************************************
+******************************************************************************
+
+\endpreamble
+\generate{\file{silence.sty}{\from{silence-doc.dtx}{package}}}
+\endbatchfile
diff --git a/Master/texmf-dist/tex/latex/silence/silence.sty b/Master/texmf-dist/tex/latex/silence/silence.sty new file mode 100644 index 00000000000..521e15907a7 --- /dev/null +++ b/Master/texmf-dist/tex/latex/silence/silence.sty @@ -0,0 +1,652 @@ +%% +%% This is file `silence.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% silence-doc.dtx (with options: `package') +%% +%% ****************************************************************************** +%% ****************************************************************************** +%% ** ** +%% ** silence v.1.1 by Paul Isambert ** +%% ** See the documentation for a comment on the implementation. ** +%% ** ** +%% ** This set of macros is published under the LaTeX Project Public License: ** +%% ** ** +%% ** Do whatever you want to that software, ** +%% ** but if you modify it, change its name to avoid confusion, ** +%% ** and if you copy part of the code please mention where it comes from. ** +%% ** ** +%% ** Comments, suggestions and bugs: ** +%% ** ** +%% ** zappathustra@free.fr ** +%% ** ** +%% ** http://paulisambert.free.fr/ ** +%% ** ** +%% ** Enjoy! ** +%% ** ** +%% ****************************************************************************** +%% ****************************************************************************** +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{silence}[2009/02/20 v1.1 Selective filtering of warnings and error messages] +\makeatletter + +\newcount\sl@Save +\newif\ifsl@Debrief +\newif\ifsl@ShowWarnings +\newif\ifsl@ShowErrors +\newif\ifsl@Immediate +\newif\ifsl@SafeMode + +\DeclareOption{debrief}{\sl@Debrieftrue} +\DeclareOption{immediate}{\sl@Immediatetrue} +\DeclareOption{safe}{\sl@SafeModetrue} +\DeclareOption{save}{\sl@Save1% +\newwrite\sl@Write% +\immediate\openout\sl@Write=\jobname.sil} +\DeclareOption{saveall}{\sl@Save2% +\newwrite\sl@Write% +\immediate\openout\sl@Write=\jobname.sil} +\DeclareOption{showwarnings}{\sl@ShowWarningstrue} +\DeclareOption{showerrors}{\sl@ShowErrorstrue} +\ProcessOptions\relax + +\newcount\sl@StateNumber +\newcount\sl@MessageCount +\newcount\sl@Casualties + +\newtoks\sl@Filter +\newtoks\sl@Message +\newtoks\sl@UnexpandedMessage +\newtoks\sl@Mess@ge + +\newif\ifsl@Check +\newif\ifsl@Belong +\newif\ifsl@KillMessage +\newif\ifsl@SafeTest + +\def\sl@end{sl@end} +\def\sl@latex{latex} +\def\sl@Terminator{£} +\gdef\sl@active{active} +\gdef\sl@safe{safe} +\gdef\sl@PackageName{NoPackage} +\def\SafeMode{\global\sl@SafeModetrue} +\def\BoldMode{\global\sl@SafeModefalse} +\def\sl@Gobble#1sl@end,{} + +\newcount\sl@WarningCount +\newcount\sl@WarningNumber +\newcount\sl@WarningCasualties + +\newtoks\sl@TempBOW +\newtoks\sl@BankOfWarnings + +\newif\ifsl@WarningsOff +\newif\ifsl@NoLine + +\expandafter\gdef\csname sl@family:WarningState\endcsname{active} +\def\sl@WarningNames{} +\def\sl@UnwantedWarnings{} +\def\sl@ProtectedWarnings{} + +\def\WarningsOn{% + \@ifnextchar[% + {\ifsl@WarningsOff% + \def\sl@next{\sl@Add\sl@ProtectedWarnings}% + \else% + \def\sl@next{\sl@Remove\sl@UnwantedWarnings}% + \fi\sl@next}% + {\global\sl@WarningsOfffalse% + \gdef\sl@ProtectedWarnings{}% + \gdef\sl@UnwantedWarnings{}}} + +\def\WarningsOff{% + \@ifstar% + {\global\sl@WarningsOfftrue + \gdef\sl@UnwantedWarnings{}% + \gdef\sl@ProtectedWarnings{}}% + {\@ifnextchar[{% + \ifsl@WarningsOff% + \def\sl@next{\sl@Remove\sl@ProtectedWarnings}% + \else% + \def\sl@next{\sl@Add\sl@UnwantedWarnings}% + \fi\sl@next}% + {\global\sl@WarningsOfftrue% + \gdef\sl@UnwantedWarnings{}% + \gdef\sl@ProtectedWarnings{latex,}}}} + +\def\sl@Add#1[#2]{% + \xdef#1{#1#2,}} + +\def\sl@Remove#1[#2]{% + \def\sl@Items{#2} + \def\sl@TempNewList{}% + \expandafter\sl@@Remove#1sl@end,% + \let#1\sl@TempNewList} + +\def\sl@@Remove#1,{% + \def\sl@Tempa{#1}% + \ifx\sl@Tempa\sl@end% + \let\sl@next\relax% + \else% + \sl@Checkfalse% + \expandafter\sl@ListCheck\sl@Items,sl@end,% + \ifsl@Check% + \else% + \xdef\sl@TempNewList{\sl@TempNewList#1,}% + \fi% + \let\sl@next\sl@@Remove% + \fi\sl@next}% + +\def\sl@ListCheck#1,{% + \def\sl@Tempb{#1}% + \ifx\sl@Tempb\sl@end% + \let\sl@next\relax% + \else% + \ifx\sl@Tempa\sl@Tempb% + \sl@Checktrue + \let\sl@next\sl@Gobble% + \else% + \let\sl@next\sl@ListCheck% + \fi% + \fi\sl@next} + +\def\WarningFilter{% + \global\advance\sl@WarningNumber1% + \@ifstar% + {\expandafter\gdef\csname\the\sl@WarningNumber:WarningMode\endcsname{safe}% + \sl@WarningFilter}% + {\sl@WarningFilter}} + +\def\sl@WarningFilter{% + \@ifnextchar[% + {\sl@@WarningFilter}% + {\sl@@WarningFilter[sl@family]}} + +\def\sl@@WarningFilter[#1]#2{% + \expandafter\ifx\csname #2@WarningFilter\endcsname\relax% + \expandafter\xdef\csname #2@WarningFilter\endcsname{\the\sl@WarningNumber:sl@#1}% + \else% + \expandafter\xdef\csname #2@WarningFilter\endcsname{% + \csname #2@WarningFilter\endcsname,\the\sl@WarningNumber:sl@#1}% + \fi% + \expandafter\ifx\csname #1:WarningState\endcsname\relax% + \sl@Add\sl@WarningNames[#1]% + \fi% + \expandafter\ifx\csname #1:WarningState\endcsname\sl@active% + \else% + \ifsl@Immediate% + \expandafter\gdef\csname #1:WarningState\endcsname{active}% + \else% + \expandafter\gdef\csname #1:WarningState\endcsname{inactive}% + \fi% + \fi% + \begingroup% + \expandafter\ifx\csname\the\sl@WarningNumber:WarningMode\endcsname\sl@safe% + \makeatletter% + \else% + \catcode`\\12\relax% + \fi% + \sl@AddToBankOfWarnings} + +\long\def\sl@AddToBankOfWarnings#1{% + \sl@TempBOW{#1}% + \edef\sl@act{% + \global\noexpand\sl@BankOfWarnings{% + \the\sl@BankOfWarnings% + (:sl@\the\sl@WarningNumber:)\the\sl@TempBOW(:sl@\the\sl@WarningNumber:)}}% + \sl@act% + \endgroup} + +\def\ActivateWarningFilters{% + \sl@StateNumber0\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@WarningNames]}} + +\def\DeactivateWarningFilters{% + \sl@StateNumber1\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@WarningNames]}} + +\def\sl@ChangeState[#1]{% + \expandafter\sl@@ChangeState#1,sl@end,} + +\def\sl@@ChangeState#1,{% + \def\sl@Tempa{#1}% + \ifx\sl@Tempa\sl@end% + \let\sl@next\relax% + \else% + \ifcase\sl@StateNumber% + \expandafter\gdef\csname #1:WarningState\endcsname{active}% + \or% + \expandafter\gdef\csname #1:WarningState\endcsname{inactive}% + \or% + \expandafter\gdef\csname #1:ErrorState\endcsname{active}% + \or% + \expandafter\gdef\csname #1:ErrorState\endcsname{inactive}% + \fi% + \let\sl@next\sl@@ChangeState% + \fi\sl@next} + +\def\ActivateFilters{% + \@ifnextchar[% + {\sl@StateNumber0% + \sl@RetrieveArgument}% + {\sl@StateNumber0\relax% + \sl@ChangeState[\sl@WarningNames]% + \sl@StateNumber2\relax% + \sl@ChangeState[\sl@ErrorNames]}} + +\def\DeactivateFilters{% + \@ifnextchar[% + {\sl@StateNumber1% + \sl@RetrieveArgument}% + {\sl@StateNumber1\relax% + \sl@ChangeState[\sl@WarningNames]% + \sl@StateNumber3\relax% + \sl@ChangeState[\sl@ErrorNames]}} + +\def\sl@RetrieveArgument[#1]{% + \def\sl@Argument{#1} + \ifcase\sl@StateNumber% + \sl@ChangeState[\sl@Argument]% + \sl@StateNumber2\relax% + \sl@ChangeState[\sl@Argument]% + \or% + \sl@ChangeState[\sl@Argument]% + \sl@StateNumber3\relax% + \sl@ChangeState[\sl@Argument]% + \fi} + +\def\sl@GetNumber#1:sl@#2,{% + \ifnum#1>0% + \expandafter% + \ifx\csname #2:\ifcase\sl@StateNumber Warning\or Error\fi State\endcsname\sl@active% + \sl@GetMessage{#1}% + \else% + \let\sl@next\sl@GetNumber% + \fi% + \else% + \let\sl@next\relax% + \fi\sl@next} + +\def\sl@GetMessage#1{% + \def\sl@@GetMessage##1(:sl@#1:)##2(:sl@#1:)##3(:sl@end:){\sl@Filter={##2£}}% + \ifcase\sl@StateNumber% + \edef\sl@act{\noexpand\sl@@GetMessage\the\sl@BankOfWarnings(:sl@end:)}% + \or% + \edef\sl@act{\noexpand\sl@@GetMessage\the\sl@BankOfErrors(:sl@end:)}% + \fi% + \sl@act% + \ifsl@SafeMode% + \sl@SafeTesttrue% + \edef\sl@act{\noexpand\sl@Mess@ge{\the\sl@UnexpandedMessage£}}% + \else% + \expandafter% + \ifx\csname #1:\ifcase\sl@StateNumber Warning\or Error\fi Mode\endcsname\sl@safe% + \sl@SafeTesttrue% + \edef\sl@act{\noexpand\sl@Mess@ge{\the\sl@UnexpandedMessage£}}% + \else% + \sl@SafeTestfalse% + \edef\sl@act{\noexpand\sl@Mess@ge{\the\sl@Message£}}% + \fi% + \fi% + \sl@act% + \sl@TestStrings} + +\def\sl@TestStrings{% + \edef\sl@act{% + \noexpand\sl@Slice\the\sl@Filter(:sl@mid:)\noexpand\sl@Filter\noexpand\sl@FilterToken% + \noexpand\sl@Slice\the\sl@Mess@ge(:sl@mid:)\noexpand\sl@Mess@ge\noexpand\sl@MessageToken}% + \sl@act% + \ifx\sl@FilterToken\sl@Terminator% + \sl@KillMessagetrue% + \let\sl@@next\relax% + \let\sl@next\sl@Gobble% + \else + \ifx\sl@MessageToken\sl@Terminator% + \let\sl@@next\relax% + \let\sl@next\sl@GetNumber% + \else% + \ifsl@SafeTest% + \ifx\sl@FilterToken\sl@MessageToken% + \let\sl@@next\sl@TestStrings% + \else% + \let\sl@@next\relax% + \let\sl@next\sl@GetNumber% + \fi% + \else% + \if\sl@FilterToken\sl@MessageToken% + \let\sl@@next\sl@TestStrings% + \else% + \let\sl@@next\relax% + \let\sl@next\sl@GetNumber% + \fi% + \fi% + \fi% + \fi\sl@@next} + +\def\sl@Slice#1#2(:sl@mid:)#3#4{\def#4{#1}#3={#2}} + +\def\sl@Belong#1,{% + \def\sl@Tempa{#1} + \ifx\sl@Tempa\sl@end% + \let\sl@next\relax% + \else% + \ifx\sl@Tempa\sl@PackageName% + \sl@Belongtrue% + \let\sl@next\sl@Gobble% + \else% + \let\sl@next\sl@Belong% + \fi% + \fi\sl@next} + +\def\sl@StoreMessage#1{% + \ifsl@SafeMode% + \sl@UnexpandedMessage{#1}% + \else% + \sl@UnexpandedMessage{#1}% + \bgroup% + \let\protect\string% + \let\noexpand\string% + \edef\sl@Tempa{#1}% + \global\expandafter\sl@Message\expandafter{\sl@Tempa}% + \egroup% + \fi} + +\ifsl@ShowWarnings +\else +\expandafter\let\expandafter\sl@GenericWarning\csname GenericWarning \endcsname +\let\sl@PackageWarning\PackageWarning +\let\sl@ClassWarning\ClassWarning +\let\sl@latex@warning\@latex@warning + +\def\PackageWarning#1#2{% + \def\sl@PackageName{#1}% + \ifsl@NoLine% + \sl@NoLinefalse% + \else% + \sl@StoreMessage{#2}% + \fi% + \sl@PackageWarning{#1}{#2}} + +\def\PackageWarningNoLine#1#2{% + \sl@StoreMessage{#2}% + \sl@NoLinetrue% + \PackageWarning{#1}{#2\@gobble}} + +\def\ClassWarning#1#2{% + \def\sl@PackageName{#1}% + \ifsl@NoLine% + \sl@NoLinefalse% + \else% + \sl@StoreMessage{#2}% + \fi% + \sl@ClassWarning{#1}{#2}} + +\def\ClassWarningNoLine#1#2{% + \sl@StoreMessage{#2}% + \sl@NoLinetrue% + \ClassWarning{#1}{#2\@gobble}} + +\def\@latex@warning#1{% + \def\sl@PackageName{latex}% + \ifsl@NoLine% + \sl@NoLinefalse% + \else% + \sl@StoreMessage{#1}% + \fi% + \sl@latex@warning{#1}} + +\def\@latex@warning@no@line#1{% + \sl@StoreMessage{#1}% + \sl@NoLinetrue% + \@latex@warning{#1\@gobble}} + +\DeclareRobustCommand{\GenericWarning}[2]{% + \advance\sl@WarningCount1\relax% + \sl@KillMessagefalse% + \sl@Belongfalse% + \ifsl@WarningsOff% + \expandafter\sl@Belong\sl@ProtectedWarnings sl@end,% + \ifsl@Belong% + \else% + \sl@KillMessagetrue% + \fi% + \else% + \expandafter\sl@Belong\sl@UnwantedWarnings sl@end,% + \ifsl@Belong% + \sl@KillMessagetrue% + \fi% + \fi% + \ifsl@KillMessage% + \else% + \expandafter\ifx\csname\sl@PackageName @WarningFilter\endcsname\relax% + \else% + \sl@StateNumber0\relax% + \expandafter\expandafter\expandafter% + \sl@GetNumber\csname\sl@PackageName @WarningFilter\endcsname,0:sl@sl@end,% + \fi% + \fi% + \ifsl@KillMessage% + \advance\sl@WarningCasualties1% + \else% + \sl@GenericWarning{#1}{#2}% + \fi% + \ifcase\sl@Save% + \or% + \ifsl@KillMessage% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericWarning{#1}{#2}% + \egroup% + \fi% + \or% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericWarning{#1}{#2}% + \egroup% + \fi% + \gdef\sl@PackageName{NoPackage}}% +\fi + +\newcount\sl@ErrorCount +\newcount\sl@ErrorNumber +\newcount\sl@ErrorCasualties + +\newtoks\sl@TempBOE +\newtoks\sl@BankOfErrors + +\newif\ifsl@ErrorsOff + +\expandafter\gdef\csname sl@family:ErrorState\endcsname{active} +\expandafter\gdef\csname sl@end:ErrorState\endcsname{active} +\def\sl@ErrorNames{} +\def\sl@UnwantedErrors{} +\def\sl@ProtectedErrors{} + +\def\ErrorsOn{% + \@ifnextchar[% + {\ifsl@ErrorsOff% + \def\sl@next{\sl@Add\sl@ProtectedErrors}% + \else% + \def\sl@next{\sl@Remove\sl@UnwantedErrors}% + \fi\sl@next}% + {\global\sl@ErrorsOfffalse% + \gdef\sl@ProtectedErrors{}% + \gdef\sl@UnwantedErrors{}}} + +\def\ErrorsOff{% + \@ifstar% + {\global\sl@ErrorsOfftrue + \gdef\sl@UnwantedErrors{}% + \gdef\sl@ProtectedErrors{}}% + {\@ifnextchar[{% + \ifsl@ErrorsOff% + \def\sl@next{\sl@Remove\sl@ProtectedErrors}% + \else% + \def\sl@next{\sl@Add\sl@UnwantedErrors}% + \fi\sl@next}% + {\global\sl@ErrorsOfftrue% + \gdef\sl@UnwantedErrors{}% + \gdef\sl@ProtectedErrors{latex,}}}} + +\def\ErrorFilter{% + \global\advance\sl@ErrorNumber1% + \@ifstar% + {\expandafter\gdef\csname\the\sl@ErrorNumber:ErrorMode\endcsname{safe}\sl@ErrorFilter}% + {\sl@ErrorFilter}} + +\def\sl@ErrorFilter{% + \@ifnextchar[% + {\sl@@ErrorFilter}% + {\sl@@ErrorFilter[sl@family]}} + +\def\sl@@ErrorFilter[#1]#2{% + \expandafter\ifx\csname #2@ErrorFilter\endcsname\relax% + \expandafter\xdef\csname #2@ErrorFilter\endcsname{\the\sl@ErrorNumber:sl@#1}% + \else% + \expandafter\xdef\csname #2@ErrorFilter\endcsname{% + \csname #2@ErrorFilter\endcsname,\the\sl@ErrorNumber:sl@#1}% + \fi% + \expandafter\ifx\csname #1:ErrorState\endcsname\relax% + \sl@Add\sl@ErrorNames[#1]% + \fi% + \expandafter\ifx\csname #1:ErrorState\endcsname\sl@active% + \else% + \ifsl@Immediate% + \expandafter\gdef\csname #1:ErrorState\endcsname{active}% + \else% + \expandafter\gdef\csname #1:ErrorState\endcsname{inactive}% + \fi% + \fi% + \begingroup% + \expandafter\ifx\csname\the\sl@ErrorNumber:ErrorMode\endcsname\sl@safe% + \makeatletter% + \else% + \catcode`\\12\relax% + \fi% + \sl@AddToBankOfErrors} + +\long\def\sl@AddToBankOfErrors#1{% + \sl@TempBOE{#1}% + \edef\sl@act{% + \global\noexpand\sl@BankOfErrors{% + \the\sl@BankOfErrors% + (:sl@\the\sl@ErrorNumber:)\the\sl@TempBOE(:sl@\the\sl@ErrorNumber:)}}% + \sl@act% + \endgroup} + +\def\ActivateErrorFilters{% + \sl@StateNumber2\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@ErrorNames]}} + +\def\DeactivateErrorFilters{% + \sl@StateNumber3\relax% + \@ifnextchar[% + {\sl@ChangeState}% + {\sl@ChangeState[\sl@ErrorNames]}} + +\ifsl@ShowErrors +\else +\expandafter\let\expandafter\sl@GenericError\csname GenericError \endcsname +\let\sl@PackageError\PackageError +\let\sl@ClassError\ClassError +\let\sl@latex@error\@latex@error + +\def\PackageError#1#2#3{% + \def\sl@PackageName{#1}% + \sl@StoreMessage{#2}% + \sl@PackageError{#1}{#2}{#3}} + +\def\ClassError#1#2#3{% + \def\sl@PackageName{#1}% + \sl@StoreMessage{#2}% + \sl@ClassError{#1}{#2}{#3}} + +\def\@latex@error#1#2{% + \def\sl@PackageName{latex}% + \sl@StoreMessage{#1}% + \sl@latex@error{#1}{#2}} + +\DeclareRobustCommand{\GenericError}[4]{% + \advance\sl@ErrorCount1\relax% + \sl@KillMessagefalse% + \sl@Belongfalse% + \ifsl@ErrorsOff% + \expandafter\sl@Belong\sl@ProtectedErrors,sl@end,% + \ifsl@Belong% + \else% + \sl@KillMessagetrue% + \fi% + \else% + \expandafter\sl@Belong\sl@UnwantedErrors,sl@end,% + \ifsl@Belong% + \sl@KillMessagetrue% + \fi% + \fi% + \ifsl@KillMessage% + \else% + \expandafter\ifx\csname\sl@PackageName @ErrorFilter\endcsname\relax% + \else% + \sl@StateNumber1\relax% + \expandafter\expandafter\expandafter% + \sl@GetNumber\csname\sl@PackageName @ErrorFilter\endcsname,0:sl@sl@end,% + \fi% + \fi% + \ifsl@KillMessage% + \advance\sl@ErrorCasualties1% + \else% + \sl@GenericError{#1}{#2}{#3}{#4}% + \fi% + \ifcase\sl@Save% + \or% + \ifsl@KillMessage% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericError{#1}{#2}{#3}{#4}% + \egroup% + \fi% + \or% + \bgroup% + \let\@unused\sl@Write% + \sl@GenericError{#1}{#2}{#3}{#4}% + \egroup% + \fi% + \gdef\sl@PackageName{NoPackage}}% + \fi +\AtEndDocument{% + \ifsl@Debrief% + \clearpage% + \sl@MessageCount\sl@WarningCount% + \advance\sl@MessageCount\sl@ErrorCount% + \sl@Casualties\sl@WarningCasualties% + \advance\sl@Casualties\sl@ErrorCasualties% + \ifnum\sl@MessageCount>0% + \ifnum\sl@Casualties>0% + \advance\sl@WarningCount-1% + \PackageWarningNoLine{silence}{% + There were \the\sl@WarningCount\space warning(s) + and \the\sl@ErrorCount\space error(s).\MessageBreak% + \ifnum\sl@Casualties=\sl@MessageCount% + None survived. This is a violent world% + \else% + I've killed \the\sl@WarningCasualties\space warning(s) + and \the\sl@ErrorCasualties\space error(s)% + \fi}% + \fi% + \fi% + \fi} + +\makeatother +\endinput +%% +%% End of file `silence.sty'. |