% \iffalse meta-comment % % colordoc - colored code documentation in LaTeX. % Copyright 2010 Federico Garcia federook@gmail.com % ------------------------------------------- % % % This program can be redistributed and/or modified under the terms % of the LaTeX Project Public License distributed from CTAN archives % in the directory macros/latex/base/lppl.txt; either version 1 of % the License, or (at your option) any later version. % % %<*driver> % \fi \ProvidesFile{colordoc.dtx}[2010/04/16 Colored code documentation] % \iffalse \documentclass{ltxdoc} \bibliographystyle{plain} \CodelineIndex \advance\textwidth1.6in \hoffset-.9in \GetFileInfo{colordoc.dtx} \providecommand{\MF}{\textsf{METAFONT}} \usepackage[pdftex]{color} \usepackage{fixltx2e} \definecolor{color-0}{rgb}{0,0,0} \definecolor{color-1}{rgb}{0,0,0} \definecolor{color-2}{rgb}{.15,0.15,.75} \definecolor{color-3}{rgb}{0,.47,0} \definecolor{color-4}{cmyk}{0,0.72,1,.4} \definecolor{color-5}{cmyk}{0,.5,0,0.6} \definecolor{color-def}{rgb}{0.8,0,0} \title{{\ttfamily colordoc}\\\TeX ni\textcolor{color-def}c\textcolor{color-3}o\textcolor{color-4}l\textcolor{color-5}o\textcolor{color-0}r documentation} \date{\filedate{}} \author{Federico Garcia\\\texttt{federook@gmail.com}} \begin{document} \maketitle \DocInput{\filename} \end{document} % % \fi % %\begin{abstract} %\noindent The \texttt{colordoc} package builds on the \texttt{doc} package to provide color highlighting of \TeX\ syntactical conventions, especially curly braces, |\if|-dots-|\fi| pairs, and definitions. %\end{abstract} %\tableofcontents %\section{Use and samples} %\makeatletter %\let\doc@macrocode\macro@code %\def\@makebracesactive{\catcode`\{\active\catcode`\}\active} %\def\macro@name#1{^^A % \edef\macro@namepart{\macro@namepart#1}^^A % \ifx\macro@namepart\colordoc@new\let\futuremacro@style\textnew\fi^^A % \ifx\macro@namepart\colordoc@newif\@ifcheckallowedfalse\fi^^A % \ifx\macro@namepart\colordoc@if\if@ifcheckallowed^^A % \gdef\macro@style{\@openingbrace}^^A % \else\global\@ifcheckallowedtrue\fi\fi^^A % \futurelet\next\more@macroname^^A % } %\def\macro@finish{\relax % \ifx\macro@namepart\colordoc@newenvironment\let\futuremacro@style\relax\fi % \ifx\macro@namepart\colordoc@newcounter\let\futuremacro@style\relax\fi % \ifx\macro@namepart\colordoc@def\let\futuremacro@style\textnew\fi % \ifx\macro@namepart\colordoc@edef\let\futuremacro@style\textnew\fi % \ifx\macro@namepart\colordoc@gdef\let\futuremacro@style\textnew\fi % \ifx\macro@namepart\colordoc@xdef\let\futuremacro@style\textnew\fi % \ifx\macro@namepart\colordoc@renewcommand\let\futuremacro@style\textnew\fi % \ifx\macro@namepart\colordoc@providecommand\let\futuremacro@style\textnew\fi % \ifx\macro@namepart\colordoc@loop % \let\macro@style\@openingbrace % \@ifcheckallowedfalse\fi % \ifx\macro@namepart\colordoc@repeat\let\macro@style\@closingbrace\fi % \ifx\macro@namepart\colordoc@fi\let\macro@style\@closingbrace\fi % \ifx\macro@namepart\colordoc@else % \gdef\macro@style{\@closingbrace\relax\@openingbrace}\fi % \macro@style\macro@namepart\global\let\macro@style\relax % \global\let\macro@style\futuremacro@style\global\let\futuremacro@style\relax % \ifnot@excluded\relax % \edef\@tempa{\noexpand\SpecialIndex{\bslash\macro@namepart}}\relax % \@tempa \fi} %\newif\if@ifcheckallowed\@ifcheckallowedtrue %\def\colordoc@new{new}\def\colordoc@newif{newif} %\def\colordoc@if{if}\def\colordoc@fi{fi} %\def\colordoc@else{else} %\def\colordoc@loop{loop} %\def\colordoc@repeat{repeat} %\def\colordoc@def{def}\def\colordoc@edef{edef} %\def\colordoc@gdef{gdef}\def\colordoc@xdef{xdef} %\def\colordoc@providecommand{providecommand} %\def\colordoc@renewcommand{renewcommand} %\def\colordoc@newenvironment{newenvironment} %\def\colordoc@newcounter{newcounter} %\def\colordoc@newsavebox{newsavebox} %\def\colordoc@bgroup{bgroup}\def\colordoc@egroup{egroup} %\def\colordoc@begingroup{begingroup}\def\colordoc@endgroup{endgroup} %\def\colordoc@begin{begin}\def\colordoc@end{end} %\def\ColorLevels#1{\relax % \@colorlevels#1\relax % \@tempcnta\@colorlevels % \loop\ifnum\@tempcnta>\z@ % \expandafter\edef\csname @color\the\@tempcnta\endcsname{\relax % \noexpand\color{color-\the\@tempcnta}} % \advance\@tempcnta\m@ne % \repeat % } %\newcount\@colorlevels %\newcount\BraceLevel \BraceLevel\z@ %\def\braces@colorscheme{\relax % \ColorLevels4 % \BraceLevel\z@ % \definecolor{color-0}{rgb}{0,0,0} % \definecolor{color-1}{cmyk}{1,.5,0,.3} % \definecolor{color-2}{cmyk}{0,1,0,.2} % \definecolor{color-3}{rgb}{0,.6,0} % \definecolor{color-4}{cmyk}{0,0,1,.6} % \def\textnew##1{\textit{\color{color-def}##1\/}} % \definecolor{color-def}{rgb}{0.8,0,0} % } %\def\contents@colorscheme{\relax % \ColorLevels5 % \BraceLevel\@ne % \definecolor{color-0}{rgb}{0,0,0} % \definecolor{color-1}{cmyk}{0,.5,0,0.6} % \definecolor{color-2}{rgb}{0,0,0} % \definecolor{color-3}{rgb}{.15,0.15,.75} % \definecolor{color-4}{rgb}{0,.47,0} % \definecolor{color-5}{cmyk}{0,0.72,1,.4} % \def\textnew##1{\textit{\color{color-def}##1\/}} % \definecolor{color-def}{rgb}{0.8,0,0} % } %\def\numberssample{\relax % \def\macro@code{\doc@macrocode\@makebracesactive} % \def\textnew##1{\textit{\underline##1\/}} % \def\@openingbrace##1{\global\advance\BraceLevel\@ne##1\textsubscript{\the\BraceLevel}} % \def\@closingbrace{\textsubscript{\the\BraceLevel}\global\advance\BraceLevel\m@ne} % \BraceLevel\z@ % } %\def\nothingsample{\relax % \let\@openingbrace\relax % \let\@closingbrace\relax % \let\textnew\relax % \def\macro@code{\doc@macrocode\@makebracesactive} % } %\def\bracessample{\relax % \def\macro@code{\doc@macrocode\@makebracesactive} % \let\@colorcode\relax % \braces@colorscheme % \def\@openingbrace##1{\@modinc\BraceLevel{\@bracecolor##1}} % \def\@closingbrace##1{{\@bracecolor##1}\@moddecr\BraceLevel} % } % \let\docendmacro@code\endmacro@code % \let\doctheCodelineNo\theCodelineNo %\def\contentssample{% % \contents@colorscheme % \def\macro@code{\doc@macrocode\@makebracesactive\@bracecolor} % \def\endmacro@code{\docendmacro@code\normalcolor} % \def\theCodelineNo{\normalcolor\doctheCodelineNo} % \def\@openingbrace##1{##1\@modinc\BraceLevel % \global\let\@codecolor\@bracecolor\@codecolor} % \def\@closingbrace{\@moddecr\BraceLevel % \global\let\@codecolor\@bracecolor\@codecolor} % } %\bgroup %\catcode`\[\@ne\catcode`\]\tw@ %\@makebracesactive %\gdef{[\@openingbrace[\char'173]] %\gdef}[\@closingbrace[\char'175]] %\catcode`\|\z@\catcode`\%12\catcode`\ \active\catcode`\\\active|gdef|xmacro@code#1% \end{macrocode}[#1|end[macrocode]]|catcode`| 12|gdef|sxmacro@code#1% \end{macrocode*}[#1|end[macrocode*]]|egroup %\def\@modinc#1{\relax % \global\advance#1\@ne % \ifnum#1>\@colorlevels % \global#1\@ne\fi} %\def\@moddecr#1{\relax % \global\advance#1\m@ne % \ifnum#1>\z@\else % \global#1\@colorlevels\fi} %\def\@bracecolor{\@nameuse{@color\the\BraceLevel}} %\EnableCrossrefs %\let\macro@style\relax %\let\futuremacro@style\relax % %To use the package, simply load it with |\usepackage|. (A few user commands for customization are mentioned below.) The package is designed for use with |doc|, mainly in |dtx| files. You can use it in your own, or simply add the package to any |dtx| in order to get the coloring of the code. % %This \texttt{dtx} doesn't itself load the package (since odds are it's not installed), but it contains the package's code in order to make the samples. I've been careful and tested the package separately, but there's always the risk that some subtle thing is different---please let me know if you find something. In any case, the official supported version is |colordoc.sty|, not |colordoc.dtx|. % %The package has three options: |braces| (default) colors the braces and pairs of matching macros (|\if|\dots-|\fi|); |contents| colors what's inside these delimiters; |numbers| (also |numbered|) puts subscripts after the delimiters; and |nothing| just does nothing. The first three options also highlight newly defined things. % % %\subsection{Option \texttt{nothing}}\nothingsample % %This doesn't change anything and the result is exactly as if not loading the package: % % \begin{macrocode} %<*sample> \newcount\@sample \newif\if@sample \newbox\samplebox\newcounter{samplecount} \newcommand\test{\ifhmode\gdef\@test{% \loop\ifnum\@sample\z@ \advance\@sample\@ne \repeat} \else\ifcat\noexpand#1a% \begin{minipage} Test sample. \PackageWarning{sample}{Don't do this!}% \end{minipage} \else\ifodd\@sample \@namedef{@@sample}{\textit{It}\space\textsf{(\textbf{Note})}}% % \end{macrocode} %Sample text. % \begin{macrocode} \fi \fi \xdef\@test{\relax}% \fi } % % \end{macrocode} % %\bigskip\subsection{Option \texttt{braces} (default)}\bracessample % %Here the delimiters are colored, as well as new commands: % % \begin{macrocode} %<*sample> \newcount\@sample \newif\if@sample \newbox\samplebox\newcounter{samplecount} \newcommand\test{\ifhmode\gdef\@test{% \loop\ifnum\@sample\z@ \advance\@sample\@ne \repeat} \else\ifcat\noexpand#1a% \begin{minipage} Test sample. \PackageWarning{sample}{Don't do this!}% \end{minipage} \else\ifodd\@sample \@namedef{@@sample}{\textit{It}\space\textsf{(\textbf{Note})}}% % \end{macrocode} %Sample text. % \begin{macrocode} \fi \fi \xdef\@test{\relax}% \fi } % % \end{macrocode} % %\bigskip\subsection{Option \texttt{contents}}\contentssample % %Here what is colored is the stuff within delimiters, not the delimiters themselves: % % \begin{macrocode} %<*sample> \newcount\@sample \newif\if@sample \newbox\samplebox\newcounter{samplecount} \newcommand\test{\ifhmode\gdef\@test{% \loop\ifnum\@sample\z@ \advance\@sample\@ne \repeat} \else\ifcat\noexpand#1a% \begin{minipage} Test sample. \PackageWarning{sample}{Don't do this!}% \end{minipage} \else\ifodd\@sample \@namedef{@@sample}{\textit{It}\space\textsf{(\textbf{Note})}}% % \end{macrocode} %Sample text. % \begin{macrocode} \fi \fi \xdef\@test{\relax}% \fi } % % \end{macrocode} % %\bigskip\subsection{Option \texttt{numbers} (black and white)}\numberssample % %This replaces coloring with numbers in subscript and underlining for the new commands: % % \begin{macrocode} %<*sample> \newcount\@sample \newif\if@sample \newbox\samplebox\newcounter{samplecount} \newcommand\test{\ifhmode\gdef\@test{% \loop\ifnum\@sample\z@ \advance\@sample\@ne \repeat} \else\ifcat\noexpand#1a% \begin{minipage} Test sample. \PackageWarning{sample}{Don't do this!}% \end{minipage} \else\ifodd\@sample \@namedef{@@sample}{\textit{It}\space\textsf{(\textbf{Note})}}% % \end{macrocode} %Sample text. % \begin{macrocode} \fi \fi \xdef\@test{\relax}% \fi } % % \end{macrocode} % %\subsection{Further variations} % %The user can easily customize the given options. \DescribeMacro{\textnew}|\textnew| holds the formatting of the macro names after |\def|, |\new|\dots, etc., and can be easily modified. The actual colors are held in \DescribeMacro{color-1}\DescribeMacro{color-2}\marginpar{\raggedleft$\vdots$\hspace*{.5cm}}|color-1|, |color-2|, etc., and can be changed through the \texttt{color} package's |\definecolor|. There are four colors (in addition to the default black) in the \texttt{braces} option, and five in \texttt{contents}. Should the user want to change this, \DescribeMacro{\ColorLevels}|\ColorLevels|\meta{$n$} sets things up for $n$ colors; their actual hue still has to be defined through |\definecolor|. % %\section{Warnings, decisions, wishes}\label{warnings} % %\begin{enumerate} %\item\textit{It would be nice if highlighting is suppressed for braces that open and close within the same code line.} I tried this several times. In the end I don't think it's worthwhile the amount of hacking it requires. Using some \TeX\ trickery, you can make the opening brace find out whether there is a closing brace before the end of the line. That much is possible and fairly robust; but the problem is that there might be several other braces apart from the first one; the full task involves counting opening and closing braces before the end of the line---a case of multiple macro reversion with unknown numbers of arguments, in the tricky conditions of the \texttt{macrocode} environment. %\item\textit{Smart \cs{repeat}.} I personally use and have seen `|\loop\if|\dots\ |\repeat|' more frequently than `|\loop|\dots\ |\repeat\if|.' So \texttt{colordoc} works for the former construction: |\loop| suppresses the behavior of the following |\if|, and itself behaves as an opening delimiter---closed by |\repeat|. The program \emph{will} get confused if the latter construction is used. There is really no way around this. %\item\textit{\LaTeX\ conditionals} (|\@ifundefined|, etc.), that do \emph{not} behave as delimiters, will be treated correctly by \texttt{colordoc}. But this is because of the lucky coincidence that those conditionals have the |@| at the beginning. \texttt{colordoc} treats anything starting |\if| as a delimiter. If you are defining fancy conditionals, it might be a good idea to use |\@if|\dots %\item\textit{In an emergency,} when something in the code does confuse \texttt{colordoc}, you can manually set |\BraceLevel| to a number, and restore order. Just like that: |\BraceLevel1| (or even |\BraceLevel=1|). %\item\textit{The main text may appear colored} sometimes. This is due, who knows how, to the several-pass cross-reference mechanisms. One more run will usually make it good. %\item\textit{I wish the color of the backslash could be easily controlled.} But the backslash is typeset by |doc| before |\macro@name| starts assembling the letters of the command. |\macro@name| is what I hacked, and what was easiest and best to hack, but then I had no control over the backslash. %\item\textit{Does the program know when a macro is being defined?} While working on the package I realized that by coloring any macro that is being defined, I didn't need to religiously append |\begin{macro}| to generate the marginpars. With the coloring of new commands, the visual reference was there already. At a wild point I thought that maybe the package would add the |\begin{macro}|'s automatically! Of course this is actually impossible, and in any case the user would have no control over when and where to put it. But it is true that the need for the marginpars with macro names is eased. This \texttt{dtx} doesn't have many (none in the code) and thus I'm using a little less paper. %\item\textit{\textsf{METAFONT} support.} I thought it would be simply changing |{| for |(|. This much is easy, but apart from that catching |if|-|endif| is impossible for a language with no ``escape character'' that would allow |doc| scan for a macro name. The solution is to create a wholly new package adapting |doc| to \textsf{METAFONT}. %\end{enumerate} % %\section{The package} % %\subsection{Introduction} % %This program modifies Frank Mittelbach's \texttt{doc} package to use colors in the code listing of a program. With a natural emphasis on \TeX, color is used mainly to highlight matching curly braces (`|{|' and `|}|', henceforth simply `braces'), |\if|\dots-|\fi| constructions, and other \TeX\ programming stuff. % %Originally I imagined coloring pairs of matching braces with the same color (different for each level of nesting). In 2002--3 I prepared the `interactive version' in the \textsc{cd} accompanying my uncle's book \emph{El Universo \LaTeX} \cite{universo}, and developed some macros to color matching braces in the examples. That \textsf{pdf} was prepared in a larger font, suitable for on-screen reading, and this made the colored braces very easy to spot. It was fun work, but not vary robust (it was intended for my own use), and it certainly required some retouching of the code that was being listed---in part, because other stuff was being done to it, like highlighting the particular commands that each example illustrated, and making them links to their description in the text. So it wasn't really a literate programming tool (where the point is to use \emph{the same} source as both the working program and its typeset-able listing). But that was where I saw that coloring the code makes a difference in code readability. % %So when I did the first tries for the present package I started by coloring the braces. But such small characters (made even |\small|'er by |macrocode|) did not really stand out, and the colored brace matching was nice, but less than obvious to the eye. Then I think my wife Jen proposed coloring not the braces but the stuff inside them! I initially liked this a lot. (An architect and graphic designer, Jen would eventually be in charge of defining the default color schemes of the package). The result was more what I had in mind: the matching is really obvious, and the colored code is not as obnoxious as I first feared. % %However, that is true when we're only considering braces. After adding the rest of the features (|\if|'s, highlighting of newly defined macros, etc.), it became clear that, sadly, there are really a lot of things colored all over the place. So I am back to the coloring of the braces, not the contents, as a default. Coloring the contents is offered as an option---another option was thought of anyway, for black-and-white needs (i.e., when printing): instead of colors we can give braces a numeric subscript. % %Just to give it a chance, I am using the ``contents'' option in the code of the present package below. % %\subsection{General strategy} % %We will have to hack the |macrocode| environment, where the code listing actually happens, and which is analogous to the usual |verbatim|, except that other things happen---addition of line numbers being the most obvious. |{| and |}| will have to be made active characters---not too much of a problem because they are innocuous in |macrocode|, not having to perform any special tasks. % %Catching |\if|'s, and analogously catching |\def|'s, |\edef|'s, |\newcommand|'s, etc.\ (since it would be nice to highlight the commands that are being defined), seems harder. It will mean making |\| active, and making it read ahead for the name of the macro it introduces: take letter by letter, find the end of a command name (is it true, as intuitively felt, that we can simply look for a character with a category code other than `letter'?), decide what to do with it, and hope that this doesn't break anything else, and that you can prove it. % %Two good news: within |macrocode| (or |verbatim|), not much does much---all the special characters' special meanings are suppressed, so, after all, there isn't much that can be `broken'. It actually turns out to be a pretty danger-free low-level hacking setting. % %And the second good news: Frank Mittelbach, in |doc| itself, already did most of the job about finding a macro's name! This is because of his bold dream, and execution thereof, of making |macrocode| compile index entries from the macros used in the code. Since the |doc| package not only implements literate programming, but also illustrates it very well (the explanations\footnote{I mean the explanations on how the macros work and are implemented. The explanations to the user, on how to \emph{use} the macros, are paradoxically less friendly!} are quite sufficient to understand a code that is itself very readable, and the functions are broken into logical sections), it is very easy to achieve the results of |colordoc| with only relatively small, targeted modifications.\contentssample % %So let's start by setting up \texttt{colordoc} as a package, and then the main modification from \texttt{doc}: % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{colordoc}[2010/04/18 Documentation in TeXnicolor (Federico Garcia)] \let\doc@macrocode\macro@code % \end{macrocode} % %The new meaning of |macrocode| depends on \texttt{colordoc}'s options, and will be established there (section~\ref{options}). It will always do what it does in \texttt{doc} (now |\doc@macrocode|) plus more stuff; among this additional stuff is the need to make the braces active, through |\@makebracesactive|: % \begin{macrocode} \def\@makebracesactive{\catcode`\{\active\catcode`\}\active} % \end{macrocode} % %\subsection{Highlighting of special commands} %When |doc| finds a |\| in the user's code, it starts gathering the command name that follows, in order to make an index entry (except when the command is in the |\DoNotIndex| list). We are going to hack two of the commands involved: |\macro@name|, that takes each letter and adds it to the name that is being collected---we need this to find partial command names like |\if|\dots\ or |\new|\dots---and |\macro@finish|, that operates on a completed macro name---which we will use to catch complete things like |\fi| without finding |\finish|. We won't really re-use the original definitions (as we did with |\macro@code|, because we are changing, not just adding to, the behavior of the original |\macro@namepart| and |\macro@finish|. % \begin{macrocode} \def\macro@name#1{% \edef\macro@namepart{\macro@namepart#1}% Like in doc \ifx\macro@namepart\colordoc@new\let\futuremacro@style\textnew\fi \ifx\macro@namepart\colordoc@newif\@ifcheckallowedfalse\fi \ifx\macro@namepart\colordoc@if\if@ifcheckallowed \gdef\macro@style{\@openingbrace}% \else\global\@ifcheckallowedtrue\fi\fi \futurelet\next\more@macroname% Like in doc } \def\macro@finish{% \ifx\macro@namepart\colordoc@newenvironment\let\futuremacro@style\relax\fi \ifx\macro@namepart\colordoc@newcounter\let\futuremacro@style\relax\fi \ifx\macro@namepart\colordoc@def\let\futuremacro@style\textnew\fi \ifx\macro@namepart\colordoc@edef\let\futuremacro@style\textnew\fi \ifx\macro@namepart\colordoc@gdef\let\futuremacro@style\textnew\fi \ifx\macro@namepart\colordoc@xdef\let\futuremacro@style\textnew\fi \ifx\macro@namepart\colordoc@renewcommand\let\futuremacro@style\textnew\fi \ifx\macro@namepart\colordoc@providecommand\let\futuremacro@style\textnew\fi \ifx\macro@namepart\colordoc@loop\let\macro@style\@openingbrace\@ifcheckallowedfalse\fi \ifx\macro@namepart\colordoc@repeat\let\macro@style\@closingbrace\fi \ifx\macro@namepart\colordoc@fi\let\macro@style\@closingbrace\fi \ifx\macro@namepart\colordoc@else\def\macro@style{\@closingbrace\relax\@openingbrace}\fi \ifx\macro@namepart\colordoc@csname\let\macro@style\@openingbrace\fi \ifx\macro@namepart\colordoc@endcsname\let\macro@style\@closingbrace\fi % \end{macrocode} %The original definition of |\macro@finish| simply typesets the macro name (held in |\macro@namepart|), and then proceeds to process it (or not, according to |\ifnot@excluded|) as an index entry. We will add the formatting, both of the present macro with |\macro@style|, and of the very next one with |\futuremacro@style|. % \begin{macrocode} \macro@style\macro@namepart\global\let\macro@style\relax \global\let\macro@style\futuremacro@style\global\let\futuremacro@style\relax \ifnot@excluded% From here on like in doc \edef\@tempa{\noexpand\SpecialIndex{\bslash\macro@namepart}}% \@tempa \fi} % \end{macrocode} % %\bigskip\noindent With these redefinitions we have made the program able to find the macro names that trigger special formatting. Some of them trigger it for themselves, some trigger it for the coming macro. This all happens through |\macro@style| and |\futuremacro@style|. In particular, |\if| and other behave like an opening brace, making |\macro@style| equal to |\@openingbrace| (discussed later on). |\fi| and others are like a closing brace, while |\else| is \emph{both} a closing and an opening brace. % %Some macros, however, should suppress this special behavior of |\if|, because after them |\if| doesn't work as a delimiter: after a |\newif|, and after |\loop| (rather, |\loop| itself is a delimiter, paired with |\repeat|). This is the point of the test |\if@ifcheckallowed|. (See some warnings about this in section~\ref{warnings}). % \begin{macrocode} \newif\if@ifcheckallowed\@ifcheckallowedtrue % \end{macrocode} % %The |\new|\dots\ commands (|\newcount|, |\newif|, etc., including |\newcommand|), as well as the different |\def|'s, will highlight whatever the next macro name is. The default highlighting depends on the package options, which define the default |\textnew|. The command can freely be redefined by the user---when used by the program, if you need to consider argument handling, it is always followed by |\macro@namepart| (a single token). % %\bigskip\noindent %The special macro names are found by comparing the macros found in the code, either complete (at |\finishmacro@name|) or not (at |\macro@name|), with pre-defined contents. The comparison is done by |\ifx|, that compares only two tokens, so that we actually have to define commands to contain the comparands we're looking for. The actual comparisons happened above, but here are the comparands: % \begin{macrocode} \def\colordoc@csname{csname} \def\colordoc@endcsname{endcsname} \def\colordoc@def{def} \def\colordoc@edef{edef} \def\colordoc@gdef{gdef} \def\colordoc@xdef{xdef} \def\colordoc@if{if} \def\colordoc@else{else} \def\colordoc@fi{fi} \def\colordoc@loop{loop} \def\colordoc@repeat{repeat} \def\colordoc@new{new} \def\colordoc@newif{newif} \def\colordoc@newcounter{newcounter}\def\colordoc@newenvironment{newenvironment} \def\colordoc@providecommand{providecommand} \def\colordoc@renewcommand{renewcommand} % \end{macrocode} %\DoNotIndex{colordoc@csname,colordoc@def,colordoc@edef,colordoc@else,colordoc@endcsname,colordoc@fi,colordoc@gdef,colordoc@if,colordoc@loop,colordoc@new,colordoc@newcounter} %\DoNotIndex{colordoc@newenvironment,colordoc@newif,colordoc@newsavebox,colordoc@providecommand,colordoc@renewcommand,colordoc@repeat,colordoc@xdef}|\newenvironment| and |\newcommand| are needed, even though the search for a starting |\new| will find them, because in their cases we actually need to suppress the highlighting: their argument is not a macro name, but a simple argument. If we didn't suppress highlighting, then whatever is the next actual macro name will be (wrongly) highlighted. (The argument to |newenvironment| will then not be highlighted in any special way, but it doesn't seem worthwhile to implement a whole additional infrastructure for this one case.) |\newif|, on the other hand, also needs to suppress special treatment for the following |\if|\dots % %I decided not to include |\let|, because |\let| is used for auxiliary definitions, seldom legitimate ones that one would want to have quick reference to. You might also miss |\bgroup|, |\begingroup|, |\egroup| and |\endgroup|, whose equivalence to braces would make them obvious candidates for the changing-color macro list. I even included them at first, until I realized that one of their main use is to trick \TeX\ because one needs \emph{not} to match delimiters. Thus they should also not change colors. The other use of these commands, namely the creation of groups for local definitions, will sadly go uncolored; in case of need the user should consider simply using |{| and |}|. % %\subsection{The braces}\label{options} %The handling of braces is less straightforward. We'll have |{| and |}| defined generically in terms of |\@openingbrace| and |\@closingbrace|, commands that act on either |\char'173| or |\char'175| (|\{| and |\}| would produce the braces in the default font, not the one used for code). Their definitions depend on the options of the package. % %\subsubsection{\ttfamily numbers} %Here we will put a subscript number after the brace through |\textsubscript| (made available by the |fixltx2e| package, loaded later). This option is duplicated to provide both |numbered| and |numbers|. % \begin{macrocode} \newif\ifcolorcode@ \DeclareOption{numbers}{% \def\macro@code{\doc@macrocode\@makebracesactive} \colorcode@false \let\colordoc@scheme\relax \def\textnew#1{\textit{\underline#1\/}} \def\@openingbrace#1{\global\advance\BraceLevel\@ne#1\textsubscript{\the\BraceLevel}} \def\@closingbrace{\textsubscript{\the\BraceLevel}\global\advance\BraceLevel\m@ne} } \DeclareOption{numbered}{% \def\macro@code{\doc@macrocode\@makebracesactive} \colorcode@false \let\colordoc@scheme\relax \def\textnew#1{\textit{\underline#1\/}} \def\@openingbrace#1{\advance\BraceLevel\@ne#1\textsubscript{\the\BraceLevel}} \def\@closingbrace{\textsubscript{\the\BraceLevel}\advance\BraceLevel\m@ne} } % \end{macrocode} % %\subsubsection{\ttfamily nothing} % \begin{macrocode} \DeclareOption{nothing}{% \let\@openingbrace\relax \let\@closingbrace\relax \colorcode@false \let\colordoc@scheme\relax \let\textnew\relax } % \end{macrocode} % %\subsubsection{\ttfamily braces} %This option will color only the brackets. With the |color| package loaded (later), it can define its color scheme (see~\ref{schemes}). % %On the other hand, we need to take care of the potentially infinite nesting. The levels will cycle through a finite number $n$ of colors (established by the color scheme). |\@modinc| and |\@moddecr| (defined below \ref{auxiliary}) step the level counter up and down, modulo $n$. |\@bracecolor| always means `the color specified by the color scheme for the current nesting level'. % \begin{macrocode} \DeclareOption{braces}{% \def\macro@code{\doc@macrocode\@makebracesactive} \colorcode@true \let\@colorcode\relax \def\colordoc@scheme{\braces@colorscheme} \def\@openingbrace#1{\@modinc\BraceLevel{\@bracecolor#1}} \def\@closingbrace#1{{\@bracecolor#1}\@moddecr\BraceLevel} } % \end{macrocode} % %\subsubsection{\ttfamily contents} %This is similar, but different enough. The color scheme has to be set to |\contents@colorscheme|. In addition, since the code (not only isolated characters or macros) is being colored, we need to keep track of the appropriate color at the start of each \texttt{macrocode}. So |\macro@code| is redefined differently from the other options, to include |\@bracecolor|. Similarly, the end of the environment should bring back the default color. % \begin{macrocode} \DeclareOption{contents}{% \colorcode@true \def\colordoc@scheme{\contents@colorscheme} \def\macro@code{\doc@macrocode\@makebracesactive\@bracecolor} \let\docendmacro@code\endmacro@code \def\endmacro@code{\docendmacro@code\normalcolor} % \end{macrocode} %Code line numbers should also be guarded against coloring: % \begin{macrocode} \let\doctheCodelineNo\theCodelineNo \def\theCodelineNo{\normalcolor\doctheCodelineNo} % \end{macrocode} %The last difference is that the actual braces are not affected by the new color. % \begin{macrocode} \def\@openingbrace#1{#1\@modinc\BraceLevel \global\let\@codecolor\@bracecolor\@codecolor} \def\@closingbrace{\@moddecr\BraceLevel \global\let\@codecolor\@bracecolor\@codecolor} } % \end{macrocode} % %The options will indicate which package to load (\texttt{color}'s driver should be specified in |\documentclass|, since there is no user control here). % \begin{macrocode} \DeclareOption*{\typeout{Unknown option (`\CurrentOption')}} \ExecuteOptions{braces} \ProcessOptions \ifcolorcode@\RequirePackage{color}\else\RequirePackage{fixltx2e}\fi % \end{macrocode} % %\subsubsection{Main brace engine} %We need a counter to keep track of the nesting level of the brackets. It should be available to the user for him to take control in emergencies. % \begin{macrocode} \newcount\BraceLevel \BraceLevel\z@ % \end{macrocode} % %Now we define |{| and |}|. This has to be done within a group where they are active characters: % \begin{macrocode} \bgroup \catcode`\[\@ne\catcode`\]\tw@ \@makebracesactive \gdef{[\@openingbrace[\char'173]] \gdef}[\@closingbrace[\char'175]] % \end{macrocode} % %Now that we are in this group we set up the other stuff that takes special category codes. The definition of |\xmacro@code| (the auxiliary macro that catches the end of a |macrocode| environment) looks exactly the same as in the original |doc| package, but it has to be re-done because in |colordoc| the braces are active. % %Now, how to tell the present |dtx| that the `|% \end{macrocode}|' string below is part of the code, not its end?! Well, we'll use |macrocode*|.\footnote{Just as in \texttt{doc.dtx}. In that file there is also a new comment character, whose full point I can't see and might be related to some other issue. In any case, that trickery is not necessary here.} % \begin{macrocode*} \catcode`\|\z@\catcode`\%12 \catcode`\ \active\catcode`\\\active |gdef|xmacro@code#1% \end{macrocode}[#1|end[macrocode]] % \end{macrocode*} % %Let's take the hint to provide support for the starred versions right here. Again, thanks to the modular design of \texttt{doc}, this is really painless. The only point is that in a starred environment the space is not active, so we have to deactivate it. It becomes an `other' kind of character, that would try to print something ({\ttfamily!~Missing |\begin{document}|}) if we let it happen, even as an end-of-line, so the whole thing has to go in one line (the comment character is sensitive as well). % \begin{macrocode} |catcode`| 12|gdef|sxmacro@code#1% \end{macrocode*}[#1|end[macrocode*]]|egroup % \end{macrocode} % %\BraceLevel\@ne\subsection{Auxiliary functions}\label{auxiliary} % %For cycling through the color scheme we need a pair of arithmetic functions modulo |\@colorlevels|. % \begin{macrocode} \def\@modinc#1{% \global\advance#1\@ne \ifnum#1>\@colorlevels \global#1\@ne\fi} \def\@moddecr#1{% \global\advance#1\m@ne \ifnum#1>\z@\else \global#1\@colorlevels\fi} % \end{macrocode} % %The actual color changes are performed by |\@bracecolor|. This is a function of |\BraceLevel|, through auxiliary commands |\@color|\meta{\cs{BraceLevel}}. % \begin{macrocode} \def\@bracecolor{\@nameuse{@color\the\BraceLevel}} % \end{macrocode} % %The auxiliary commands have to be defined in advance. Their number depends on |\@colorlevels|, but since the user can change this at any point, the program needs to be ready to apply new definitions. So, the user will have |\ColorLevels|\meta{new number of colors}: this sets |\@colorlevels|, and calls the definition routine. (Apart from this, the user is responsible for defining any colors beyond the original 5.) % \begin{macrocode} \def\ColorLevels#1{% \@colorlevels#1% \@tempcnta\@colorlevels \loop\ifnum\@tempcnta>\z@ \expandafter\edef\csname @color\the\@tempcnta\endcsname{% \noexpand\color{color-\the\@tempcnta}} \advance\@tempcnta\m@ne \repeat } % \end{macrocode} % %\subsection{Color schemes}\label{schemes} %The colors themselves are |\definecolor|'ed as \texttt{color-1}, \texttt{color-2}, etc., up to |\@colorlevels|. The two options that involve colors define the defaults, but the user can change them at any time. % %The \texttt{braces} color scheme needs eye-catching colors, since a lot of the coloring happens on single characters. The outer level will be color 0, since in principle it should never happen. However, it can happen when for some reason the code confuses |colordoc| (for example, when the braces are used in some special way and are unbalanced in the code; see section~\ref{warnings} for other cases). The default scheme is blue-purple-green-yellow. % \begin{macrocode} \newcount\@colorlevels \def\braces@colorscheme{% \ColorLevels4 \BraceLevel\z@ \definecolor{color-0}{rgb}{0,0,0} \definecolor{color-1}{cmyk}{1,.5,0,.3} \definecolor{color-2}{cmyk}{0,1,0,.2} \definecolor{color-3}{rgb}{0,.6,0} \definecolor{color-4}{cmyk}{0,0,1,.6} \def\textnew##1{\textit{\color{color-def}##1\/}} \definecolor{color-def}{rgb}{0.8,0,0} } % \end{macrocode} % %For the \texttt{contents} option, where whole chunks of code will be colored (instead of only braces and a few macros), we want milder colors. In fact, assuming that most of the code listing in a \texttt{dtx} actually happens at brace level~2 (since most of it is the contents of |\def|'s, |\newcommand|'s, etc.), we have set level~2 to black. The outer level is a darkish purple, and then comes a green, a brown, and a blue. % \begin{macrocode} \def\contents@colorscheme{% \ColorLevels5 \BraceLevel\@ne \definecolor{color-0}{rgb}{0,0,0} \definecolor{color-1}{cmyk}{0,.5,0,0.6} \definecolor{color-2}{rgb}{0,0,0} \definecolor{color-3}{rgb}{.15,0.15,.75} \definecolor{color-4}{rgb}{0,.47,0} \definecolor{color-5}{cmyk}{0,0.72,1,.4} \def\textnew##1{\textit{\color{color-def}##1\/}} \definecolor{color-def}{rgb}{0.8,0,0} } % \end{macrocode} % %\section{Initialization} %The macro name scanning mechanism of \texttt{doc} happens only if it is producing an index. That in turn is true only if the user has asked to |\EnableCrossrefs|. The reason why this is not the default is that it slows down the processing of the file. \texttt{colordoc} requires the macro name scanning, but not the index, and I thought of modifying the effect of these switches to always do the scanning but be selective on the index. I am afraid this is too risky, as the switch |\ifscan@allowed| is used variously in \texttt{doc}. Since speed is not so much of a concern nowadays, I prefer to leave this untouched. We simply need to make sure that the mechanism is allowed even if the user doesn't request it. % \begin{macrocode} \EnableCrossrefs \let\macro@style\relax \let\futuremacro@style\relax \colordoc@scheme % % \end{macrocode} % %\begin{thebibliography}{[1]} %\bibitem{universo}Rodrigo De Castro, \emph{El Universo \LaTeX}, 2nd.\ ed.. Bogot\'a: Universidad Nacional de Colombia, Facultad de Ciencias, Departamento de Matem\'aticas, 2003. %\end{thebibliography} %\PrintIndex %\endinput