LATEX-L Archives

Mailing list for the LaTeX3 project


Options: Use Classic View

Use Proportional Font
Show Text Part by Default
Show All Mail Headers

Topic: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Bruno Le Floch <[log in to unmask]>
Sat, 8 Jan 2011 17:23:32 -0500
text/plain (100 lines)
> First question: why the name \cprotect? I.e., what does the "c" stand
> for?

No good reason. :)

When I started coding, I had no idea how to name that, so I picked a
temporary name. I changed the name after about 40hrs straight (yes, I am
slow) of (il)literate programming, before sending it to CTAN, so the
name is just as bad as the temporary one. We are protecting the Contents
of the arguments of the Command to allow Catcode Changes. Choose
whichever C you like. Also, I guess that being at Cape Town (CPT) for
the year influenced me: internal macros start with \[log in to unmask]

The name should be changed.

> Would it work to make \cprotect an \outer macro, then when it performs
> its \scantokens on its arguments it can redefine itself to be
> non-outer in this case?
> For the more generic case when you need to have
> \cprotect\foo{...\cprotect\bar{...\cprotect\baz{...}...}...}
> I don't imagine there's a way to ensure the \cprotect is present at
> every nesting level. (Although I suppose it would be possible to have
> a messy token-by-token scanning routine (a la ted.sty) in which you
> insert \let\cprotect\cprotecterror after every open brace and
> \let\cprotect\cprotectnormal after every close brace in a token list,
> all of which to be reverted iff \cprotect is in charge of the inner
> brace scanning.)

Actually, I am just thinking of a different way that might be better: my
parsing of the argument(s) of \cprotect\foo verbatim involves setting
all catcodes to 12 (other) just after reading \foo. If the first token
after \cprotect\foo is not of catcode 12, then it means that \cprotect
is not having the first look at the token.

On the other hand, the next token could have catcode 12 despite having
been read before, for instance the bracket for optional arguments. So we
could have something more devious, where all characters are given
catcode 2, before reading the first token in the argument. Then, we go
back to catcode 12 for the actual parsing. Why catcode 2? Because I can
imagine a macro whose argument is delimited by $, say: \foo$...$, but I
cannot imagine someone devious enough to somehow begin an argument by an
character that would be of catcode 2 (end-of-group) at any time.

I am not very convinced that this argument is robust. Any thoughts?

>    \cprotect\section[...\verb|#&!|...]{...\verb|#&!|...}  How does
>\cprotect know what to read in?

I propose the following: \cprotect[argument specification], where the
argument specification is like in xparse. Your example would become


If the optional argument is missing, \cprotect\foo could proceed like

- For \foo's that are neither made with \newcommand nor with
  \DeclareDocumentCommand, we have to guess: ``one optional, plus k
  mandatory'', where k is determined from the parameter text, except if
  this would make it zero: then it would be set to k=1 (because macros
  with one optional argument and no mandatory are less common than {o m}
  ones). That works for \section, \footnote, and friends.

- If \foo was defined through \newcommand with no optional argument,
  then the parameter text read from \meaning\foo is simply #1...#N,
  easy. If there was an optional argument, then looking at the \meaning
  of \\foo gives us the number of arguments.

- For those \foo that were \DeclareDocumentCommand-ed, we could parse
  the \meaning as well, but a much better way would be for xparse to
  store it somewhere. Here is what Joseph Wright replied to me on that

>> What is the best way to know the argument signature of an
>> xparse-defined macro?
> [...] I guess there should be an official interface, so
> \ShowDocumentCommandSignature \foo
> \DocumentCommandSignature \foo
> where the the later should insert the signature in the input stream. If
> this sounds okay I'll add the necessary backend to xparse and include it
> in the update.

- Maybe also add the case of internal commands (\foo:Nn, or whatever),
  where the argument specification would be read from the name? Although
  I don't expect any use for that: internals should not need
  \cprotect. Should they?

-- Bruno