% % \iffalse /!\ this file contains non-ascii -- encoding is utf-8 /!\ % % ted package by Manuel P\'egouri\'e-Gonnard % ----------------------------------------------------------- % % This work may be distributed and/or modified under the conditions of % the LaTeX Project Public License, either version 1.3c of this license % or (at your option) any later version. The latest version of this % license is in: % % http://www.latex-project.org/lppl.txt % % and version 1.3c or later is part of all distributions of LaTeX % version 2006/05/20 or later. % % This work has the LPPL maintenance status `maintained'. % % The current maintainer of this work is Manuel P\'egouri\'e-Gonnard. % % This work consists of the file ted.dtx and the derived files ted.sty, % ted.pdf and ted-fr.pdf. % % %<*gobble> \ProvidesFile{ted.dtx} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{ted} %<*package> % \fi % \ProvidesFile{ted.dtx} [2008/03/07 v1.06 \space a token list editor \space (mpg)] % \iffalse % % \fi % \CheckSum{816} % \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 \~} % \iffalse %<*gobble> \begingroup % %<*batchfile> \input docstrip \keepsilent \preamble ted package by Manuel P\string\'egouri\string\'e-Gonnard % This is a generated file. See ted.dtx for license information. \endpreamble \askforoverwritefalse %\generate{\file{ted.ins}{\from{ted.dtx}{batchfile}}} %\generate{\file{ted.drv}{\from{ted.dtx}{driver}}} \generate{\file{ted.sty}{\from{ted.dtx}{package}}} \generate{\file{ted-fr.drv}{\from{ted.dtx}{pilote}}} % %<*gobble> \endgroup % %<*driver|pilote> \documentclass[oneside, a4paper]{ltxdoc} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage[babel=true, expansion=false]{microtype} \usepackage{fixltx2e} \expandafter\newif\csname iffrenchdoc\endcsname % cachez ce if... %\frenchdoctrue % %<*gobble> \iffrenchdoc % %<*pilote> \usepackage[lmargin=4.5cm, rmargin=3cm]{geometry} \OnlyDescription \usepackage[english, french]{babel} \FrenchFootnotes \AddThinSpaceBeforeFootnotes \newcommand*\eng[1]{\emph{\foreignlanguage{english}{#1}}} \usepackage[bookmarks=false]{hyperref} \hypersetup{% pdftitle=L'extension ted pdfsubject=Un éditeur de liste de lexèmes pour LaTeX2e} % %<*gobble> \else % %<*driver> \AlsoImplementation \usepackage[english]{babel} \usepackage[bookmarks=true, bookmarksnumbered=true, bookmarksopen=true, bookmarksopenlevel=2]{hyperref} \hypersetup{% pdftitle=The ted package, pdfsubject=A token list editor for LaTex2e} \settowidth\MacroIndent{\rmfamily\scriptsize 000\ } \setlength\MacroTopsep{0pt} \setcounter{tocdepth}{1} \usepackage[nohints, english]{minitoc} \mtcsetpagenumbers{secttoc}{off} \mtcsetrules{secttoc}{off} \mtcsetdepth{secttoc}{3} \setlength{\stcindent}{0pt} \mtcsetfont{secttoc}{subsection}{\normalfont} \newcommand\tocwithmini{% \dosecttoc[n] \setcounter{tocdepth}{1}\tableofcontents \setcounter{tocdepth}{3}\faketableofcontents } % %<*gobble> \fi % %<*driver|pilote> \hypersetup{% colorlinks=true, linkcolor=black, urlcolor=black, pdfauthor=Manuel Pégourié-Gonnard} \newcommand\pf{\textsf} \newcommand\optstar{\meta{$*$}} \newcommand\topcs[1]{\texorpdfstring{\cs{#1}}{#1}} \begin{document} \DocInput{ted.dtx} \end{document} % %<*package> % \fi % % \GetFileInfo{ted.dtx} % % \title{\iffrenchdoc L'extension \pf{ted}\else The \pf{ted} package\fi} % \author{Manuel Pégourié-Gonnard\\ % \href{mailto:mpg@elzevir.fr}{mpg@elzevir.fr}} % \date{\fileversion\ (\filedate)} % % \maketitle % \iffrenchdoc\else \tocwithmini \fi % % \section{Introduction} % % \iffrenchdoc % % Le nom de l'extension \pf{ted} signifie \eng{token list editor}, soit % en français \og éditeur de listes de lexèmes \fg{}. Comparé à % \texttt{sed} dont son nom s'inspire, il n'est pas très puissant : il % ne sait faire actuellement que deux choses avec les listes de lexèmes, % à savoir les afficher en détail, et y opérer des substitutions. % Toutefois, sa caractéristique principale est de travailler vraiment au % niveau des lexèmes, et non des simples caractères. % % L'extension \pf{ted} est capable de faire des substitutions même à % l'intérieur d'une paire d'accolades, et n'a pas de problèmes avec des % lexèmes particuliers. En fait, elle est conçue pour fonctionner même % avec des listes comportant des lexèmes très exotiques. % % \else % % Just like \texttt{sed} is a stream editor, \pf{ted} is a token list % editor. Actually, it is not as powerful as \texttt{sed}, but its % main feature is that it really works with tokens, not only characters. % At the moment, it can do only two things with token lists: display it % with full information on each token, and perform substitutions (that % is, replacing every occurrence of a sublist with another token list). % % The \pf{ted} package can perform substitutions inside groups, and % don't forbid any token in the lists. Actually, \pf{ted} is designed to % work well even if strange tokens (that is, unusual (charcode, % \cs{catcode}) pairs or tokens with a confusing \cs{meaning}) occur in % the list. % % \fi % % \section{Usage} % % \iffrenchdoc % % L'extension \pf{ted} définit essentiellement deux macros publiques : % \cs{Substitute} et \cs{ShowTokens}. La première est la raison d'être % de \pf{ted}, mais au cours du développement de l'extension, la partie % la plus difficile et intéressante a été d'être capable d'écrire la % deuxième. J'ai donc décidé de la proposer à l'utilisateur, car je % pense qu'elle peut être utile, soit pour déboguer du code, soit pour % apprendre \TeX. % % \subsection{\topcs{Substitute}} % % \DescribeMacro{\Substitute} % La syntaxe de \cs{Substitute} est la suivante. % \begin{quote} % \cs{Substitute}\optstar\oarg{sortie}\marg{entrée}\marg{de}\marg{vers} % \end{quote} % Commençons par l'usage le plus simple : sans étoile ni argument % optionel. Sous cette forme, \cs{Substitute} remplace chaque occurrence % de la sous-liste \meta{de} par \meta{vers} dans l'\meta{entrée}, et % place le résultat dans le registre à lexèmes \cs{ted@toks}. Comme % \cs{Substitute} est sans doute destiné à être utilisé par des auteurs % de classe ou d'extensions, le |@| dans le nom de ce registre ne % devrait pas poser de problèmes la plupart du temps. % % Quoi qu'il en soit, vous pouvez changer facilement le nom du registre % utilisé pour la sortie avec l'argument optionnel en spécifiant le nom % d'un registre à lexèmes dans \meta{sortie}. En fait, vous voulez % peut-être que la sortie soit placée dans une macro et non un registre % : dans ce cas, vous pouvez spécifier par exemple \cs{def}\cs{macro} % (ou \cs{long}\cs{def}\cs{macro} etc.) comme argument optionnel. Dans % tous les cas, \meta{sortie}|{trucs}| doit être une syntaxe légale % d'affectation de |truc| dans la sortie. Bien sûr, si vous demandez à % ce que la sortie soit placée dans une macro, vous devez veiller à ce % qu'elle ne contienne pas de dièses (caractère de paramètre) mal % placés. Exemples : % % \begin{quote} % |\Substitute{a#b#c}{a}{A}|\\ % |\newtoks\vostoks \Substitute[\vostoks]{a#b#c}{a}{A}|\\ % |\Substitute[\def\votremacro]{a#b#c}{#}{##}| % \end{quote} % % La version étoilée de \cs{Substitute} a pour but de vous simplifier la % vie quand vous ne voulez pas spécifier explicitement une liste de % lexèmes en entrée, mais plutôt utiliser le contenu d'une macro ou d'un % registre, en développant une fois son premier argument obligatoire % avant de commencer à travailler dessus. Ceci vous évite d'avoir à % placer vous-même des \cs{expandafter}, surtout dans le cas ou vous % souhaitez utiliser l'argument optionnel. Cette fois, l'usage est % inversé par rapport à l'argument optionnel : c'est la cas d'une macro % qui est le plus naturel. Pour un registre de lexèmes, vous devez % écrire le \cs{the} vous même : ainsi, votre \meta{entrée} pourra être % de la forme \cs{macro}, ou \cs{the}\cs{toksreg}, ou toute autre chose % dont le 1-développement donne ce que vous voulez. Par exemple : % % \begin{quote} % |\def\abc{abccdef} \newtoks\abctoks \abctoks{abc}|\\ % |\Substitute{\abc}{cc}{C} %| donne |\abc|\\ % |\Substitute*{\abc}{cc}{C} %| donne |abCdef|\\ % |\Substitute*{\the\abctoks}{cc}{C} %| aussi % \end{quote} % % La version avec deux étoiles a aussi pour but de vous épargner la % peine de contrôler vous-même le développement des arguments. Elle % fonctionne comme la version étoilée simple, mais développe cette fois % ses trois arguments obligatoires une fois avant de commencer à % travailler. La même remarque que pour la version étoilée simple % s'applique concernant les macros et les registres à lexèmes. J'espère % que ces trois cas (de zéro à deux étoiles) couvriront la plupart des % usage courants. Pour une gestion plus souple du développement des % arguments, attendez \LaTeX$3$ ! % % Le comportement de \cs{Substitute} devrait être évident la plupart du % temps. Seul un cas particulier mérite sans doute une petite remarque : % dans le cas ou la liste \meta{de} est vide, la liste \meta{vers} est % insérée entre chaque paire de lexèmes de l'\meta{entrée} : en % particulier elle n'est pas insérée au début ni à la fin. Par exemple, % |\Substitute{abc}{}{1}| placera |a1b1c| dans \cs{ted@toks}. % % Enfin, il peut être utile de savoir qu'une fois que \cs{Substitute} a % fini son travail, le nombre de substitutions effectuées est accessible % dans le registre \cs{ted@count}. On peut ainsi s'en servir pour % compter, par exemple, le nombre d'espaces (donc approximativement de % mots) dans un texte, en faisant semblant d'opérer une substitution % dessus. % % \subsection{\topcs{ShowTokens}} % % \DescribeMacro{\ShowTokens} % La syntaxe de \cs{ShowTokens} est la suivante. % \begin{quote} % \cs{ShowTokens}\optstar\marg{liste} % \end{quote} % Dans sa forme simple, \cs{ShowTokens} se contente d'afficher la liste % de lexèmes, un par ligne. Pour les lexèmes de type caractère, % l'affichage comporte le caractère lui-même, suivi de l'indication de % son code de catégorie sous la forme utilisée par \cs{show}. Je % rappelle ci-dessous (table~\ref{cc}) pour la commodité du lecteur les % différents \cs{catcode}s possibles dans une liste de lexème, ainsi % qu'un exemple et la façon dont ils sont affichés par \cs{ShowTokens}. % % \begin{table} % \begin{tabular}{rcl} % 1 & |{| & |(begin-group character {)|\\ % 2 & |}| & |(end-group character })|\\ % 3 & |$| & |(math shift character $)|\\ % 4 & |&| & |(alignment tab character &)|\\ % 6 & |#| & |(macro parameter character #)|\\ % 7 & |^| & |(superscript character ^)|\\ % 8 & |_| & |(subscript character _)|\\ % 10 & | | & |(blank space )|\\ % 11 & |a| & |(the letter a)|\\ % 12 & |0| & |(the character 0)|\\ % 13 & |~| & |(active character=macro:->\nobreakspace {})|\\ % \end{tabular} % \caption{Les \cs{catcode} : code, exemple, et description.}\label{cc} % \end{table} % % Pour les séquence de contrôles et les caractères actifs, le (début du) % \cs{meaning} est également affiché, sans dépasser les~$80$ colonnes de % large afin de ne pas perturber l'affichage par ligne. Il s'agit bien % sûr du sens courant au moment de l'appel à \cs{ShowTokens}. % % \DescribeMacro{\ShowTokensLogonly} \DescribeMacro{\ShowTokensOnline} % Le comportement par défaut est d'afficher ces listes à la fois sur le % terminal et dans le fichier log. Si vous préférez que l'affichage % n'ait lieu que dans le fichier log, vous n'avez qu'à dire % \cs{ShowTokensLogonly}. Si vous souhaitez ensuite revenir au % comportement par défaut, dites seulement \cs{ShowTokensOnline}. % % La version étoilée de \cs{ShowTokens} fonctionne de la même façon que % dans le cas de \cs{Substitute} en développant son argument une fois % avant d'en commencer l'analyse. La même remarque que précédemment % s'applique concernant les macros et les registres. Imaginons par % exemple que vous vouliez vérifier, après la définition d'une macro, % que vous avez bien les bons \cs{catcode}s : % % \begin{quote} % |\begingroup \uccode`\~=32 \uppercase{\endgroup|\\ % | \def\macro{1~2}}|\\ % |\ShowTokens*{\macro} %| donne à l'écran : [...]\\ % |1 (the character 1)|\\ % | (active character=macro:-> )|\\ % |2 (the character 2)| % \end{quote} % % \medskip % J'aimerais conclure par la remarque suivante : au cours de la % conception de \pf{ted}, j'ai vraiment essayé de ne faire aucune % hypothèse sur les lexèmes présents dans la liste. Ainsi, vous pouvez % utiliser librement des accolades, des dièses, des espaces, des % \cs{par}, des \cs{if}s, des \cs{bgroup} ou \cs{egroup} dans toutes les % listes de lexèmes. À ma connaissance à ce jour, la seule limitation % est que les séquences de contrôle qui apparaissent ne doivent pas être % (ou être \cs{let}-égales à) des macros intimes de \pf{ted}, % c'est-à-dire celles commençant par \cs{ted@@}. % % \begin{quote} % Vous savez maintenant tout ce qu'il y a à savoir sur l'utilisation de % \pf{ted}. Si vous souhaitez vous pencher sur son implémentation, il % vous faudra lire les commentaires en anglais car je n'ai pas eu le % courage de documenter mon code en deux langues. % \end{quote} % % \begin{center}\large % C'est tout pour cette fois ! \\ % Amusez-vous bien avec \LaTeX{} ! % \end{center} % % \else % % The \pf{ted} package provides two user macros: \cs{Substitute} and % \cs{ShowTokens}. The first one is the primary goal of the package, but % to be able to do the second was the more interesting part while % writing the package. I made it into a user macro since I believe it % can be useful for debugging things, or for learning \TeX. % % \subsection{\topcs{Substitute}} % % \DescribeMacro{\Substitute} % The syntax of \cs{Substitute} is as follows. % \begin{quote} % \cs{Substitute}\optstar\oarg{output}\marg{input}\marg{from}\marg{to} % \end{quote} % Let's begin with the basics. Without star or optional argument, the % \cs{Substitute} macro will replace each occurrence of the \meta{from} % token list with \marg{to} in the \meta{input}, and put the result in % the \cs{toks} register \cs{ted@toks}. This macro has a |@| in its % name, but since I think the \cs{Substitute} macro will be essentially % be used by class or package writers, this should be ok. % % Anyway, if you don't like this name, you can specify another one as % \meta{output} using the optional argument. Your \meta{output} should % be the name of a \cs{toks} register. If you want the output to be put % in a macro, use \cs{def}\cs{macro} (or \cs{long}\cs{def}\cs{macro} % or\ldots) as the optional argument. Anyway, \meta{output}\marg{stuff} % must be a legal syntax for an assignment: using \cs{macro} as optional % argument will not work (and may actually result in chaos). Of course, % if you want your output to be placed in a macro, it should not contain % improperly placed hash signs (that is, macro parameter tokens). % % \begin{quote} % |\Substitute{a#b#c}{a}{A}|\\ % |\newtoks\yourtoks \Substitute[\yourtoks]{a#b#c}{a}{A}|\\ % |\Substitute[\def\yourmacro]{a#b#c}{#}{##}| % \end{quote} % % The one-starred form of \cs{Substitute} is meant to help you when your % \meta{input} is not an explicit token list, but the contents of either % a macro or a \cs{toks} register, by expanding once its first mandatory % argument before proceeding. It spares you the pain of using % \cs{expandafter}s, especially in case you want to use the optional % argument too. This time, things are reversed compared to the optional % argument : using a macro instead of a toks register is easier. % Actually, with the starred form, the first argument can be \cs{macro} % or \cs{the}\cs{toksreg}, or anything whose one-time expansion is the % token list you want \cs{Substitute} to act upon. % % \begin{quote} % |\def\abc{abccdef} \newtoks\abctoks \abctoks{abc}|\\ % |\Substitute{\abc}{cc}{C} %| gives |\abc|\\ % |\Substitute*{\abc}{cc}{C} %| gives |abCdef|\\ % |\Substitute*{\the\abctoks}{cc}{C} %| too % \end{quote} % % The two-starred form is also meant to avoid you trouble with % development. It expands its three mandatory arguments once before % executing. The remark about macros and \cs{toks} register still % holds. I hope this three cases (from zero to two stars) will suffice % for most purpose. For a better handling of arguments expansion, wait % for \LaTeX$3$! % % The action of \cs{Substitute} is pretty obvious most of the time. % Maybe a particular case needs some precision: when \meta{from} is % empty, then the \meta{to} list gets inserted between each two tokens % of the \cs{input}, but not before the first one. For example, % \cs{Substitute}|{abc}{}{1}| puts |a1b1c| in \cs{ted@toks}. % % Finally, it may be useful to know that, after \cs{Subsitute} finished % its job, it leaves the number of replaced occurrences in the count % register \cs{ted@count}. This can be used, for example, to count % spaces (hence words) in a text, by making a fake substitution on it. % % \subsection{\topcs{ShowTokens}} % % \DescribeMacro{\ShowTokens} % The syntax of \cs{ShowTokens} is as follows. % \begin{quote} % \cs{ShowTokens}\optstar\marg{list} % \end{quote} % In its simple form, \cs{ShowTokens} just shows the list, one token per % line. For characters tokens, its prints the character, and its % category code in human-friendly form. For the sake of readability, % here is (table~\ref{cc}) a reminder of the possible \cs{catcode}s, % with an exemple and the way \cs{ShowTokens} displays them. % % \begin{table} % \begin{tabular}{rcl} % 1 & |{| & |(begin-group character {)|\\ % 2 & |}| & |(end-group character })|\\ % 3 & |$| & |(math shift character $)|\\ % 4 & |&| & |(alignment tab character &)|\\ % 6 & |#| & |(macro parameter character #)|\\ % 7 & |^| & |(superscript character ^)|\\ % 8 & |_| & |(subscript character _)|\\ % 10 & | | & |(blank space )|\\ % 11 & |a| & |(the letter a)|\\ % 12 & |0| & |(the character 0)|\\ % 13 & |~| & |(active character=macro:->\nobreakspace {})|\\ % \end{tabular} % \caption{Possible \cs{catcode}s: code, example, and description.}\label{cc} % \end{table} % % For control sequences and active characters, it % also prints their current \cs{meaning} as a bonus, or only the % beginning of it (ending with \cs{ETC.}) if it is more than one line % ($80$ columns) long. % % \DescribeMacro{\ShowTokensLogonly} % \DescribeMacro{\ShowTokensOnline} % The default is to show this list both in the terminal and in the log % file. If you don't want it to be printed on the terminal, just say % \cs{ShowTokensLogonly}. If you change your mind latter, you can % restore the default behaviour with \cs{ShowTokensOnline}. % % The starred form of \cs{ShowTokens} works the same as for % \cs{Substitute}: it expands its argument once before analysing and % displaying it. The same remarks hold: use \cs{macro} or % \cs{the}\cs{toksreg} in the argument. % % \begin{quote} % |\begingroup \uccode`\~=32 \uppercase{\endgroup|\\ % | \def\macro{1~2}}|\\ % |\ShowTokens*{\macro} %| prints on screen: [...]\\ % |1 (the character 1)|\\ % | (active character=macro:-> )|\\ % |2 (the character 2)| % \end{quote} % % \medskip % I would like to conclude with the following remark: I have really % tried to make sure \pf{ted}'s macros will work fine even with the % wierdest token list. In particular, you can freely use begin-group % and end-group characters, hash signs, spaces, \cs{bgroup} and % \cs{egroup}, \cs{par}, \cs{if}s, as well as exotic % charcode-\cs{catcode} pairs in every argument of the macros. As far as % I am aware, the only restriction is you should not use the very % private macros of \pf{ted} (those beginning with \cs{ted@@}) in your % token lists. % % \fi % % \StopEventually{} % % \section{Implementation} % % A important problem, when trying to substitute things in token lists, % is to handle begin-group and end-group tokens, since they prevent us % from to reading the tokens one by one, and tend to be difficult to % handle individually. Two more kinds of tokens are special: the space % tokens, since they\footnote{Actually, only tokens with charcode $32$ % and \cs{catcode}~$10$ (i.e. $32_{10}$ tokens) are concerned.} cannot % be grabbed as the non-delimited argument of a macro, and the parameter % tokens (hash signs), since they cannot be part of the delimiters in % the parameter text of a macro. From now on, ``special tokens'' thus % denotes tokens with \cs{catcode} $1$, $2$, $6$ or $10$. % % To get rid of these problems, the \cs{Substitute} command proceeds in % three steps. First, encode the input, replacing all special tokens % with nice control sequences representing them, then do the actual % substitution, and finally decode the output, replacing the special % control sequences with the initial special tokens. % % Encoding is the hard part. The idea is to try reading the tokens one % by one; for this we have two means: using a macro with one % non-delimited argument, or something like \cs{let}. The former doesn't % work well with \cs{catcode}~$1$, $2$ or $10$ tokens, and the later do % not see the name of the token (its character code, or its name for a % CS). So we need to use both \cs{futurelet}, a ``grabbing'' macro with % argument, and \cs{string} in order to scan the tokens. Actually, the % encoding proceeds in two passes: in the first, we try and detect the % special tokens, storing their character codes for later use, then do % the actual encoding in the last pass. % % Decoding also processes the tokens one by one, and is simpler, since % special cases are already detected. There is, however, a trick with % groups since, when we encounter a begin-group character, we have to % wait for the corresponding end-group before adding the whole thing to % the output. There is also a simpler version of decoding, for % \cs{ShowTokens}, for screen/log output, with no need to use this % trick, since it only outputs \cs{catcode}-$12$ characters. Finally, % the substitution part uses a macro with delimited argument, defined on % the fly. % % The code is divided as follows. % \par\vspace{-0.5\baselineskip} % \secttoc % \par\vspace{-0.5\baselineskip} % % \begin{macro}{\ted@toks} % \begin{macro}{\ted@list} % \begin{macro}{\ted@code} % Before we begin, just allocate (or give a nice name to) a few % registers. % \begin{macrocode} \@ifdefinable\ted@toks{\newtoks\ted@toks} \@ifdefinable\ted@list{\let\ted@list\toks@} \@ifdefinable\ted@code{\let\ted@code\count@} \@ifdefinable\ted@count{\newcount\ted@count} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Encoding} % % \begin{macro}{\ted@encloop} % \begin{macro}{\ted@encloop@} % The two passes use the same loop for reading the input almost token % by token. This loop grabs the next token through a % \cs{futurelet}\ldots % \begin{macrocode} \newcommand\ted@encloop{% \futurelet\@let@token \ted@encloop@} % \end{macrocode} % \ldots then looks at it with some \cs{ifx} and \cs{ifcat} (non nested, % since the token could be an \cs{if} itself), in order to distinguish % between three cases: normal token, end reached, or special token. In % the later case, remember which kind of special token it is, using a % numeric code. % \begin{macrocode} \newcommand\ted@encloop@{% \let\next\ted@do@normal \ifx\@let@token\ted@@end \let\next\ted@gobble@end \fi \ifcat\noexpand\@let@token##% \ted@code0 \let\next\ted@do@special \fi \ifcat\noexpand\@let@token\@sptoken \ted@code1 \let\next\ted@do@special \fi \ifcat\noexpand\@let@token\bgroup \ted@code2 \let\next\ted@do@special \fi \ifcat\noexpand\@let@token\egroup \ted@code3 \let\next\ted@do@special \fi \next} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ted@@end} % \begin{macro}{\ted@gobble@end} % Here we used the following to detect the end, then gobble it when % reached. % \begin{macrocode} \newcommand\ted@@end{\ted@@end@} % \end{macrocode} % \begin{macrocode} \@ifdefinable\ted@gobble@end{% \def\ted@gobble@end\ted@@end{}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\ted@sanitize} % \begin{macro}{\ted@@active} % Now, this detection method, with \cs{futurelet} and \cs{ifcat}, is % unable to distinguish the following three cases for potential special % tokens: (i) a ``true'' (explicit) special token, (ii) a CS % \cs{let}-equal to a special token, (iii) an active character % \cs{let}-equal to a special token. While this is pre-scanning's job % to detect the (ii) case, the (iii) can be easily got rid of by % redefining locally all active characters. % \begin{macrocode} \count@\catcode\z@ \catcode\z@\active \newcommand\ted@sanitize{% \count@\z@ \@whilenum\count@<\@cclvi \do{% \uccode\z@\count@ \uppercase{\let^^00\ted@@active}% \advance\count@\@ne}} \catcode\z@\count@ % \end{macrocode} % \begin{macrocode} \newcommand\ted@@active{\ted@@active@} % \end{macrocode} % This sanitizing macro also mark active characters by \cs{let}-ing them % equal to \cs{ted@@active} in order to detect them easily later, for % example while displaying on-screen token analysis. All operations % (scanning, replacing, display and decoding) are going to happen inside % a group where \cs{ted@sanitize} has been executed, so that active % characters are no longer an issue. \end{macro} \end{macro} % % \begin{macro}{\ted@encode} \begin{macro}{\ted@do@normal} % \begin{macro}{\ted@do@special} The \cs{ted@encode} macro is the master % macro for encoding. It only initialise a few things and launches the % two loops. We select one of the tree steps by \cs{let}-ing % \cs{ted@do@normal} and \cs{ted@do@special} to the appropriate action. % \begin{macrocode} \newcommand\ted@encode[1]{% \ted@list{}% \let\ted@do@normal\ted@gobble@encloop \let\ted@do@special\ted@scan@special \ted@encloop#1\ted@@end \ted@toks{}% \let\ted@do@normal\ted@addtoks@encloop \let\ted@do@special\ted@special@out \ted@encloop#1\ted@@end \ted@assert@listempty} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\ted@assert@listempty} % After the last loop, \cs{ted@list} should be empty. If it's not, it % means something very weird happened during the encoding procedure. I % hope the code below will never be executed :) % \begin{macrocode} \newcommand\ted@assert@listempty{% \edef\next{\the\ted@list}% \ifx\next\@empty \else \PackageError{ted}{% Assertion `\string\ted@list\space is empty' failed}{% This should not happen. Please report this bug to the author. \MessageBreak By the way, you're in trouble there... I'm sorry.}% \fi} % \end{macrocode} % \end{macro} % % \subsubsection{Pre-scanning} % % \begin{macro}{\ted@gobble@encloop} % For normal tokens, things are pretty easy: just gobble them! % \begin{macrocode} \newcommand\ted@gobble@encloop{% \afterassignment\ted@encloop \let\@let@token= } % \end{macrocode} % \end{macro} % \begin{macro}{\ted@scan@special} % For special tokens, it's harder. We must distinguish explicit % character tokens from control sequences \cs{let}-equal to special % tokens. For this, we use \cs{string}, then grab the next character to % see whether its code is \cs{escapechar} or not. Actually, things are % not this easy, for two reasons. First, we have to make sure the next % character's code is not already \cs{escapechar} before the % \cs{string}, by accident. For this purpose, we set \cs{escapechar} % to~$0$ except if next character's code is also~$0$, in which case we % prefer~$1$. % \begin{macrocode} \count@\catcode\z@ \catcode\z@ 12 \newcommand\ted@scan@special{% \begingroup \escapechar\if\@let@token^^00 \@ne \else \z@ \fi \expandafter\ted@check@space\string} \catcode\z@\count@ % \end{macrocode} % \end{macro} % \begin{macro}{\ted@check@space} % \begin{macro}{\ted@check@space@} % Second, we have to handle carefully the case of the next token being % the $32_{10}$ token, since we cannot grab this one with a macro. We % are in this case if and only if the token we just \cs{string}ed was a % character token with code $32$, and it is enough to check if next % token's \cs{catcode} is $10$ in order to detect it, since it will be % $12$ otherwise. In order to check this, we use \cs{futurelet} again % for pre-scanning. % \begin{macrocode} \newcommand\ted@check@space{% \futurelet\@let@token \ted@check@space@} % \end{macrocode} % \begin{macrocode} \newcommand\ted@check@space@{% \ifcat\@let@token\@sptoken \endgroup \ted@addlist{32}% \expandafter\ted@gobble@encloop \else \expandafter\ted@list@special \fi} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ted@list@special} % Now that we got rid of this nasty space problem, we know for sure that % the next token has \cs{catcode} $12$, so we can easily grab it as an % argument, find its charcode, and decide whether the original token was % a control sequence or not. Note the \cs{expandafter} over % \cs{endgroup} trick, since we need to add the charcode to the list % outside the group (opened for the modified \cs{escapechar}) though it % was set inside. % \begin{macrocode} \newcommand*\ted@list@special[1]{% \ted@code`#1\relax \expandafter\expandafter\expandafter \endgroup \ifnum\ted@code=\escapechar \ted@addlist{\m@ne}% \else \expandafter\ted@addlist\expandafter{\the\ted@code}% \fi \ted@encloop} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@addlist} % Here we used the following macro to add an element to the list, which % is space-separated. % \begin{macrocode} \newcommand*\ted@addlist[1]{% \ted@list\expandafter{\the\ted@list#1 }} % \end{macrocode} % \end{macro} % % \subsubsection{Actually encoding} % % Remember that, before this last encoding pass, \cs{ted@encode} did the % following: % \begin{quote} % \cs{let}\cs{ted@do@normal}\cs{ted@addtoks@encloop}\\ % \cs{let}\cs{ted@do@special}\cs{ted@special@out} % \end{quote} % \begin{macro}{\ted@addtoks@encloop} % The first one is very easy : normal tokens are just grabbed as % arguments and appended to the output, then the loop continues. % \begin{macrocode} \newcommand\ted@addtoks@encloop[1]{% \ted@toks\expandafter{\the\ted@toks#1}% \ted@encloop} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@special@out} % Special tokens need to be encoded, but before, just check if they are % really special: they aren't if the corresponding code is $-1$. % \begin{macrocode} \newcommand\ted@special@out{% \ifnum\ted@list@read=\m@ne \ted@list@advance \expandafter\ted@cs@clean \else \expandafter\ted@special@encode \fi} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@cs@clean} % Even if the potentially special token was not a real one, we have work % to do. Indeed, in the first pass we did break it using a \cs{string}, % and thus we introduced some foreign tokens in the stream. Most of them % are not important since they have \cs{catcode}~$12$. Anyway, some of % them may be space tokens : in this case we have extra $32$'s in our % list. So, we need to check this before going any further. % \begin{macrocode} \newcommand\ted@cs@clean[1]{% \expandafter\ted@add@toks{#1}% \expandafter\ted@cscl@loop\string#1 \@nil} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@cscl@loop} % We first add the CS to the output, then break it with a \cs{string} in % order to look at its name with the following loop. It first grabs % everything to the first space\ldots % \begin{macrocode} \@ifdefinable\ted@cscl@loop{% \def\ted@cscl@loop#1 {% \futurelet\@let@token \ted@cscl@loop@}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@cscl@loop@} % \ldots and carefully look at the next token in order to know if we are % finished or not. % \begin{macrocode} \newcommand\ted@cscl@loop@{% \ifx\@let@token\@nil \expandafter\ted@gobble@encloop \else \ted@list@advance \expandafter\ted@cscl@loop \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\ted@special@encode} % Now, let's come back to the special tokens. As we don't need the token % to encode it (we already know its \cs{catcode} from \cs{ted@code}, % and its charcode is stored in the list), we first gobble it in order % to prepare for next iteration. % \begin{macrocode} \newcommand\ted@special@encode{% \afterassignment\ted@special@encode@ \let\@let@token= } % \end{macrocode} % \end{macro} % \begin{macro}{\ted@special@encode@} % Then we encode it in two steps : first, create a control sequence with % name \cs{ted@@}\meta{code}\meta{charcode}, where code is a digit % denoting\footnote{I don't store the \cs{catcode} for two reasons: % first, having a single digit is easier; second, having the true % catcode would be useless (though it could maybe make the code more % readable).} the \cs{catcode} of the special token, \ldots % \begin{macrocode} \newcommand\ted@special@encode@{% \expandafter\ted@special@encode@@\expandafter{% \csname ted@@\the\ted@code\ted@list@read\endcsname}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@special@encode@@} % \begin{macro}{\ted@@special} % \ldots then, mark this CS as a special token encoding, in order to % make it easier to detect later, add it to the output and loop again. % \begin{macrocode} \newcommand*\ted@special@encode@@[1]{% \ted@list@advance \let#1\ted@@special \ted@addtoks@encloop{#1}} % \end{macrocode} % \begin{macrocode} \newcommand\ted@@special{\ted@@special@} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\ted@list@read} % \begin{macro}{\ted@list@read@} % Here we used the following macros in order to manage our charcode list. % The reading one is fully expandable. % \begin{macrocode} \newcommand\ted@list@read{% \expandafter\ted@list@read@\the\ted@list\@nil} % \end{macrocode} % \begin{macrocode} \@ifdefinable\ted@list@read@{% \def\ted@list@read@#1 #2\@nil{% #1}} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ted@list@advance} % \begin{macro}{\ted@list@advance@} % Since it's expandable, it cannot change the list, so we need a % separate macro to remove the first element from the list, once read. % \begin{macrocode} \newcommand\ted@list@advance{% \expandafter\ted@list@advance@\the\ted@list\@nil} % \end{macrocode} % \begin{macrocode} \@ifdefinable\ted@list@advance@{ \def\ted@list@advance@#1 #2\@nil{% \ted@list{#2}}} % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Decoding} % % \begin{macro}{\ted@add@toks} % Main decoding macro is \cs{ted@decode}. It is again a loop, processing % the token list one by one. For normal tokens, things are easy as % always: just add them to the output, via % \begin{macrocode} \newcommand\ted@add@toks[1]{% \ted@toks\expandafter{\the\ted@toks#1}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@decode} % Encoded special tokens are easily recognized, since they were \cs{let} % equal to \cs{ted@@special}. In order to decode it, we use the name of % the CS. The following macro uses \LaTeX-style \cs{if} in order to % avoid potential nesting problems when \cs{ifs} are present in the % token list being processed. % \begin{macrocode} \newcommand\ted@decode[1]{% \ifx#1\ted@@end \expandafter\@gobble\else\expandafter\@firstofone\fi{% \ifx#1\ted@@special \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi{% \begingroup \escapechar\m@ne \expandafter\endgroup \expandafter\ted@decode@special\string#1\@nil }{% \ted@add@toks{#1}}% \ted@decode}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@decode@special} % The next macro should then gobble the |ted@@| part of the CS name, and % use the last part as two numeric codes (here we use the fact that the % first one is only a digit). % \begin{macrocode} \@ifdefinable\ted@decode@special{% \begingroup\escapechar\m@ne \expandafter\endgroup\expandafter \def\expandafter\ted@decode@special\string\ted@@#1#2\@nil{% % \end{macrocode} % It then proceeds according to the first code, building back the % original token and adding it to the output. The first two kinds of % tokens (macro parameter characters and blank spaces) are easily dealt % with. % \begin{macrocode} \ifcase#1 \begingroup \uccode`##=#2 \uppercase{\endgroup \ted@add@toks{##}}% \or \begingroup \uccode32=#2 \uppercase{\endgroup \ted@add@toks{ }}% \or % \end{macrocode} % For begin-group and end-group characters, we have a problem, since % they are impossible to handle individually: we can only add a % \meta{balanced text} to the output. So, when we find a begin-group % character, we just open a group (a real one), and start decoding again % inside the group, until we find the corresponding end-group character. % Then, we enclose the local decoded list of tokens into the correct % begin-group/end-group pair, and then add it to the output one group % level below, using the \cs{expandafter}-over-\cs{endgroup} trick % (essential here). % \begin{macrocode} \begingroup \ted@toks{}% \uccode`{=#2 \or \uccode`}=#2 \uppercase{\ted@toks\expandafter{\expandafter{\the\ted@toks}}}% \expandafter\endgroup \expandafter\ted@add@toks\expandafter{\the\ted@toks}% \fi}} % \end{macrocode} % \end{macro} % % \subsection{Substitution} % % For this part, the idea\footnote{for which I am grateful to Jean-Côme % Charpentier, who first taught me the clever use delimited arguments % (and lots of other wonderful things) in \nolinkurl{fr.comp.text.tex}} % is to use a macro whose first argument is delimited with the % \meta{from} string, which outputs the first argument followed by the % \meta{to} string, and loops. Obviously this macro has to be defined on % the fly. All tokens lists need to be encoded first, and the output % decoded at end. Since all this needs to happens inside a group (for % \cs{ted@sanitize} and the marking up of special-characters control % sequences), remember to ``export'' \cs{ted@toks} when done. % % \begin{macro}{\ted@Substitude} % The main substitution macro is as follows. Arguments are \meta{input}, % \meta{from}, \meta{to}. \cs{ted@output} will be discussed later. % \begin{macrocode} \newcommand\ted@Substitute[3]{% \begingroup \ted@sanitize \ted@encode{#3}% \expandafter\ted@def@subsmac\expandafter{\the\ted@toks}{#2}% \ted@encode{#1}% \ted@subsmac \ted@toks\expandafter{\expandafter}% \expandafter\ted@decode\the\ted@toks\ted@@end \expandafter\endgroup \expandafter\ted@output\expandafter{\the\ted@toks}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@def@subsmac} % The actual iterative substitution macro is defined by the following % macro, whose arguments are the \meta{to} string, encoded, and the % plain \meta{from} string. % \begin{macrocode} \newcommand\ted@def@subsmac[2]{% \ted@encode{#2}% \long\expandafter\def\expandafter\ted@subsmac@loop \expandafter##\expandafter1\the\ted@toks##2{% \ted@add@toks{##1}% \ifx##2\ted@@end \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi{% \expandafter\ted@remove@nil\the\ted@toks }{% \global\advance\ted@count\@ne \ted@add@toks{#1}\ted@subsmac@loop##2}}% \expandafter\ted@def@subsmac@\expandafter{\the\ted@toks}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@def@subsmac@} % While we have the encoded \meta{from} string at hand, define the % start-loop macro. % \begin{macrocode} \newcommand\ted@def@subsmac@[1]{% \def\ted@subsmac{% \global\ted@count\z@ \ted@toks\expandafter{\expandafter}% \expandafter\ted@subsmac@loop\the\ted@toks\ted@@nil#1\ted@@end}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@remove@nil} % You probably noticed the \cs{ted@@nil} after \cs{ted@toks} in the % above definition. This is to avoid problems while trying to % substitute something like ``AA'' in a list ending with ``A'' (new in % v1.05). We need to remove it when finished. % \begin{macrocode} \@ifdefinable\ted@remove@nil{% \long\def\ted@remove@nil#1\ted@@nil{% \ted@toks{#1}}} % \end{macrocode} % \end{macro} % % \subsection{Display} % % \begin{macro}{\ted@ShowTokens} % In order to display the tokens one by one, we first encode the string. % \begin{macrocode} \newcommand\ted@ShowTokens[1]{% \begingroup \ted@sanitize \ted@toks{#1}% \ted@typeout{--- Begin token decomposition of:}% \ted@typeout{\@spaces \the\ted@toks}% \ted@encode{#1}% \expandafter\ted@show@toks\the\ted@toks\ted@@end \endgroup \ted@typeout{--- End token decomposition.}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@show@toks} % Then we proceed, almost like decoding, iteratively, processing the % encoded tokens one by one. We detect control sequences the same way as % in pre-scanning. For our tests (and also for use in % \cs{ted@show@toks@}) we embed |#1| into \cs{ted@toks} in order to % nest the \cs{if}s without fear. There are four cases that need to be % typeset in different ways : active character, CS that represent a % special token, normal CS, normal character token. However, we need to % do one more test to detect the character tokens whose charcode is % $32$, before we apply \cs{string} to it in order to check if it was a % control sequence. % \begin{macrocode} \count@\catcode\z@ \catcode\z@ 12 \newcommand\ted@show@toks[1]{% \ted@toks{#1}\expandafter \ifx\the\ted@toks\ted@@end \else\expandafter \ifx\the\ted@toks\ted@@active % \end{macrocode} % It's time to think about the following: we are inside a group where % all active characters were redefined, but we nonetheless want to % display their meaning. In order to do this, the display need to % actually happen after the current group is finished. For this we use % \cs{aftergroup} (with specialized macro for displaying each kind of % token). % \begin{macrocode} \aftergroup\ted@type@active \expandafter\aftergroup\the\ted@toks \else \if\expandafter\noexpand\the\ted@toks\@sptoken \aftergroup\ted@type@normal \expandafter\aftergroup\the\ted@toks \else \begingroup \escapechar\if\noexpand#1^^00 \@ne \else \z@ \fi \expandafter\expandafter\expandafter\ted@show@toks@ \expandafter\string\the\ted@toks\@nil \fi \fi \expandafter\ted@show@toks \fi} \catcode\z@\count@ % \end{macrocode} % \end{macro} % \begin{macro}{\ted@show@toks@} % Now test the remaining cases : special CS, normal CS, or normal % character. % \begin{macrocode} \@ifdefinable\ted@show@toks@{% \long\def\ted@show@toks@#1#2\@nil{% \expandafter\endgroup \ifnum`#1=\escapechar \expandafter\ifx\the\ted@toks\ted@@special \ted@show@special#2\@nil \else \aftergroup\ted@type@cs \expandafter\aftergroup\the\ted@toks \fi \else \aftergroup\ted@type@normal \expandafter\aftergroup\the\ted@toks \fi}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@show@special} % Let's begin our tour of specialized display macro with the most % important one: \cs{ted@show@special}. Displaying the special token % goes mostly the same way as decoding them, but is far easier, since we % don't need to care about groups: display is done with % \cs{catcode}~$12$ characters. % \begin{macrocode} \@ifdefinable\ted@show@special{% \begingroup\escapechar\m@ne \expandafter\endgroup \expandafter\def\expandafter\ted@show@special\string\ted@@#1#2\@nil{% \ifcase#1 \aftergroup\ted@type@hash \or \aftergroup\ted@type@blank \or \aftergroup\ted@type@bgroup \or \aftergroup\ted@type@egroup \fi \begingroup \uccode`1#2 \uppercase{\endgroup\aftergroup1}}} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@type@hash} % \begin{macro}{\ted@type@blank} % \begin{macro}{\ted@type@bgroup} % \begin{macro}{\ted@type@egroup} % \begin{macro}{\ted@type@normal} % The four macros for special tokens are obvious. So is the macro for % normal tokens. By the way, \cs{ted@typeout} will be discussed in the % next section. % \begin{macrocode} \newcommand\ted@type@hash[1]{% \ted@typeout{#1 (macro parameter character #1)}} % \end{macrocode} % \begin{macrocode} \newcommand\ted@type@blank[1]{% \ted@typeout{#1 (blank space #1)}} % \end{macrocode} % \begin{macrocode} \newcommand\ted@type@bgroup[1]{% \ted@typeout{#1 (begin-group character #1)}} % \end{macrocode} % \begin{macrocode} \newcommand\ted@type@egroup[1]{% \ted@typeout{#1 (end-group character #1)}} % \end{macrocode} % \begin{macrocode} \newcommand\ted@type@normal[1]{% \ted@typeout{#1 (\meaning#1)}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\ted@type@cs} % \begin{macro}{\ted@type@active} % For control sequences and active characters, we use more sophisticated % macros. Indeed, their \cs{meaning} can be quite long, and since it is % not so important (\pf{ted}'s work is lexical analysis, displaying the % \cs{meaning} is just an add-on), we cut it so that lines are shorter % than~$80$ colons, in order to save our one-token-a-line presentation. % \begin{macrocode} \newcommand\ted@type@cs[1]{% \ted@type@long{\string#1 (control sequence=\meaning#1}}% % \end{macrocode} % \begin{macrocode} \newcommand\ted@type@active[1]{% \ted@type@long{\string#1 (active character=\meaning#1}}% % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ted@type@long} % Lines are cut and displayed by \cs{ted@type@long}. This macro uses a % loop, counting down how many columns remain on the current line. The % input need to be fully expanded first, and the output is stored in % \cs{ted@toks}. % \begin{macrocode} \newcommand\ted@type@long[1]{% \ted@toks{}% \ted@code72 \edef\next{#1}% \expandafter\ted@tl@loop\next\@nil} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@tl@loop} % The only difficult thing in this loop is to take care of space tokens. % For this we use again our \cs{futurelet} trick: % \begin{macrocode} \newcommand\ted@tl@loop{% \futurelet\@let@token \ted@tl@loop@} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@tl@loop@} % \ldots then check what to do. % \begin{macrocode} \newcommand\ted@tl@loop@{% \ifx\@let@token\@nil \let\next\ted@tl@finish \else \advance\ted@code\m@ne \ifnum\ted@code<\z@ \let\next\ted@tl@finish \else \ifx\@let@token\@sptoken \let\next\ted@tl@space \else \let\next\ted@tl@add \fi \fi \fi \next} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@tl@add} % \begin{macro}{\ted@tl@space} % Normal characters are just grabbed and added without care, and spaces % are gobbled with a special macro which also add a space to the output. % \begin{macrocode} \newcommand*\ted@tl@add[1]{% \ted@toks\expandafter{\the\ted@toks #1}% \ted@tl@loop} % \end{macrocode} % \begin{macrocode} \@ifdefinable\ted@tl@space{% \expandafter\def\expandafter\ted@tl@space\space{% \ted@tl@add{ }}} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ted@tl@finish} % When the end has been reached (either because a \cs{@nil} was % encountered or because the line is almost full), it's time to % actually display the result. We add \cs{ETC.} at the end when the % full \cs{meaning} isn't displayed. % \begin{macrocode} \@ifdefinable\ted@tl@finish{% \def\ted@tl@finish#1\@nil{% \ifnum\ted@code<\z@ \ted@typeout{\the\ted@toks\string\ETC.)} \else \ted@typeout{\the\ted@toks)} \fi}} % \end{macrocode} % \end{macro} % % \subsection{User macros} % % \begin{macro}{\ted@typeout} % Since we just discussed display, let's see the related user commands. % Output is done with % \begin{macrocode} \newcommand\ted@typeout{% \immediate\write\ted@outfile} % \end{macrocode} % \end{macro} % \begin{macro}{\ShowTokensOnline} % \begin{macro}{\ShowTokensLogonly} % allowing the user to choose between online display, or log output. % Default is online. % \begin{macrocode} \newcommand\ShowTokensOnline{% \let\ted@outfile\@unused} % \end{macrocode} % \begin{macrocode} \newcommand\ShowTokensLogonly{% \let\ted@outfile\m@ne} % \end{macrocode} % \begin{macrocode} \ShowTokensOnline % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ShowTokens} % \begin{macro}{\ted@ShowTokens@exp} % The user macro for showing tokens is a simple call to the internal % macro, just expanding its argument once in its stared form. % \begin{macrocode} \newcommand\ShowTokens{% \@ifstar{\ted@ShowTokens@exp}{\ted@ShowTokens}} % \end{macrocode} % \begin{macrocode} \newcommand\ted@ShowTokens@exp[1]{% \expandafter\ted@ShowTokens\expandafter{#1}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\Substitute} % \begin{macro}{\ted@Subs@star} % Now, the user macro for substitution. First, check how many stars % there are, if any, and set \cs{ted@subs@cmd} accordingly. % \begin{macrocode} \newcommand\Substitute{% \@ifstar {\ted@Subs@star} {\let\ted@Subs@cmd\ted@Substitute \ted@Subs}} % \end{macrocode} % \begin{macrocode} \newcommand\ted@Subs@star{% \@ifstar {\let\ted@Subs@cmd\ted@Subs@exp@iii \ted@Subs} {\let\ted@Subs@cmd\ted@Subs@exp@i \ted@Subs}} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ted@Subs@exp@i} % \begin{macro}{\ted@Subs@exp@iii} % Here are the intermediate macros that expand either the first or all % three arguments before calling \cs{ted@Substitute}. % \begin{macrocode} \newcommand\ted@Subs@exp@i{% \expandafter\ted@Substitute\expandafter} % \end{macrocode} % \begin{macrocode} \newcommand\ted@Subs@exp@iii[3]{% \begingroup \toks0{\ted@Substitute}% \toks2\expandafter{#1}% \toks4\expandafter{#2}% \toks6\expandafter{#3}% \xdef\ted@Subs@cmd{\the\toks0{\the\toks2}{\the\toks4}{\the\toks6}}% \endgroup \ted@Subs@cmd} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\ted@Subs} % Now, the last macro checks and process the optional argument. Here we % set \cs{ted@output}, which will be used at the end of % \cs{ted@Substitute}. % \begin{macrocode} \newcommand\ted@Subs[1][\ted@toks]{% \def\ted@output{#1}% \ted@Subs@cmd} % \end{macrocode} % \end{macro} % \begin{macro}{\ted@output} % Finally set a default \cs{ted@output} for advanced users who may want % to use \cs{ted@Substitute} directly. % \begin{macrocode} \let\ted@output\ted@toks % \end{macrocode} % \end{macro} % % \bigskip % \begin{center}\Large % That's all folks!\\ % Happy \TeX ing! % \end{center} % % \Finale % % \iffalse % %<*batchfile> % \fi % \begingroup\obeyspaces % \typeout{*****************************************************} % \typeout{* *} % \typeout{* To finish the installation you have to move the *} % \typeout{* following file into a directory searched by TeX: *} % \typeout{* *} % \typeout{* ted.sty *} % \typeout{* *} % \typeout{* Documentation is in ted.dvi or ted.pdf *} % \typeout{* *} % \typeout{* To produce the french documentation, run *} % \typeout{* (pdf)latex ted-fr.drv *} % \typeout{* *} % \typeout{* Happy TeXing! *} % \typeout{* *} % \typeout{*****************************************************} % \endgroup % \iffalse % % \fi \endinput