% \iffalse meta-comment %<*internal> \iffalse % %<*readme> %^^A To generate the readme, we make + into an ignored character!! ---------------------------------------------------------------- cprotect --- verbatim in macro arguments E-mail: blflatex@gmail.com Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- A user of the cprotect.sty package can include verbatim text (\verb, verbatim environment, ...) in the argument of any command, including moving arguments. Including verbatim text in footnotes, section titles (and other titles), etc. is as simple as typing `\cpro+tect\footnote` instead of `\footnote`, etc. A similar approach is taken for environments. Nesting of the various environments is taken into account. This is work in progress, all comments/bug reports are welcome! The whole package can be built from the file `cprotect.dtx' by running pdflatex cprotect.dtx makeindex -s gglo.ist -o cprotect.gls cprotect.glo makeindex -s gind.ist -o cprotect.ind cprotect.idx pdflatex cprotect.dtx pdflatex cprotect.dtx mv README.txt README The first run of pdflatex produces `cprotect.ins', `cprotect.sty', `cprotect.pdf', and this file. The other commands are necessary for the pdf to contain its index and glossary. % %<*internal> \fi \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*install> \input docstrip.tex \keepsilent \askforoverwritefalse \preamble ---------------------------------------------------------------- cprotect --- verbatim in macro arguments E-mail: blflatex@gmail.com Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- \endpreamble \postamble Copyright (C) 2010-2011 by Bruno Le Floch This work may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this license or (at your option) any later version. The latest version of this license is in the file: http://www.latex-project.org/lppl.txt This work is "maintained" (as per LPPL maintenance status) by Bruno Le Floch. This work consists of the file cprotect.dtx and the derived files cprotect.ins, cprotect.pdf and cprotect.sty. \endpostamble \usedir{tex/latex/cprotect} \generate{ \file{\jobname.sty}{\from{\jobname.dtx}{package}} } % %\endbatchfile %<*internal> \usedir{source/latex/cprotect} \generate{ \file{\jobname.ins}{\from{\jobname.dtx}{install}} } \nopreamble\nopostamble \usedir{doc/latex/cprotect} \begingroup \catcode`\+=9\relax \generate{ \file{README.txt}{\from{\jobname.dtx}{readme}} } \endgroup \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % %<*package> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{cprotect}[2011/01/27 v1.0e (Bruno Le Floch)] % %<*driver> \documentclass[12pt]{ltxdoc} \usepackage[T1]{fontenc} \usepackage{cprotect} \usepackage{amsmath} \usepackage[margin=4cm]{geometry} \usepackage{hyperref} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \catcode`\^^@=9\relax %^^A We need an ignored character for later. \DocInput{cprotect.dtx} \end{document} % % \fi % % \CheckSum{0} % % %\GetFileInfo{cprotect.sty} % %\DoNotIndex{\addtocounter,\advance,\afterassignment,\aftergroup,\arabic} %\DoNotIndex{\begingroup,\closeout,\count,\csname,\def,\edef,\gdef,\else} %\DoNotIndex{\endcsname,\endgroup,\expandafter,\fi,\ifnum,\ifthenelse,\ifx} %\DoNotIndex{\immediate,\indexspace,\let,\newcommand,\newcounter,\newwrite} %\DoNotIndex{\openout,\relax,\repeat,\RequirePackage,\setcounter,\string} %\DoNotIndex{\stepcounter,\value,\WithSuffix,\(,\),\+,\/,\=,\@gobble} %\DoNotIndex{\{} %\DoNotIndex{\}} %\DoNotIndex{\^} % %\cprotect\title{|{cprotect.sty}|\\ % |\verb|atim in |\macro| arguments\thanks{This file % describes version \fileversion, last revised \filedate.}} %\author{Bruno Le Floch\thanks{E-mail: bruno@le-floch.fr}} %\date{Released \filedate} % %\maketitle % % \tableofcontents % \changes{v1.0}{2010/12/30}{First version with documentation} % \changes{v1.0b}{2011/01/01}{Filenames expanded much earlier: allows nesting.} % \cprotect{\changes{v1.0b}{2011/01/01}}{Environments names were letter-only: % now only control sequences are forbidden. Fixed by switching from % |\catcode=11| to |12| when processing.} % \cprotect[mmm]\changes{v1.0d}{2011/01/12}{|\cprotect| \oarg{spec} to % cprotect a control sequence with the argument specification \meta{spec}} % % % \cprotect\section{Include \verb-\verb- anywhere!} % \label{sec:intro} % % The |cprotect| package attempts to do something that should be % impossible:\cprotect\footnote{The UK \TeX\ FAQ % |http://www.tex.ac.uk/cgi-bin/texfaq2html| states: % \begin{quote} % So |\verb| and |\begin{verbatim}| have to assume that they are getting % the first look at the parameter text; if they aren't, \TeX\ has already % assigned category codes so that the verbatim command doesn't have a % chance. % \end{quote} % The argument is quite sound, but it can be circumvented if one can change % category codes once assigned, which we do.} it allows you to put verbatim % in footnotes\cprotect\footnote{Like this one: \verb-!@#$%^&*()_+-.}, section % titles, \ldots in a straightforward way. The section above was typeset using % \begin{verbatim} % \cprotect\section{Include\verb-\verb- anywhere!}\end{verbatim} % and the footnote was % \begin{verbatim} % ...tes\cprotect\footnote{Like this one: \verb-!@#$%^&*()_+-.}\end{verbatim} % % More generally, let us assume that you want to use verbatim text in % the argument of some macro |\cs| \marg{arg1}, and that this % macro is normally allergic to verbatim. It probably has a good reason % to be allergic, but using an auxiliary file, we can often solve the % problem: if you want \marg{arg1} to contain verbatim, just write % |\cprotect\cs| or |\cprotect{\cs}| instead of |\cs|.\cprotect\footnote{This % solves most problems, for instance, verbatim text in section titles % written as |\cprotect\section|\marg{title} appears correctly in the table % of contents. However, there are still bugs in capitalized headers.} % All the examples I give use very standard macros, but it should work % with any macro.\cprotect\footnote{If you have a macro that works when it is % not preceeded by |\cprotect|, but breaks down if you put |\cprotect| in % front of it, I will be interested to know why.} % % Nesting is supported: \cs{cprotect} cannot appear in a command argument % unless this command is itself \cs{cprotect}ed: % \begin{verbatim} % \cprotect\section{Title \cprotect\emph{emphasized} word} % \end{verbatim} % % The first version of this package did not support macros with several % arguments, nor macros with optional arguments. This new feature is % accessed by giving an optional argument to \cs{cprotect}: % \begin{verbatim} % \cprotect[om]\section[Short title \verb-&^-]{Long title \verb-&^%$-} % \end{verbatim} % Each |o| stands for an optional argument (within |[]|), and |m| stands for % a mandatory argument (within |{}|). For example, one can write % \begin{verbatim} % \[ % \cprotect[om]\sqrt[\verb-%c-]{\cprotect[mm]\frac{\verb-%a-}{\verb-%b-}} % \] % \end{verbatim} % to typeset % \[ % \cprotect[om]\sqrt[\verb-%c-]{\cprotect[mm]\frac{\verb-%a-}{\verb-%b-}} % \] % In fact, the |[om]| argument specifier is optional. % % Some commands will not accept reading from a file as a valid argument. For % instance, the first argument of \cs{hyperlink} cannot be \cs{cprotect}-ed. % Workaround: write |\cprotect{\hyperlink|\marg{arg1}|}|\marg{arg2}, in % other words, \cs{cprotect} the combination of \cs{hyperlink} and its first % argument. This trick can be tried when all else fails. % % % \section{List of user commands} % \label{sec:commandlist} % % \DescribeMacro{\cpro^^@tect} % Possibly the single most useful command is |\cprotect|, used as % |\cprotect| |\foo| \marg{arg1} or |\cprotect| \marg{cslist} \marg{arg1}. % As described in the previous section, the first form behaves as % |\foo| \marg{arg1}, and the second as \meta{cslist} \marg{arg1}. % The difference is that the argument \marg{arg1} can now contain % |\catcode| changes (e.g., induced by the |\verb| command and the % |verbatim| environment). In fact, \marg{arg1} is written to a file, and % then read again as the argument of |\foo|. So using the ideas behind % |\cprotect|, one could in principle build weird macros that read their % arguments several times, with different |\catcode|s in effect each time. % The e-\TeX\ primitive \cs{scantokens} is most probably a better way to % do these things, or you can try to use the experimental macro % |\ReadVerbatimUntil|. % % \DescribeMacro{\cMakeRobust} % If you find yourself using a |\cprotect\foo| combination frequently, and % you try to define \cs{bar} to mean |\cprotect\foo|, you will run into % trouble. The technical point is that I made \cs{cprotect} ``outer'', % which prevents it from being nested in the argument of another command. % % However, the package provides \cs{icprotect}, which is a non-outer version % of \cs{cprotect}. You can write % \begin{verbatim} % \outer\def\bar{\icprotect\foo} % \end{verbatim} % (I like to make \cs{bar} outer, to make sure that it does not get called % from inside a macro argument. It is not necessary.) % % You can also use the typical % \begin{verbatim} % \let\oldfoo\foo % \outer\def\foo{\icprotect\oldfoo}\end{verbatim} % to redefine |\foo| itself instead of a new command |\bar|. The package % provides a wrapper for this construction: |\cMakeRobust\foo| replaces |\foo| % by a version which accepts verbatim. As a stupid example, % \begin{verbatim} % \newcommand{\expon}[1]{\mathrm{#1}^{#1}} % \cMakeRobust{\expon} % \(\expon{Hel\verb+|+o}\)\end{verbatim} % produces % \newcommand{\expon}[1]{\mathrm{#1}^{#1}} % \cMakeRobust{\expon} % \(\expon{Hel\verb+|+o}\), and the verbatim is treated correctly. % % % \DescribeMacro{\cprotEnv} % Some\cprotect\footnote{Todo: rethink \cs{cprotEnv}.} % environments do not really behave as environment in that they % read their argument before acting on it. One such example is |amsmath|'s % |align| environment. For these cases, use |\cprotEnv| as follows. Simply % put |\cprotEnv| |\begin| \marg{name} instead of |\begin| \marg{name}. For % example, % \begin{verbatim} % \cprotEnv\begin{align} % x&=\begin{cases} % 1 &\text{if }\verb"@#%^&*"\\ % 2 &\text{otherwise} % \end{cases} % \end{align}\end{verbatim} % gives % \cprotEnv\begin{align} % x&=\begin{cases} % 1 &\text{if }\verb"@#%^&*"\\ % 2 &\text{otherwise} % \end{cases} % \end{align} % Beware: the |align| environment does something weird at the measuring % step, and \cs{cprotect} will not work very easily (see Section~\ref{sec:bugs} % on bugs below). % % You can use |\CPTbegin| as a short-hand for |\cprotEnv\begin|, but this will % fail when nesting the same environment twice (admittedly, this is rare): the % inner nesting is distinguished by \emph{precisely} the characters % \texttt{\string\begin\{\emph{name}\}}. % % % \DescribeMacro{\ReadVerbatimUntil} % Finally, an odd half-deprecated macro. We use all of the auxiliary macros % that are involved in its construction, but not \cs{ReadVerbatimUntil} % anymore (the code has to be rewritten to make things clearer. % % The aim of this command is to read a % piece of text verbatim, until it reaches an end-marker. % It then writes all that it has read to an auxiliary file for % future use. The most naive approach has a major flaw when nesting is % involved: when parsing |...{}}| for instance, with an end-marker of |}|, we % often wish to stop at the \emph{second} closing bracket, not the first one. % Thus, |\ReadVerbatimUntil| needs to be aware of a begin-marker. Also, for % some applications we need to write things before and after the content % read by |\ReadVerbatimUntil|. Finally, we want to do something once the % file has been written, and possibly something before. % % The syntax is thus |\ReadVerbatimUntil| \oarg{arg1} \marg{arg2} % |^begin|\-|text^end|\-|text^begin|\-|tag^end|\-|tag^|, followed by the text % in which we look for |endtag|. The caret (|^|) can be any character. % It delimits the four verbatim-like arguments of % |\ReadVerbatimUntil|. The strings of letters |begintext| % and |endtext| are pre- and ap-pended to the file. As mentionned before, % |begintag| and |endtag| are used when reading the content, to determine % how far |\ReadVerbatimUntil| should go. The mandatory argument % \marg{arg2} is executed once the whole text has been stored to a file. % Typically, \marg{arg2} involves reading the file one or more times, % and acting on it in any way we like. The optional argument can be used for % hacks such as changing where |cprotect| writes its files. % % % \section{Technical points} % % [...] Will break if |^| does not have its usual catcode at the beginning % and at the end of the \cs{cprotect}ed command. % % Also, will break if |^^E| or |^^L| change catcodes. This choice of symbols % can be changed by setting the options |gobbling-escape =| \meta{letter}, and % |gobbling-letter =| \meta{letter}. The defaults are |gobbling-escape = E| and % |gobbling-letter = L|. % % % % \section{Known bugs/limitations} % \label{sec:bugs} % % Incompatibility with |\pagestyle{headings}|: when a chapter title is put % as a header, it gets upper-cased. If you did |\cprotect\chapter{...}| as % usual, the title has been stored to a file, but now, the name of the file % is capitalized, and \TeX\ cannot find it. % % Issues with nesting of |\cprotect| in |align| environments: the |align| % environment is being too clever with counting braces in its argument. % But we do nasty things to braces, such as |\let\foo{|\iffalse}\fi. This % should in fact not be counted as a brace\cprotect\footnote{In some sense, % it defines |\foo| to be an opening brace.}, but |align| has no way of knowing % that. Thus, it expects a closing brace when there will ba none. A workaround % is to add \iffalse{\fi|\iffalse}\fi| in the body of the align environment, % after any |\cprotect|. Also, the |align| environment itself should be % protected. Here is an example (three |\cprotect|, hence three closing braces): % \begin{verbatim} % \cprotEnv\begin{align*} % \sum\cprotect_{\verb"\k" = 1}\cprotect^{\verb"\N"} \verb"\k" % = \cprotect\frac{\verb"\N"(\verb"\N"+1)}{2} \iffalse}}}\fi % \end{align*} \end{verbatim} % \cprotEnv\begin{align*} % \sum\cprotect_{\verb"\k" = 1}\cprotect^{\verb"\N"} \verb"\k" % = \cprotect\frac{\verb"\N"(\verb"\N"+1)}{2} \iffalse}}}\fi % \end{align*} % % For commands with two or more arguments, it is only possible to put verbatim % in one of the arguments (and the syntax is not great). % % The argument of any command that is prefixed with |\cprotect| has to have % balanced braces, \emph{even when hidden inside verbatim environments, or % behind a comment character}. For instance, % \begin{verbatim} % \cprotect\footnote{On the \verb:{: character} \end{verbatim} % would fail: |\cprotect| would see the brace in |\verb:{:|, and count it % as an opening tag, which then has to be closed. This is most likely % to lead |\cprotect| to gobble the whole file before complaining. Similarly, % \begin{verbatim} % \cprotect\footnote{On the \verb:!: %should it be }? % character}\end{verbatim} % would only gobble until the closing brace in |%should it be }?|, and % I am not sure what error would be produced. % % But we can use one ailment to cure the other! A correct way to typeset % the first example is % \begin{verbatim} % \cprotect\footnote{On the \verb:{: character%} % } \end{verbatim} % if |%| is a comment character at the time it is read. A safer solution % would be to use |\iffalse}\fi| instead of |%}|. It still requires to % be sure that |\| is an escape character when this piece of code is read, % and can lead to problems if the previous token is |\let| for instance. % % % % \section{The code} % \label{sec:code} % %\StopEventually{\PrintChanges\PrintIndex} % % \begin{macrocode} %<*package> % \end{macrocode} % % \subsection{Setting up} % % We first load a few packages % \begin{macrocode} \RequirePackage{ifthen} \RequirePackage{suffix} % \end{macrocode} % % We borrow the idea of quark from |expl3|: |\CPT@qend| expands to % itself, useful for |\ifx| comparisons. % \begin{macrocode} \def\CPT@qend{\CPT@qend} \def\CPT@option@head#1=#2\CPT@qend{#1} \def\CPT@option@tail#1=#2\CPT@qend{#2} \DeclareOption*{% \ifthenelse{% \equal{gobbling-escape}{% \expandafter\CPT@option@head\CurrentOption=\CPT@qend}% }{% \edef\CPT@gobbling@escape{% \expandafter\CPT@option@tail\CurrentOption\CPT@qend }% }{% \ifthenelse{% \equal{gobbling-letter}{% \expandafter\CPT@option@head\CurrentOption=\CPT@qend}% }{% \edef\CPT@gobbling@letter{% \expandafter\CPT@option@tail\CurrentOption\CPT@qend }% }{% \PackageError{cprotect}{Unknown option \CurrentOption}{}% }% }% } \def\CPT@gobbling@escape{E} \def\CPT@gobbling@letter{L} \ProcessOptions\relax % \end{macrocode} % % Then we introduce the commands pertaining to writing % files.\footnote{To be rewritten. For the moment, we use a new file % each time cprotect is used. Thus, many files. But this is needed if % people want to nest cprotect's.} % % We write files |\jobname-1.cpt|, |\jobname-2.cpt|, etc. in order. % \begin{macrocode} \newwrite\CPT@WriteOut \newcounter{CPT@WriteCount} \edef\CPT@filename{\jobname.cpt} \newcommand{\CPT@Write}[1]{% \immediate\openout\CPT@WriteOut=\CPT@filename% \newlinechar`\^^M% \immediate\write\CPT@WriteOut{#1}% \immediate\closeout\CPT@WriteOut% \expandafter\xdef\csname CPT@\CPT@filename\endcsname{% \noexpand\scantokens{#1}% }% %\expandafter\gdef\csname \string\CPT@\CPT@filename\expandafter\endcsname\expandafter{% % \expandafter\protect\csname CPT@\CPT@filename\endcsname}% %\expandafter\show\csname \string\CPT@\CPT@filename\endcsname% %\expandafter\show\csname CPT@\CPT@filename\endcsname% } % \end{macrocode} % % % The next command changes all catcodes to ``other''. It was adapted from % |filecontents.sty|. % \begin{macrocode} \newcommand{\makeallother}{% \count0=0\relax \loop \catcode\count0=12\relax \advance\count0 by 1\relax \ifnum\count0<256 \repeat } % \end{macrocode} % % % \begin{macro}{\CPT@gobbling@escape} % \begin{macro}{\CPT@gobbling@letter} % \changes{v1.0c}{Replaced \cs{relax} by |^^L|, with |L| customizable.} % We make the active character |^^L| of charcode 11 % [letter...], and define it to expand % to \cs{relax} (was hoping to make it % invalid most of the time, but that fails) [...]. Also, failure if |^| is not % of catcode ``superscript''. % % \cs{CPT@escape@hat@hat@L} contains the string of characters |\^^L|, with % |L| replaced by the value of \cs{CPT@gobbling@letter}. % % \cs{CPT@hat@hat@E@hat@hat@L} contains the string of characters % |^^E^^L| where |^^E| is the escape character, and |^^L| is the active % charace. % % We define \cs{CPT@hat@hat@E@hat@hat@L} to be empty: it will simply % be used to % gobble the initial space at the beginning of environments and hide the % end-of-line token that e\TeX\ inserts for every \cs{scantokens}. % % \begin{macrocode} { \catcode`\/=0 /catcode`/\=12 /catcode`/^=12 /xdef/CPT@escape@hat@hat@L{\^^/CPT@gobbling@letter/space} /xdef/CPT@escape@hat@hat@E{\^^/CPT@gobbling@escape/space} /xdef/CPT@hat@hat@E@hat@hat@L{% ^^/CPT@gobbling@escape^^/CPT@gobbling@letter/space} } \expandafter\scantokens\expandafter{% \expandafter\catcode\expandafter`\CPT@escape@hat@hat@E=0} \expandafter\scantokens\expandafter{% \expandafter\catcode\expandafter`\CPT@hat@hat@E@hat@hat@L=11} \expandafter\scantokens\expandafter{% \expandafter\def\CPT@hat@hat@E@hat@hat@L{}} % \end{macrocode} % \end{macro} % \end{macro} % % \cprotect\subsection{|\ReadVerbatimUntil|} % Both |\ReadVerbatimUntil| and its starred version (which we define using % the |suffix.sty| package) take one optional argument \oarg{first-cs} and % a mandatory argument \marg{final-cs}. The \meta{final-cs} is saved as % |\CPT@commandatend| to be executed when we close the file (and the % group).\cprotect\footnote{It is not a straightforward |\aftergroup|, % because I want this to be executed after another |\aftergroup| that % comes later.} % \begin{macrocode} \newcommand\ReadVerbatimUntil[2][]{% \def\CPT@commandatend{#2}% \begingroup #1% \makeallother% \CPT@setup} \WithSuffix\newcommand\ReadVerbatimUntil*[2][]{% \def\CPT@commandatend{#2}% \begingroup #1% \makeallother% \CPT@starsetup} % \end{macrocode} % % |\CPT@setup| reads the four ``verbatim'' arguments following % \marg{final-cs}, and stores them in this order as macros |\CPT@preText|, % |\CPT@postText|, |\CPT@begin|, and |\CPT@end|. The macros which read each % of these arguments need to be defined inside |\CPT@setup|, because % I don't want any constraint on the delimiter. I could write a single % macro that gobbles all four arguments at once, but this would require % a crazy number of |\expandafter|s, so instead I do it one by one. % % If the delimiter was given, say |^|, then we would define |\CPT@readBegin| % as |\def \CPT@readBegin#1^{\def \CPT@begin{#1}\CPT@readEnd}|. % But since |^| is not given explicitly, we need |\expandafter|s to % expand it before the definition takes place. To avoid code repetition, % I did it once and for all in the auxiliary macro |\CPT@def|. Note that % a parameter of |##1| is somehow hidden inside |\CPT@def|, and that the % |##1| inside the replacement text refer to the arguments of the % |\CPT@read...| macros. % \begin{macrocode} \newcommand{\CPT@def}[2]{\expandafter\def\expandafter#1% \expandafter##\expandafter1#2} \newcommand{\CPT@setup}[1]{% \def\CPT@delimiter{#1}% \CPT@def\CPT@readPreText\CPT@delimiter{% \def\CPT@preText{##1}\CPT@readPostText}% \CPT@def\CPT@readPostText\CPT@delimiter{% \def\CPT@postText{##1}\CPT@readBegin}% \CPT@def\CPT@readBegin\CPT@delimiter{% \def\CPT@begin{##1}\CPT@readEnd}% \CPT@def\CPT@readEnd\CPT@delimiter{% \def\CPT@end{##1}\CPT@readContent}% \CPT@readPreText% } \newcommand{\CPT@starsetup}[1]{\CPT@setup#1#1#1} % \end{macrocode} % We also give the variant |\CPT@starsetup|, which has empty % |\CPT@preText| and |\CPT@postText|. % % When |\CPT@setup| is expanded, it will call |\CPT@|\-|readPreText|, % |\CPT@|\-|readPostText|, |\CPT@|\-|readBegin|, and |\CPT@|\-|readEnd|, % and finish with |\CPT@|\-|readContent|, which we describe now. % % % The counter |CPT@numB| will count % the surplus of |begin-tag|s compared to |end-tag|s when we parse the text % following |\CPT@readContent|. And |\CPT@store| is a macro that adds its % argument to an other macro (I was too lazy to learn about token lists). % The storage itself will be initialized later. % \begin{macrocode} \newcounter{CPT@numB} \newcommand{\CPT@store}[1]{\edef\CPT@storage{\CPT@storage#1}} % \end{macrocode} % % The macro |\CPT@readContent| is quite tricky: if the |begin-tag| and % |end-tag| were one character, things would be easy: I would read one % character at a time, and compare it to both |begin-tag| and |end-tag|, % then either store it, and possibly increase or decrease |CPT@numB|, or % decide that I am done if |CPT@numB| becomes negative. % % Unfortunately, I want to use |\ReadVerbatimUntil| for environments, in % which case the |begin-tag| is |\begin{myenv}| and the |end-tag| is % |\end{myenv}|. So two options: % \begin{itemize} % \item code a standard string searching algorithm... I did not feel % like it, but it might lead to a regexp package later on; % \item use \TeX's delimited parameters. % \end{itemize} % I did the latter, using |\CPT@def| again (we want to expand the string % which delimits the parameter before doing the definition). % % The details are ugly: % \begin{itemize} % \item gobble until the first |end-tag|,\cprotect\footnote{This will fail for % devious cases: if |begin-tag| is |abc| and |end-tag| is |bcd|, and % |\CPT@readContent| is followed by |abcd...|: we will wrongly see % |bcd| as an |end-tag|.} and insert a fake |begin-tag|, as well as the % quark guard |\CPT@qend|, % \item inside what we gobbled, gobble |begin-tag|s until reaching the fake % one (marked by the quark guard). % \item continue until we have one more |end-tag| than |begin-tag|. % \end{itemize} % \begin{macrocode} \newcommand{\CPT@readContent}{% \CPT@def\CPT@gobbleOneB\CPT@begin##2{% \ifx\CPT@qend##2\CPT@store{##1}\addtocounter{CPT@numB}{-1}% \else\CPT@store{##1\CPT@begin}\stepcounter{CPT@numB}% \expandafter\CPT@gobbleOneB\expandafter##2\fi}% % \CPT@def\CPT@gobbleUntilE\CPT@end{% \edef\CPT@tempi{##1\CPT@begin}% \expandafter\CPT@gobbleOneB\CPT@tempi\CPT@qend% \ifthenelse{\value{CPT@numB}<0}{% \CPT@store{\CPT@postText}% \CPT@Write{\CPT@storage}\endgroup% \CPT@commandatend% }{% \CPT@store{\CPT@end}\CPT@gobbleUntilE% }% }% \setcounter{CPT@numB}{0}% \def\CPT@storage{\CPT@preText}% \CPT@gobbleUntilE% } % \end{macrocode} % % % \cprotect\subsection{For macros: |\cprotect| and friends} % % \begin{macro}{\cpro^^@tect} % \changes{v1.0c}{2011/01/11}{Made \cs{cprotect} \cs{outer}, and introduced % \cs{icprotect}.} % Equipped with |\ReadVerbatimUntil|, we are ready for the more practical % macros. |\cprotect| cheats: it uses |{| and |}| as a |begin-tag| and % |end-tag|. This works most of the time, but fails in cases such as those % presented in Section~\ref{sec:bugs} (in usual cases there are % workarounds\cprotect\footnote{But I could definitely not have the contents of % this |.dtx| file as a (huge) footnote in some document: since |{| and |}| % change |\catcode|s, it is unlikely that the numbers balance correctly.}). % % We define |\cprotect| as |\outer|, as a check that it is the first % to read its argument. A neat thing is that |\cprotect| will complain % if it is nested inside anything, \cprotect\emph{except if the enclosing % macro is itself |\cprotect|ed}.\footnote{In particular, the author of this % documentation had to use a devious trick (namely, have an ignored character % in the midst of the name) to include even the name of the macro in the left % margin.} % % \begin{macrocode} \outer\long\def\cprotect{\icprotect} % \end{macrocode} % Normally, one should always use |\cprotect|. In some rare cases, it can be necessary % to overcome the |\outer|ness of |\cprotect|. For this we provide |\icprotect|, % where |i| stands for |i|nternal. % % |\icprotect| \oarg{spec} \marg{\cs{cs}} takes as a mandatory argument the control sequence % \cs{cs} that we are protecting, and as a first, optional, argument the argument specification % of \cs{cs}, in the |xparse| style: |m| for mandatory arguments, |o| for optionals, % etc.\cprotect\footnote{Todo: list all the arguments that are supported: for the moment, % |o| and |m|.} \emph{\textbf{No spaces, i.e., % \texttt{[om]}, not \texttt{[o m]}!}} % \begin{macrocode} \newtoks\CPT@commandatend@toks \newcommand{\icprotect}[2][om]{% \def\CPT@argsig{#1}% \def\CPT@cs{#2}% \CPT@commandatend@toks{#2}% \def\CPT@commandatend{\CPT@read@args}% used by RVU. \CPT@commandatend% } \def\CPT@argsig@pop{% \edef\CPT@argsig{\expandafter\@gobble\CPT@argsig}% } % \end{macrocode} % \end{macro} % % Currently, \cs{CPT@read@args} is simply a synonym. % % \begin{macrocode} %\newcommand\CPT@read@args{\CPT@read@m} \newcommand\CPT@read@args{% \ifx\CPT@argsig\empty \expandafter\the\expandafter\CPT@commandatend@toks \else \expandafter\expandafter\expandafter\CPT@read@one \expandafter\CPT@argsig\expandafter\CPT@qend% \fi } \def\CPT@read@one#1#2\CPT@qend{% \def\CPT@argsig{#2}% \def\CPT@tempii{\csname CPT@read@#1\endcsname}% To make the \afterassignment simpler. \afterassignment\CPT@tempii\let\CPT@next=% } % \end{macrocode} % % % \subsubsection{Mandatory arguments} % % % First, we learn how to parse mandatory arguments. We define \cs{CPT@read@m} to read a % mandatory (braced) argument. Note the use of |\bgroup| in |\CPT@read@m|: if the argument % of |\cs| starts with an opening brace, it has been read early, and its |\catcode| will % still be |1|.\cprotect\footnote{I am not sure whether catcodes really matter % in such an |\ifx|.} % % We check whether the next token is a brace or not: % \begin{itemize} % \item If it is, we discard the |{|, and the argument of \cs{cs} stops % at the matching explicit closing brace |}|. (See \cs{CPT@read@mbeg} below, % where |beg| stands for an opening brace.) % \item If it is not, the argument of \cs{cs} is this token only, and there is % no need for \cs{cprotect}ion (see \cs{CPT@read@mone} below). % \end{itemize} % % \begin{macrocode} \newcommand\CPT@read@m{% \ifx\CPT@next\bgroup% \expandafter\CPT@read@mbeg% \else% \expandafter\CPT@read@mone% \fi% } \def\CPT@read@mone{\CPT@cs\CPT@next} % \end{macrocode} % % Since |\ReadVerbatimUntil| makes everything into others, we need braces % to be others when we define most macros in this Section. We thus need % a few |\catcode| changes. Think of \(|{|\to|(|\) and \(|}|\to|)|\). % \begin{macrocode} \begingroup \catcode`\{=12 \catcode`\}=12 \catcode`\(=1 \catcode`\)=2 \gdef\CPT@other@bgroup({) \gdef\CPT@other@egroup(}) \endgroup % \end{macrocode} % % \cs{CPT@read@mbeg} to read a braced mandatory argument once the begin-group symbol % has been read. % \begin{macrocode} \def\CPT@read@mbeg{% \stepcounter{CPT@WriteCount}% \edef\CPT@filename{\jobname-\arabic{CPT@WriteCount}.cpt}% \expandafter\expandafter\expandafter\CPT@commandatend@toks \expandafter\expandafter\expandafter{% \expandafter\the \expandafter\CPT@commandatend@toks % Input a file: \expandafter{% \expandafter\protect \expandafter\input \CPT@filename \relax }% % % Using \scantokens: requires '%' active. % \expandafter{% % \csname \string\CPT@\CPT@filename\endcsname % \expandafter\protect % \expandafter\csname CPT@\CPT@filename\endcsname % }% }% %\showthe\CPT@commandatend@toks% % \end{macrocode} % We append |{\protect \input| \meta{file name}|relax}| at the end of the % token list \cs{CPT@commandatend@toks}. Then we set \cs{CPT@commandatend} % to be this token list. The role of \cs{CPT@commandatend} is to be executed % once the matching |}| is found. Note the \cs{protect}, necessary for % things to work well inside \cs{section}. % % Since we |\edef|ed, |\CPT@filename| contains the expanded version of the % filename. We then use many |\expandafter|s in order to expand the filename % now: we are then sure that the right file will be input as an argument of % |\CPT@cs| (this is the |\cprotect|ed command). % % \begin{macrocode} \begingroup% \makeallother% \def\CPT@preText{}% \let\CPT@postText\CPT@hat@hat@E@hat@hat@L% \let\CPT@begin\CPT@other@bgroup% \let\CPT@end\CPT@other@egroup% \CPT@readContent% }% % \end{macrocode} % % % \cprotect\subsubsection{Optional (|o|) and delimited (|d**|) arguments} % % \cs{CPT@read@o} (for scanning standard optional arguments) is defined to be % \cs{CPT@read@d[]}. % \begin{macrocode} \def\CPT@read@o{\CPT@read@d[]} % \end{macrocode} % % Now for delimited arguments, \cs{CPT@read@d} takes two arguments (the two % delimiters). If the next token, \cs{CPT@next} is the same \emph{character} % as the opening delimiter |#1|, then we read the argument with % \cs{CPT@read@d@beg}. Otherwise, we use \cs{CPT@read@d@none}. % \begin{macrocode} \def\CPT@read@d#1#2{% \if\noexpand\CPT@next#1% \expandafter\CPT@read@d@beg% \else% \expandafter\CPT@read@d@none% \fi% {#1}{#2}% } \def\CPT@read@d@none#1#2{% \CPT@read@args\CPT@next% } % \end{macrocode} % % \cs{CPT@read@d@beg} to read a delimited argument once (if) the beginning % symbol \cs{CPT@d@begin} has been found. The begin-tag and end-tag used by % \cs{ReadVerbatimUntil} and its friends are here \cs{CPT@d@begin} and % \cs{CPT@d@end}. Errata: replaced by |#1| and |#2|. % \begin{macrocode} \def\CPT@read@d@beg#1#2{% \stepcounter{CPT@WriteCount}% \edef\CPT@filename{\jobname-\arabic{CPT@WriteCount}.cpt}% \expandafter\expandafter\expandafter\CPT@commandatend@toks% \expandafter\expandafter\expandafter{% \expandafter\the% \expandafter\CPT@commandatend@toks% \expandafter #1% \expandafter\protect% \expandafter\input% \CPT@filename% \relax% #2% }% % \end{macrocode} % % Since we |\edef|ed, |\CPT@filename| contains the expanded version of the % filename. We then use many |\expandafter|s in order to expand % \cs{CPT@d@begin}, \cs{CPT@d@end}, and \cs{CPT@filename} % the filename now: we are then sure that the right file will be input as % an argument of |\CPT@cs| (this is the |\cprotect|ed command). % % \begin{macrocode} \begingroup% \makeallother% \def\CPT@preText{}% \let\CPT@postText\CPT@hat@hat@E@hat@hat@L% \def\CPT@begin{#1}% \def\CPT@end{#2}% \CPT@readContent% }% % \end{macrocode} % % % % Finally, the |\cMakeRobust| command is a mess, and could probably be improved, % although... it works |:)|. We make the new command \cs{outer}, and use % the inner version \cs{icprotect} of \cs{cprotect}. % \begin{macrocode} \newcommand{\cMakeRobust}[1]{% \def\CPT@cs@name{\expandafter\@gobble\string#1}% \expandafter\let\csname CPT@old@\CPT@cs@name\endcsname #1% \expandafter\outer\expandafter\def\csname\CPT@cs@name\endcsname{% \expandafter\icprotect\csname CPT@old@\CPT@cs@name\endcsname}% } % \end{macrocode} % % % \cprotect\subsection{For Environments: |\cprotEnv\begin| and |\CPTbegin|} % % \DescribeMacro{\CPTbegin} % We introduce the command |\CPTbegin|, which has a behaviour close to % the behaviour of |\begin|. Namely, |\CPTbegin{env}| gobbles its argument % until it sees the matching |\end|, and it writes what it gobbled to % a file. It then inputs the file between |\begin{...}| and |\end{...}|, % as we can see from the definition of |\CPT@commandatend|. % % As for the case of |\cprotect|, we need to setup the values of the four % arguments of |\ReadVerbatimUntil| before reading the content. Since % the |begin-tag| and |end-tag| depend on a parameter, it would be % incredibly messy to try to expandafter the right things, so we % define |\CPT@env@setup| to, well, setup the values of the four % arguments of |\ReadVerbatimUntil|, and then skip directly to % |\CPT@readContent|. % % \begin{macrocode} \newcommand{\CPTbegin}[1]{% \stepcounter{CPT@WriteCount}% \edef\CPT@filename{\jobname-\arabic{CPT@WriteCount}.cpt}% \edef\CPT@commandatend{% \noexpand\begin\noexpand{\noexpand#1\noexpand}% \noexpand\expandafter\noexpand\protect% \noexpand\expandafter\noexpand\input \CPT@filename\relax% \noexpand\end\noexpand{\noexpand#1\noexpand}% }% % \end{macrocode} % Here, we are defining |\CPT@commandatend| to be |\begin{#1}| % |\expandafter| |\protect| |\expandafter| |\input| \meta{filename} % |\end{#1}|, where \meta{filename} is |\CPT@filename|, fully expanded. % Is there a cleaner way of doing that, given how far in the definition % |\CPT@filename| is? % \begin{macrocode} \begingroup% \CPT@env@setup{#1}% \makeallother% \CPT@readContent% } % \end{macrocode} % % As announced, |\CPT@env@setup|, defined with lots of catcode changes % [\emph{this paragraph is not up to date}]. % Since the catcode of |\| changes, I need an extra escape character, % which I take to be |/|. I use two groups so each group is opened and % closed using the same escape character (this is technically irrelevant, % but seems less messy). % \begin{macrocode} \newcommand{\CPT@otherify}[1]{% \expandafter\expandafter\expandafter\@gobble \expandafter\string\csname #1\endcsname } \newcommand{\CPT@env@setup}[1]{% \def\CPT@temp{#1}% \edef\CPT@temp{\CPT@otherify{#1}}% \edef\CPT@temp{\expandafter\strip@prefix\meaning\CPT@temp}% \expandafter\CPT@env@setup@\expandafter{\CPT@temp}% } \def\CPT@env@setup@#1{% \let\CPT@preText\CPT@hat@hat@E@hat@hat@L% \let\CPT@postText\CPT@hat@hat@E@hat@hat@L% \edef\CPT@begin{\string\begin\string{#1\string}}% \edef\CPT@end{\string\end\string{#1\string}}% } % \end{macrocode} % % A final piece of code is needed so that |\CPT|-environments can be % nested: in order to be able to nest, we need |\ReadVerbatimUntil| % to be aware that our environment has been opened when |\CPTbegin{foo}| % or |\begin{foo}| appear in the text. Given the rules for delimited % parameters in TeX, this is quite difficult. A workaround is to replace % |\CPTbegin| by something that ends in |\begin| shuch as |\cprotEnv\begin| % as defined below. Thus, for nesting to work, you need to prepend every % one of your |env| environments with |\cprotEnv|. % \begin{macrocode} \def\cprotEnv\begin{\CPTbegin} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} %\Finale \endinput