%\iffalse % makegobbler.dtx generated using makedtx version 1.2 (c) Nicola Talbot % Command line args: % -src "makegobbler\.sty$=>makegobbler.sty" % -codetitle "Le code" % -author "Vincent Bela{\\"\\i}che" % -doc "../../doc/latex/makegobbler/makegobbler-doc.tex" % -dir "../../tex/latex/makegobbler" % makegobbler % Created on 2026/2/1 8:55 %\fi %\iffalse %<*package> %% \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 \~} % %\fi % \iffalse % Doc-Source file to use with LaTeX2e % Copyright (C) 2026 Vincent Bela{\"\i}che, all rights reserved. % \fi % \iffalse %<*driver> % !TEX encoding = IsoLatin9 \documentclass[a4paper]{ltxdoc} \usepackage[latin9]{inputenc} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage{doc} \usepackage{efrench} % Grosse magouille non à l'épreuve du temps pour contre-carrer ce que fait eFrench {\makeatletter\@ifundefined{fr@di}{\let\@tempa\@empty}{\def\@tempa{\let\DocInput\fr@di}}\expandafter}\@tempa \newcommand*\enquote[1]{\guillemets#1\endguillemets} \usepackage[french]{datetime2} \DTMsetstyle{french} \DTMsavedate{date-doc}{2025-12-12} \usepackage{amssymb} \usepackage{placeins} \date{\DTMusedate{date-doc}} \title{Le paquetage \texttt{makegobbler} v0.3 (2025-11-29)}%\\{\protect\small Une fabrique conditionnelle à gobeurs ou dégobeurs}} \author{Vincent Belaïche} \newcommand*\vs{\leavevmode\hbox{\tt\char`\ }} \newcommand\exampleframe[1]{\centering \framebox[\textwidth]{% \begin{minipage}[t]{\dimexpr\textwidth-2\fboxrule-2\fboxsep}\ttfamily\raggedright #1% \end{minipage}% }}% \newenvironment{exemple}{\begin{figure}[h!t]}{\end{figure}\FloatBarrier} \providecommand*\DocTeX{Doc\TeX} \begin{document} \DocInput{makegobbler.dtx} \end{document} % %\fi %\renewcommand*\listfigurename{Liste des exemples}%^^A %\renewcommand*\figurename{\textsc {Exemple}}%^^A %\maketitle %\tableofcontents %\listoffigures % %\section{Introduction} %\label{sec:intro} % %Le but du paquetage \texttt{makegobbler} et de faciliter l'omission conditionnelle d'une portion de document. Un exemple %valant mieux qu'un long discours : % %\begin{exemple} % \exampleframe{%^^A % \cs{newif}\cs{ifgarde}\\ % \ldots\\ % \cs{MGBkeep*}\cs{ifgarde}\\ % \cs{LaMacroQuiGobeTout}\\ % Bla Bla bla, texte inséré conditionnellement seulement si \cs{gardetrue}.\\ % \cs{LaMacroQuiGobeTout} % }%^^A % \caption{Exemple introductif} % \label{ex:intro} %\end{exemple} % %Dans l'exemple ci-dessus la macro \cs{LaMacroQuiGobeTout} est ci-après désigné par \emph{délimiteur}, et on %peut utiliser n'importe quel nom \meta{délimiteur} de macro \cs{}\meta{délimiteur} aux lieux de %\cs{LaMacroQuiGobeTout}. Dans le cas où \cs{conditionfalse} tout ce qui est entre les deux %\cs{}\meta{délimiteur}s est supprimé (gobé), et dans le cas inverse, quand \cs{conditiontrue}, c'est conservé %(dégobé).\\ Dans le premier cas, le premier \cs{}\meta{délimiteur} est défini comme une macro de gobage, ou %gobeur, gobant tout jusqu'à une marque de fin qui est le second \cs{}\meta{délimiteur} vu comme une %string\footnote{\texttt{string} en \LaTeX\ signifie une chaîne d'unités lexicales qui sont des caractères de % catcode \texttt{other} ou \texttt{space}, dans le cas de \texttt{makegobbler} le \cs{}\meta{délimiteur} de % fin ne comprend que des caractères de catcode \texttt{other}.}, et c'est la raison du nom %\texttt{makegobbler} du paquetage, parce qu'il fait du premier \cs{}\meta{délimiteur} un gobeur. % %\section{Usage et limitations} %\label{sec:use-and-limits} % %\subsection{Motivations} %\label{sec:motivations} % %Le paquetage \texttt{makegobbler} n'est pas fait pour remplacer les constructions conditionnelles de \TeX\ du genre de : %\begin{exemple} % \exampleframe{%^^A % \cs{newcommand}*\cs{Un}\{2\}\%\\ % \ldots\\ % \cs{ifnum}\cs{Un}=1 C'est un\cs{else} C'est deux\cs{fi} % }%^^A % \caption{Gobage conditionnel classique à la \TeX} %\end{exemple} %\noindent ni plus la macro \cs{ifthenelse} du paquetage \LaTeX\ \texttt{ifthen} qu'on peut utiliser ainsi : %\begin{exemple} % \exampleframe{%^^A % \cs{newcommand}*\cs{Un}\{2\}\%\\ % \ldots\\ % \cs{ifthenelse}\{\cs{Un}=1\}\{C'est un\}\{C'est deux\} % }%^^A % \caption{Gobage conditionnel classique à la \LaTeX} %\end{exemple} %\noindent bien au contraire, \texttt{makegobbler} s'appuie justement sur ces constructions pour tester les conditions de %gobage ou dégobage, et son objectif est plutôt de pallier certaines limitations du gobage effectué par ces méthodes %classiques. L'exemple \ref{ex:lim-ltx-spec-car} illustre\footnote{Aux non-francophones, c'est extrait des paroles de la % chanson \emph{Comic strip} de Serge Gainsbourg, la drôlerie des paroles vient qu'en franglais \emph{strip} n'est connu % que dans son sens \emph{dévêtir} et non dans son sens \emph{bande}.} cela : si vous décommentez le %\cs{alternativetrue} il produit une erreur \texttt{You can\string't use \string`macro parameter character \#\string' in % horizontal mode.}. % %\begin{exemple} % \exampleframe{%^^A % \cs{newif}\cs{ifalternative}\\ % \%\cs{alternativetrue}\\ % \ldots\\ % Viens petite fille dans mon comic strip\\ % \ldots\\ % \cs{ifthenelse}\{\cs{boolean}\{alternative\}\}\{\cs{verb}+\#!+\}\{SHEBAM !\} POW ! BLOP ! WIZZ ! % }%^^A % \caption{Limitation d'{\tt\cs{ifthenelse}} avec des caractères spéciaux} % \label{ex:lim-ltx-spec-car} %\end{exemple} % %Cela se produit parce que \cs{verb} fonctionne en changement le régime de catcode de ce qui suit, mais pour que cela %fonctionne il faut que \cs{verb} soit exécuté\footnote{Le deuxième étage de \TeX, c-à-d. la gueule du lion.}. Or si on %passe \texttt{\cs{verb}+\#!+} en argument à \cs{ifthenelse} le catcode de \texttt{\#} est fixé au moment de la capture %de l'argument, car celle-ci impose de passer le premier étage\footnote{les yeux du lion.} de \TeX, celui qui convertit %les caractères en unités lexicales, et donc \texttt{\#} conserve son catcode initial 6 (qui veut dire argument de macro) %et \cs{verb} n'y pourra rien changer. % %Le paquetage \texttt{makegobbler} résout le problème de l'exemple \ref{ex:lim-ltx-spec-car} parce que les sections %dégobées ne sont pas passées en argument de macro, et d'ailleurs pour la même raison l'utilisation d'une condition à la %\TeX\ aurait aussi résolu le problème, comme dans l'exemple \ref{ex:tex-cond-spec-car} ci-dessous : % %\begin{exemple} % \exampleframe{%^^A % \cs{newif}\cs{ifalternative}\\ % \cs{alternativetrue}\\ % \ldots\\ % Viens petite fille dans mon comic strip\\ % \ldots\\ % \cs{ifalternative}\cs{verb}+\#!+\cs{else} SHEBAM !\cs{fi}\cs{space} POW ! BLOP ! WIZZ ! % }%^^A % \caption{Caractères spéciaux avec une condition à la \TeX} % \label{ex:tex-cond-spec-car} %\end{exemple} % %Bien sûr dans ces exemples simplistes il aurait suffit d'écrire \texttt{\cs{texttt}\{\cs{\#}!\}} au lieu de %\texttt{\cs{verb}+\#!+} et cela aurait aussi fonctionné, mais le prix de cela est d'écrire un code moins lisible. % % %Utiliser des conditions à la \TeX\ n'est toutefois pas une solution ultime, en effet il reste des cas qui ne %fonctionnent pas même avec les conditions à la \TeX, l'exemple \ref{ex:lim-tex-if} en illustre un : % %\begin{exemple} % \exampleframe{%^^A % \cs{newif}\cs{ifok}\\\cs{oktrue}\\ % \ldots\\ % \cs{ifok} À minuit les carrosses redeviennent des c\cs{verb}+\cs{iftrue}+illes.\cs{fi} % }%^^A % \caption{Limitations d'\cs{if}\ldots} % \label{ex:lim-tex-if} %\end{exemple} % %Si vous mettez en commentaire le \cs{oktrue} alors il y aura une erreur de compilation \texttt{Incomplete \cs{iffalse}; % all text was ignored after line \ldots} La raison pour laquelle cela échoue est que le \cs{ifok} pour gober tout ce %qui suit jusqu'au \cs{fi} suivant teste tout de même s'il y a des unités lexicales de type \cs{if}\ldots, de sorte à %tomber sur le bon délimiteur de fin \cs{fi}. En faisant cela il considère par erreur que le \cs{iftrue} qui est passé %dans \texttt{\cs{verb}+\ldots+} attend un \cs{fi}, et donc il considère que le \cs{fi} suivant correspond à ce %\cs{iftrue} et non à \cs{ifok}. % %Avec \texttt{makegobbler} ce problème est résolu parce que l'utilisateur donne un délimiteur \cs{}\meta{délimiteur} arbitraire, et donc en cas de gobage avec imbrications de plusieurs sections en gobage/dégobage conditionnels il suffit d'utiliser un \cs{}\meta{délimiteur} propre à chaque niveau d'imbrication. % %Dans cette rubrique j'ai surtout mentionné les problèmes qu'on peut avoir avec \cs{verb} que vous n'utilisez peut-être %jamais. Sachez que c'est loin d'être le seul cas, et que toutes macros ou environnements qui jouent avec le régime de %catcode sont sujets aux mêmes types de limitations, et d'ailleurs les questions posées par les débutants sur les forums %ne concernent pas rarement la survenue de cette famille de problèmes. Notons pas exemple\footnote{Cette liste n'est en aucun cas exhaustive.} que : %\begin{itemize} %\item \cs{includegraphics} avec les paquetages \texttt{graphicx,grffile} est capable de traiter correctement certains % caractères spéciaux, comme par ex. \texttt{\~}, au sein d'un nom de fichier en changeant son régime de catcode, %\item \cs{href} et \cs{url} du paquetage \texttt{hyperref} sont également concernés pour traiter correctement certains % caractères spéciaux au sein d'\textsc{url}s, ou encore %\item l'environnement \texttt{lstlisting} et la macro \cs{lstinline} de l'excellent paquetage \texttt{listings}, par % exemple avec un listing en langage C on peut avoir typiquement des directives préprocesseur \texttt{\#if CONDITION} % qui poseraient problème si vous essayez de les dégober avec \cs{ifthenelse}. %\end{itemize} % %\subsection{Limitations de \protect\texttt{makegobbler}} %\label{sec:mgb-limits} % %Si vous avez lu attentivement la rubrique \S\ref{sec:motivations} alors vous savez déjà qu'utiliser les macros de %\texttt{makegobbler} au sein d'un argument de macro est voué à l'échec : comme \cs{verb} les macros de %\texttt{makegobbler} jouent avec les catcodes, et donc produisent le même type de limitations. % %Au sein de la plupart des environnements, cela au contraire va fonctionner. Et d'ailleurs si cela ne fonctionnait pas au %sein de l'environnement \texttt{document}, alors le paquetage serait inutilisable. Toutefois avec certains %environnements cela ne fonctionnera pas. En effet un environnement \meta{env} peut-être de deux types : %\begin{itemize} %\item soit c'est un environnement \emph{fil-de-l'eau}, dans ce cas le \texttt{\cs{begin}\{\meta{env}\}} et sa % contrepartie \texttt{\cs{end}\{\meta{env}\}} sont juste comme deux macros qui activent et désactivent certaines % conditions de traitement de ce qu'il y a entre les deux, par exemple la police, ou bien le régime de catcode ou encore % le paramétrage de formation de paragraphes, %\item soit c'est un environnement \emph{aspirant}, cela signifie que tout ce qui se trouve entre % \texttt{\cs{begin}\{\meta{env}\}} et \texttt{\cs{end}\{\meta{env}\}} est préalablement aspiré comme si c'était % l'argument d'une macro de sorte à avoir une liste d'unités lexicales, et qu'ensuite cette liste est post-traitée. %\end{itemize} %Les macros de \texttt{makegobbler} ne vont donc fonctionner correctement pour gober/dégober des sections de code entre %\texttt{\cs{begin}\{\meta{env}\}} et \texttt{\cs{end}\{\meta{env}\}} que si \meta{env} est un environnement fil-de-l-eau, mais elles ne fonctionneront pas avec un environnement aspirant, puisqu'on se retrouve dans la même situation que si le code était au sein d'un argument de macro. Voici quelques environnements aspirants : %\begin{itemize} %\item la plupart des environnements du paquetage \texttt{amsmath}, %\item tous les environnements créés avec la macro \cs{NewEnviron} du paquetage \texttt{environ}, et %\item l'environnement \texttt{frame} de la classe \texttt{beamer}, sauf dans le cas où il reçoit l'argument optionnel % \texttt{fragile}. %\end{itemize} % %\section{Options du paquetage} %\label{sec:package-options} % %Le paquetage a deux options : % %\begin{description} %\item[ifthen] Juste une commodité pour charger le paquetage \texttt{ifthen}, ceci est nécessaire pour utiliser % les macros de (dé)gobage conditionnel avec une condition à la \LaTeX. %\item[tense] Ne pas utiliser sauf si vous savez ce que vous faites. Voir la documentation du code. %\end{description} % %\section{Interface utilisateur} %\subsection{Macros pour un gobage ou dégobage conditionnel} %\label{sec:conditional-macros} % %Le paquetage offre quatre macros pour le (dé)gobage conditionnel d'un bout de code \LaTeX : \cs{MGBkeep}, %\cs{MGBdrop}, \cs{MGBkeepelse}, et \cs{MGBdropelse}. Les deux premières utilisent deux %\cs{}\meta{délimiteur}s, et les deux dernières trois. % %Chacune de ses macros a pour premier argument une condition. La syntaxe est la suivante : % %\begin{exemple} % \exampleframe{%^^A % \cs{MGBkeep}\meta{étoile}\meta{condition}\cs{}\meta{délimiteur}\\ % \quad\meta{dégobé}\\ % \cs{}\meta{délimiteur}}%^^A %\end{exemple} %\meta{dégobé} peut être n'importe quoi entre les deux \cs{}\meta{délmiteur}s, et il est dégobé si %\meta{condition} est vraie, et gobé sinon. Avec \cs{MGBdrop} c'est le contraire, la condition de débogage %est\footnote{\enquote{$\neg C$} signifie \enquote{non $C$}.} $\neg$\meta{condition}. % %Avec les deux autres macros, \cs{MGBkeepelse} et \cs{MGBdropelse}, on a deux branches, l'une contenant %\meta{gobé} et l'autre \meta{dégobé} : % %\begin{exemple} % \exampleframe{%^^A % \cs{MGBkeepelse}\meta{étoile}\meta{condition}\cs{}\meta{délimiteur}\\ % \quad\meta{dégobé}\\ % \cs{}\meta{délimiteur}\\ % \quad\meta{gobé}\\ % \cs{}\meta{délimiteur}}%^^A %\end{exemple} %Dans ce cas si \meta{condition} est vraie, \meta{dégobé} est dégobé, et \meta{gobé} est gobé, et sinon, si %\meta{condition} est faux, c'est le contraire. En utilisant \cs{MGBdropelse}, la branche \meta{gobé} %correspondant au gobage sous \meta{condition} est donnée en premier, et celle \meta{dégobé} correspondant au %dégobage en second. % %\begin{exemple} % \exampleframe{%^^A % \cs{MGBdropelse}\meta{étoile}\meta{condition}\cs{}\meta{délimiteur}\\ % \quad\meta{gobé}\\ % \cs{}\meta{délimiteur}\\ % \quad\meta{dégobé}\\ % \cs{}\meta{délimiteur}}%^^A %\end{exemple} %\meta{étoile} peut être soit \texttt{*} soit vide, dans le premier cas on dit que la macro est étoilée, et %dans le second qu'elle est non-étoilée. Si la macro est non-étoilée, alors la condition est une condition à la %\LaTeX, c'est à dire une condition telle que la prend en premier argument la macro \cs{ifthenelse} du %paquetage \texttt{ifthen}, par exemple\footnote{\meta{condition} correspond à % \texttt{\{}\meta{test}\texttt{\}} dans le manuel de \texttt{ifthen}.} %\texttt{\{}\cs{boolean}\texttt{\{true\}\}} ou \texttt{\{}\cs{equal}\texttt{\{}\meta{chaîne % 1}\texttt{\}\{}\meta{chaîne 2}\texttt{\}\}}. Se reporter à la documentation de ce paquetage pour plus ample %information. Avec les formes non étoilées il faut donc que le paquetage \texttt{ifthen} ait été chargé, ce que %vous pouvez faire en passant l'option \texttt{ifthen} à \texttt{makeglobber}. % %Avec la forme étoilée, le premier argument doit être une condition à la \TeX, c'est à dire : %\begin{itemize} %\item soit une condition\footnote{Toto a un cousin anglais complètement foo.} \cs{iftoto} qui est instanciée % avec une commande \cs{newif}\cs{iftoto} et qui peut être commutée avec les macros \cs{totofalse} et % \cs{tototrue}, %\item soit une condition qui utilise l'un des opérateurs de branchement conditionnel prédéfini dans \TeX, par % ex. \cs{ifmmode}, \texttt{\{}\cs{ifnum}\meta{a}=\meta{b}\vs\texttt{\}}, % \texttt{\{}\cs{ifx}\cs{}\meta{a}\cs{}\meta{b}\texttt{\}}, etc.\ Notez que dans les cas où \meta{condition} % consiste en plusieurs unités lexicales il faut\footnote{Ceci n'a rien à voir avec le paquetage % \texttt{makeglobber}, c'est une règle générale de \TeX, lorsqu'un argument de macro consiste en une % séquence de plusieurs unités lexicales on le met entre accolades pour le passer d'un seul tenant à la % macro. Lorsque il y a une seule unité lexicale, alors les accolades sont optionnelles, on peut passer % \texttt{\{}\cs{iftoto}\texttt{\}} aussi bien que \cs{iftoto}.} l'écrire entre accolades. %\end{itemize} % %\subsection{Macros pour un gobage ou dégobage inconditionnel} %\label{sec:elementary-macros} % %Le paquetage fournit également deux macros de plus bas niveau \cs{makegobbler} et \cs{makeungobbler} qu'en général %l'utilisateur $\lambda$ n'a pas besoin d'utiliser directement, et qui servent respectivement au gobage et au %dégobage inconditionnel d'un bout de code \LaTeX. % %Je décris ci-après ci-après ces deux macros parce qu'elles constituent le mécanisme sous-jacent du paquetage, %c'est à dire que sous le capot, les macros pour le gobage et/ou dégobage conditionnel, \cs{MGBkeep}, %\cs{MGBdrop}, \cs{MGBkeepelse}, et \cs{MGBdropelse}, finissent par se développer, selon la \meta{condition} %qui leur est passée, en un \cs{makegobbler} ou un \cs{makeungobbler} % %Le nom du paquetage provient d'ailleurs de ce que le délimiteur \cs{}\meta{délimiteur} peut être utilisé avec %\cs{makegobbler} pour supprimer tout ce qui suit jusqu'au prochain \cs{}\meta{délimiteur}, comme ci-dessous, %où pour l'exemple \cs{}\meta{délimiteur} est nommé \cs{LaMacroQuiGobeTout} : % %\begin{exemple} % \exampleframe{%^^A % \cs{makegobbler}\cs{LaMacroQuiGobeTout}\\ % Bla Bla bla, tout le texte ici est supprimé.\\ % \cs{LaMacroQuiGobeTout} % }%^^A %\end{exemple} %On appelle cette suppression \emph{gobage}, et on dit que \cs{LaMacroQuiGobeTout} est un gobeur, la macro \cs{makegobbler} %sert donc à fabriquer un gobeur du nom de \cs{LaMacroQuiGobeTout} qui va tout gober jusqu'à rencontrer une marque de fin %également nommé \cs{LaMacroQuiGobeTout}, sauf que du point de vue catcodique la première occurrence de \cs{LaMacroQuiGobeTout} est une %séquence de contrôle, alors que la seconde est une \texttt{string}, c'est à dire une suite de caractères de %catcode \texttt{other}. % %Si on avait utilisé \cs{makeungobbler} à la place de \cs{makegobbler} alors le texte aurait été inséré au lieu d'être %supprimé : % %\begin{exemple} % \exampleframe{%^^A % \cs{makeungobbler}\cs{LaMacroQuiGobeTout}\\ % Bla Bla bla, tout le texte ici est inséré.\\ % \cs{LaMacroQuiGobeTout} % }%^^A %\end{exemple} % %Et donc dans l'exemple ci-dessus on parle de \emph{dégobage} et on dit que \cs{LaMacroQuiGobeTout} a été définie comme %un dégobeur, c'est à dire qu'elle conserve tout ce qui suit jusqu'à la prochaine occurrence de \cs{LaMacroQuiGobeTout} %qui sert de marque de fin, et que cette marque de fin est supprimée. % %Il est à noter que la définition de \cs{}\meta{délimiteur} comme une macro de gobage/dégobage est transitoire. Une fois %la marque de fin consommée, \cs{}\meta{délimiteur} reprend sa valeur initiale si elle en avait une, ou sinon redevient %indéfini. % % %%^^A Local Variables: %%^^A coding: latin-9 %%^^A ispell-dictionary: "fr" %%^^A mode: LaTeX %%^^A compile-command: "make -C ../../../ doc" %%^^A End: % %\StopEventually{} %\section{Le code} %\iffalse % \begin{macrocode} %<*makegobbler.sty> % \end{macrocode} %\fi %^^A !TEX encoding = IsoLatin9 % \subsection{Options du paquetage} % Les déclarations habituelles pour que \LaTeX\ connaisse le paquetage. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}[2020/10/01] \ProvidesPackage{makegobbler} [2025-11-29 v0.3 % Gobbling macros maker] % \end{macrocode} % \DescribeMacro{\MGB@process@ifthen@option} Une option juste pour dire de charger le paquetage \texttt{ifthen} qui % permet d'avoir des conditions à la \LaTeX. La macro \cs{MGB@process@ifthen@option} sert juste à faire le % \cs{RequirePackage\{ifthen\}} après le \cs{ProcessOptions}, c'est à dire qu'on la développe à cet endroit là. Elle % s'autodétruit assitôt sa tâche accomplie, vu qu'on n'en a plus besoin par la suite. % \begin{macrocode} \DeclareOption{ifthen}{\def\MGB@process@ifthen@option {\RequirePackage{ifthen}\let\MGB@process@ifthen@option\@undefined}} % \end{macrocode} % Si l'option \texttt{ifthen} n'est pas passée, \cs{MGB@process@ifthen@option} ne fait rien mis à part s'autodétruire. % \begin{macrocode} \def\MGB@process@ifthen@option{\let\MGB@process@ifthen@option\@undefined} % \end{macrocode} % N'utilisez pas l'option \texttt{tense}, sauf si vous avez lu et compris le code qui l'utilise, et si vous recherchez % un substitut à la caféine. % \begin{macrocode} \newif\ifMGB@tense \DeclareOption{tense}{\MGB@tensetrue} % \end{macrocode} % \begin{macrocode} \ProcessOptions* \MGB@process@ifthen@option % \end{macrocode} % %\subsection{Interface utilisateur} %\label{sec:user-interface} % \subsubsection{Macros de gobage/dégobage conditionnel} % \DescribeMacro{\MGBkeep}% % \DescribeMacro{\MGBdrop}% % \DescribeMacro{\MGBkeepelse}% % \DescribeMacro{\MGBdropelse} Définition des macros d'interface utilisateur, les quatre définitions ont sensiblement % la même gueule parce qu'en premier lieu on ne fait que sélectionner si on passe une condition à la \TeX\ en étoilant % la macro, ou bien à la \LaTeX\ en ne l'étoilant pas. % \begin{macrocode} \def\MGBkeep{\MGB@stdhooks\@ifstar{\MGBkeep@tex}{\MGBkeep@latex}} \def\MGBdrop{\MGB@stdhooks\@ifstar{\MGBdrop@tex}{\MGBdrop@latex}} \def\MGBkeepelse{\MGB@elsehooks\@ifstar{\MGBkeep@tex}{\MGBkeep@latex}} \def\MGBdropelse{\MGB@elsehooks\@ifstar{\MGBdrop@tex}{\MGBdrop@latex}} % \end{macrocode} % \subsubsection{Macros de gobage/dégobage inconditionnel} % Les quatre macros de gobage/dégobage conditionnel sous le capot finissent tôt ou tard par développer l'une des deux % macros de plus bas niveau \cs{MGB@g} dans le cas d'un gobage, ou \cs{MGB@u} dans le cas d'un dégobage. Ces deux % dernières sont également accessible depuis l'interface utilisateur, via respetivement les macros \cs{makeglobber} et % \cs{makeunglobber}, en effet \cs{makeglobber} pourrait être utile par exemple en \DocTeX\ pour gober la section pilote % du document \texttt{.dtx}.\\ % \DescribeMacro{\makegobbler}\DescribeMacro{\makeungobbler}Les macros \cs{makegobbler} et \cs{makeungobbler} délèguent le % traitement proprement dit de gobage/dégobage à respectivement \cs{MGB@g} et \cs{MGB@u} avec le préliminaire de % développer en premier lieu \cs{MGB@stdhooks}, ce dont on verra l'utilité en \S\,\ref{sec:hooks} : % \begin{macrocode} \def\makegobbler{\MGB@stdhooks\MGB@g}% \def\makeungobbler{\MGB@stdhooks\MGB@u}% % \end{macrocode} % \DescribeMacro{\MGB@u}La macro \cs{MGB@u} a juste pour effet qu'elle gobe le délimiteur, et le définit % de sorte qu'il se redéfinisse à sa valeur initiale. Donc ce qui suit entre les deux délimiteurs n'est pas gobé. % \begin{macrocode} \def\MGB@u#1{\MGB@save@mark#1\def#1{\MGB@ungobblerhook#1}}% % \end{macrocode} % % \DescribeMacro{\MGB@g}% %La macro \cs{MGB@g} prend en argument une séquence de contrôle \cs{}\meta{delimiteur}, et gobe tout ce qui suit %jusqu'à rencontrer la string \cs{}\meta{delimiteur} : % \begin{macrocode} \def\MGB@g#1{% \MGB@save@mark#1% \begingroup \expandafter\MGB@\expandafter {\string#1}#1\MGB@set@catcoderegime#1}% % \end{macrocode} % \subsection{Gestion des crochets de fin de traitement} % \label{sec:hooks} % Notez que les deux macros \cs{MGBkeepelse} et \cs{MGBdropelse} ne se distinguent respectivement de \cs{MGBkeep} et % \cs{MGBdrop} que par l'insertion de la macro \cs{MGB@elsehooks} au lieu de \cs{MGB@stdhooks}. En fait le c½ur du % réacteur c'est les macros \cs{MGB@g} et \cs{MGB@u}. Chacune des ces macros développe en fin de % traitement respectivement une macro crochet \cs{MGB@gobblerhook}, resp.\ \cs{MGB@ungobblerhook}, dont la valeur standarde \cs{MGB@stdhook} consiste à finir le traitement.\\ % \DescribeMacro{\MGB@stdhooks} La macro \cs{MGB@stdhooks} règle les définitions de ces deux macros crochet à leur valeur % standarde, après avoir empilé la valeur courante : % \begin{macrocode} \def\MGB@stdhooks{% % \end{macrocode} % Donc en premier lieu, avant de faire ce réglage, elle empile la valeur courante des macros crochets, ceci permettant % de cascader plusieurs niveaux de gobage/dégobage avec leur \cs{}\meta{délimiteur} respectifs : % \begin{macrocode} \MGB@pushhooks % \end{macrocode} % puis elle fait le réglage proprement dit aux valeurs standardes des crochets en développant la % macro\cs{MGB@standardizehooks} : % \begin{macrocode} \MGB@standardizehooks } % \end{macrocode} % \DescribeMacro{\MGB@standardizehooks}La macro \cs{MGB@standardizehooks} règle les définitions des deux macros crochet % à leur valeur standarde, c'est à dire celle qui termine le traitement, ou en d'autres termes celle qui correspond au % fait que le \cs{}\meta{délimiteur} est le dernier : % \begin{macrocode} \def\MGB@standardizehooks{% \let\MGB@gobblerhook\MGB@stdhook \let\MGB@ungobblerhook\MGB@stdhook } % \end{macrocode} % \DescribeMacro{\MGB@elsehooks} La macro \cs{MGB@elsehooks} ne fait que changer les définitions de ces macros crochet pour % qu'un dégobage soit fait à la suite d'un gobage, ou resp.\ un gobage à la suite d'un dégobage, ceci permettant de % traiter la branche \texttt{else}. % \begin{macrocode} \def\MGB@elsehooks{% % \end{macrocode} % Comme avec \cs{MGB@stdhooks}, la première chose qu'on fait c'est d'empiler la valeur courante des macros crochet, de % sorte à pouvoir les dépiler en fin de gobage. % \begin{macrocode} \MGB@pushhooks % \end{macrocode} % Donc on règle le crochet de gobage\ldots % \begin{macrocode} \def\MGB@gobblerhook##1{% % \end{macrocode} % pour tout d'abord écraser les valeurs courantes des crochets de gobage/dégobage par ls valeur standardes, sans pour % autant changer l'état de la pile\ldots % \begin{macrocode} \MGB@standardizehooks % \end{macrocode} % et ensuite faire un dégobage : % \begin{macrocode} \MGB@u##1}% % \end{macrocode} % et pour le crochet de dégobage c'est l'inverse\ldots % \begin{macrocode} \def\MGB@ungobblerhook##1{% % \end{macrocode} % comme précédement on règle les macros crochet aux valeurs standardes sans changer l'état de la pile\ldots % \begin{macrocode} \MGB@standardizehooks % \end{macrocode} % mais ensuite on enchaîne sur un gobage au lieu d'un dégobage : % \begin{macrocode} \MGB@g##1}% } % \end{macrocode} % \DescribeMacro{\MGB@stdhook}La macro \cs{MGB@stdhook} est la valeur par défaut des macros crochet, elle finit le % traitement de gobage/dégobage : c'est à dire elle restaure la macro \cs{}\meta{délimiteur} à sa valeur initiale\footnote{Sa valeur avant gobage (\cs{MGB@g}) ou dégobage (\cs{MGB@u}).} : % \begin{macrocode} \def\MGB@stdhook#1{% \MGB@pophooks {\def\@tempa##1{\let#1##1\let##1\@undefined}% \expandafter\expandafter\expandafter}\expandafter \@tempa\csname MGB@save\string#1\endcsname }% % \end{macrocode} % \DescribeMacro{\MGB@save@mark}La restauration se fait à partir d'une sauvegarde faite dans la variable\footnote{La % deuxième contr'oblique est une lettre.} \cs{MGB@save\textbackslash}\meta{délimiteur}. La macro \cs{MGB@save@mark} sert % à effectuer la sauvegarde en début de traitement : % \begin{macrocode} \def\MGB@save@mark#1{% \expandafter\let\csname MGB@save\string#1\endcsname#1}% % \end{macrocode} % \subsection{Gestion de la pile de macros crochet} % \DescribeMacro{\MGB@hook@sd}La macro \cs{MGB@hook@sd} est un compteur qui donne la profondeur dans la pile de macros % crochet (\texttt{sd} = \enquote{\textbf{s}tack \textbf{d}epth}) : % \begin{macrocode} \newcount\MGB@hook@sd % \end{macrocode} % \DescribeMacro{\MGB@pushhooks}La macro \cs{MGB@pushhooks} sert à empiler la valeur courante des macros crochet : % \begin{macrocode} \def\MGB@pushhooks{% \expandafter\let\csname MGB@ghookstack\the\MGB@hook@sd\endcsname\MGB@gobblerhook \expandafter\let\csname MGB@uhookstack\the\MGB@hook@sd\endcsname\MGB@ungobblerhook \advance\MGB@hook@sd\@ne } % \end{macrocode} % \DescribeMacro{\MGB@pophooks}La macro \cs{MGB@pophooks} sert à dépiler les valeurs des macros crochet de sorte à % restituer les valeurs avant le dernier empilement : % \begin{macrocode} \def\MGB@pophooks{% \advance\MGB@hook@sd\m@ne \expandafter\let\expandafter\MGB@gobblerhook \csname MGB@ghookstack\the\MGB@hook@sd\endcsname \expandafter\let\expandafter\MGB@ungobblerhook \csname MGB@uhookstack\the\MGB@hook@sd\endcsname } % \end{macrocode} % Touche finale de la gestion de la pile, les macros crochet de gobage/dégobage sont initialisées pour produire une % erreur indiquant un épuisement de la pile\footnote{\enquote{stack underflow} en langue anglaise}. En effet, si on ne % fait pas cela, et que par malheur survient une situation où se produit un dépilement de plus que d'empilements, alors % on aura un message d'erreur abscons indiquant soit que \cs{MGB@gobblerhook} n'est pas définie, soit que c'est % \cs{MGB@ungobblerhook} qui n'est pas définie. Avec les initialisations suivantes, dans une telle situation au lieu de % cela on a un message d'erreur beaucoup plus explicite : % \begin{macrocode} \def\MGB@gobblerhook#1{% \PackageError{makegobbler}{\'Epuisement pile macros crochet}{% Une erreur a produit un d\'epilage de plus que d'empilage.% } } \let\MGB@ungobblerhook\MGB@gobblerhook % \end{macrocode} % \subsection{Gobage/dégobage dans le cas d'une condition à la \TeX} % \DescribeMacro{\MGBkeep@tex}\DescribeMacro{\MGBdrop@tex} % On commence par le gros morceau, le cas des conditions à la \TeX. En fait on veut grosso modo que % \cs{MGBkeep*}\cs{ifcondition} se développe en : % \begin{verse} % \cs{ifcondition}\\ % \meta{couic}\\ % \quad\cs{expandafter}\cs{MGB@u}\\ % \cs{else}\\ % \quad\cs{expandafter}\cs{MGB@g}\\ % \cs{fi} % \end{verse} % Dans le cas de \cs{MGBdrop} c'est juste l'ordre de \cs{MGB@u} et \cs{MGB@g} qui est inversé. Comme c'est un peu coton % de mettre en clair un \cs{else} ou un \cs{fi} dans un corps de macro sans qu'il n'y ait \cs{ifcondition} également en % clair, on va passer le \cs{else} et le \cs{fi} via des registres toks pour qu'ils ne soient pas en clair. Pour faire % ça on se place au sein d'un groupe, et le boulot sera fait via une macro \cs{@tempa} développée en after-group. % \begin{macrocode} \begingroup % \end{macrocode} % Au fait, \cs{ifcondition} ça peut être n'importe quelle condition à la \TeX, par exemple % \cs{ifnum}\meta{a}\texttt{=}\meta{b}\vs. Du coup pour éviter qu'au cas où l'utilisateur oublierait % l'espace\footnote{Cet espace fait partie du nombre et ne génère pas une espace dans le texte.} juste après le \meta{b} % et où donc la branche vraie serait intempestivement développée entrainant une erreur de type \cs{else} sans \cs{if}, % on insère en général un \cs{relax} après le \cs{ifcondition}, sauf pour les utilisateurs qui aiment vivre % dangereusement et ont passé l'option \texttt{tense} au paquetage. Donc en général \cs{toks0} contient \cs{relax}, sauf % si l'option \texttt{tense} et passée, auquel cas il est vide. % \begin{macrocode} \edef\@tempa{\toks0{\ifMGB@tense\else\relax\fi}}\@tempa % \end{macrocode} % \cs{toks1} contient \cs{else}, et % \begin{macrocode} \toks1\expandafter{\csname else\endcsname}% % \end{macrocode} % \cs{toks2} contient \cs{fi}. % \begin{macrocode} \toks2\expandafter{\csname fi\endcsname}% % \end{macrocode} % Et maintenant on définit \cs{MGBkeep@tex}, et \cs{MGBdrop@tex} dans une macro \cs{@tempa} développée en after-group. % \begin{macrocode} \edef\@tempa{% \def\noexpand\MGBkeep@tex##1{##1\the\toks0 \noexpand\expandafter\noexpand\MGB@u \the\toks1 \noexpand\expandafter\noexpand\MGB@g \the\toks2 }% \def\noexpand\MGBdrop@tex##1{##1\the\toks0 \noexpand\expandafter\noexpand\MGB@g \the\toks1 \noexpand\expandafter\noexpand\MGB@u \the\toks2 }% }% \expandafter\endgroup\@tempa % \end{macrocode} % \subsection{Gobage/dégobage dans le cas d'une condition à la \LaTeX} % \DescribeMacro{\MGBkeep@latex}\DescribeMacro{\MGBdrop@latex} % Le cas des conditions à la \LaTeX\ est beaucoup plus simple à traiter. En fait on veut grosso modo que % \cs{MGBkeep}\texttt{\{}\meta{condition}\texttt{\}} se développe en : % \begin{verse} % \cs{ifthenelse}\texttt{\{}\meta{condition}\texttt{\}}\texttt{\{\%}\\ % \quad\cs{MGB@u}\texttt{\}\{\%}\\ % \quad\cs{MGB@g}\texttt{\}} % \end{verse} % Pour développer \cs{MGB@u} si \meta{condition} est vraie, ou \cs{MGB@g} sinon. Et pour \cs{MGBdrop} c'est l'inverse, % ce qu'on obtient en intervertissant \cs{MGB@u} et \cs{MGB@g}. % \begin{macrocode} \def\MGBkeep@latex#1{\ifthenelse{#1}{\MGB@u}{\MGB@g}} \def\MGBdrop@latex#1{\ifthenelse{#1}{\MGB@g}{\MGB@u}} % \end{macrocode} % \subsection{Macros auxliaires de \cs{MGB@g}} % \DescribeMacro{\MGB@set@catcoderegime}\\ La macro \cs{MGB@set@catcoderegime} sert à changer le régime de catcode % pour que dans le cas du gobage, tout ce qui est gobé soit pris verbatim. % \begin{macrocode} \def\MGB@set@catcoderegime{% \catcode35=12 \catcode123=12 \catcode125=12 \catcode37=12 \catcode92=12 } % \end{macrocode} % \DescribeMacro{\MGB@otherize} La macro \cs{MGB@otherize} change le catcode de chacun des caractères du délimiteur % en other. C'est pour que le délimiteur soit bien reconnu comme marque de fin. % \begin{macrocode} \def\MGB@otherize#1{% \def\@tempa{#1}% \ifx\@tempa\@nnil\else \catcode`#1=12 \expandafter\MGB@otherize \fi } % \end{macrocode} % \DescribeMacro{\MGB@} % La macro \cs{MGB@} est l'auxiliaire de \cs{MGB@g}, elle prend deux arguments :\\ % \begin{tabular}{ll} % \texttt{\#1}&Le délimiteur en tant que string\\ % \texttt{\#2}&Le délimiteur en tant que séquence de contrôle\\ % \end{tabular} % \begin{macrocode} \def\MGB@#1#2{\MGB@otherize#1\@nil\long\def#2##1#1{\endgroup \MGB@gobblerhook#2}}% % \end{macrocode} % E finita la comedia ! % \begin{macrocode} \endinput % \end{macrocode} %^^A End of file `makegobbler.sty'. %^^A Local Variables: %^^A coding: latin-9 %^^A ispell-dictionary: "fr" %^^A mode: DocTeX %^^A compile-command: "make -C ../../../ doc" %^^A End: %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\Finale \endinput