bug-texinfo
[Top][All Lists]

## Re: ampersand issue with texi2dvi

 From: Gavin Smith Subject: Re: ampersand issue with texi2dvi Date: Sat, 8 Sep 2018 12:23:46 +0100 User-agent: Mutt/1.5.23 (2014-03-12)

On Thu, Sep 06, 2018 at 08:46:57PM +0100, Gavin Smith wrote:
> > If we can distinguish & followed by a letter from everything else,
> > this problem can be fixed, I think.
>
> perhaps there could be some preprocessing of an entire @def line at once
> to replace the & at the top level with a control sequence.

It is possible, but I am not sure if it is worth it. There is too much
difficult-to-understand macro trickery in texinfo.tex already. My
favourite solution at the moment is to introduce a Texinfo command @& to
typeset an & on a def line. And maybe @ampchar{} or @ampersandchar{} for
good measure, following the pattern of the other commands described in
the "Special Characters" section of the Texinfo manual.

A rough implementation of the preprocessing I mentioned is below,
in the \processtoplevel macro. The code to replace & with something else
has not been written but it wouldn't be hard to. This code may be
inefficient due to repeatedly scanning over the same input to find macro
arguments. I did not use any definitions, i.e. \def or \let so the code
is "fully expandable". There would certainly be other ways to implement
this using \def or \let, but I doubt whether any way of implementing it
would actually be easy to understand. If it is not a natural use of
TeX's features, I'd suggest avoiding it.

\def\embolden#1{%
{\bf #1}%
}

% \expandaftergroupII{XXX}Y{Z} - expand Y{Z} before expanding XXX, then
% remove the braces around XXX.
\def\expandaftergroupII#1#2#3{%
\expandafter\swap\expandafter{#2{#3}}{#1}%
}

\def\swap#1#2{%
#2#1%
}
\let\removefi\swap

% get the text up to the first opening brace.
% do the needful with that text.
\def\dooutsidebraces#1\endcollected#2#{%
\expandaftergroupII{\doinsidebraces#1}\processfunction{#2}\endcollected
}

\def\insertdeleteafter#1#2#3{#1#2#3\deleterest}
\def\deleterest#1\deleteend{}

% check what is inside the braces. if it is \finish, stop and leave
% everything collected inside #1.
\def\doinsidebraces#1\endcollected#2{%
\insertdeleteafter\ifx\finish#2\relax\deleteend #1%
\else\removefi{%
\dooutsidebraces#1{#2}\endcollected%
}\fi
}

% replace #1 with everything that is outside any braces with the
% results of processing that with \processfunction.
\def\processtoplevel#1{\dooutsidebraces\relax\endcollected#1{\finish}}
% the \relax here is to stop the first argument to \dooutsidebraces ever
% being surrounded by braces, which would cause them to be removed.

\let\processfunction=\embolden
\processtoplevel{xxxxx{y{w}}zzz{neenwaw}{hello}}

\end