# \ensuremath expansion fitting context

I'm writing an elisp script to expand commands defined in the preamble to their definition. I need to do this replacements for my job and, also, to simplify the reading of math texts to a sight-impaired math student. I'm not the author of the documents. I'm a typesetter and my job is "to format" scientific papers.

E.g. if I have in the preamble:

\def\PA{\ensuremath{\mathrm{A}}}


I need to expand each instance of \PA in the document to its definition.

The way I do this is: In the elisp part of my script, in a while loop, I:

• search for a user-defined command (e.g., \COMMAND),
• insert "\writetotempfile\COMMAND" and compile,
• then I remove \writetotempfile

Thus I use the \writetotempfile command once at a time in the document, for every instance of user defined commands. Here \writetotempfile is the following code:

\newcommand{\writetotempfile}[1]
{#1\newwrite\tempfile%
\immediate\openout\tempfile=expandedCommand.tmp%
\immediate\write\tempfile{\unexpanded\expandafter{#1}}%
\immediate\closeout\tempfile}%


so, e.g., when I have

\writetotempfile\PA


that returns me the string "\ensuremath {\mathrm {A}}" in the expandedCommand.tmp file. My .tmp file is overwritten each time.

When I have \ensuremath in the definition I need to remove it and to expand the command fitting the context (e.g., in this case, $\mathrm{A}$ or simply \mathrm{A}). With some elisp regexp replacements I can clean the string to "\mathrm {A}" but it would be simpler to me if I could get the "$" or "not $" form of the expansion, fitting the context. That is, I need to get the $\mathrm{A}$ expansion in text (e.g. some text \PA some text) , and the \mathrm{A} expansion when I have $\PA$ (or \PA in math environments).

Some code may clarify my purpose:

\documentclass{article}

\usepackage{xspace}

\def\PA{\ensuremath{\mathrm{A}}\xspace}

\newcommand{\writetotempfile}[1]
{#1\newwrite\tempfile%
\immediate\openout\tempfile=expandedCommand.tmp%
\immediate\write\tempfile{\unexpanded\expandafter{#1}}%
\immediate\closeout\tempfile}

\begin{document}

\writetotempfile\PA   % to be expanded to $\mathrm{A}$

$\writetotempfile\PA$ % to be expanded to \mathrm{A}

\writetotempfile\PA   % to be expanded to \mathrm{A}

\end{document}


IMPORTANT! In the example above, I have 3 instance of \writetotempfile, but in reality I will use it once at a time.

• it's not clear what your tex question is, or is this an emacs lisp question? Either way I would consider starting from one of the existing latex to xxx convertors such as latexml which already have a lot of code to deal with such this kind of context dependency in latex, the resulting html documents are probably a lot easier to handle. – David Carlisle Jun 3 '17 at 19:34
• @DavidCarlisle This is a LaTeX question. All the code I used in the example is LaTeX/TeX code. I need to write an interactive emacs function so the a solution that needs a html conversion does not fit my goal. – Gabriele Nicolardi Jun 3 '17 at 20:38
• the small fragments of code you have posted are tex yes but it isn't at all clear where you use those commands. the example should always be a complete document that people can run to see the issue. I can not guess where you have \writetotempfile\PA just once, or every time it is used or??? if \PA is used three times, twice in math mode and once in text, how often do you do \writetotempfile\PA and what do you want to write each time? – David Carlisle Jun 3 '17 at 20:43
• @DavidCarlisle I understand. You're right. I'll post a complete document as soon as I can. Just for you to know I use the \writetotempfile command once at time in the document (I use a while loop to insert the command and compile for every instance of user defined commands). – Gabriele Nicolardi Jun 3 '17 at 21:06
• @egreg I really thank you for your patience. I hope the last editing to clarify my question. – Gabriele Nicolardi Jun 4 '17 at 13:25

You can redefine \ensuremath and \xspace during the \write.

One needs a protected write, though, which will produce \protect tokens.

\documentclass{article}

\usepackage{xspace}
\usepackage{xpatch}

\makeatletter
% from https://tex.stackexchange.com/a/229017/4427
% get a copy of \protected@write
\let\protected@iwrite\protected@write
% patch the copy to add \immediate
\xpatchcmd{\protected@iwrite}{\write}{\immediate\write}{}{}
%
\newcommand{\write@ensuremat}[1]{%
\ifmmode#1\else$#1$\fi
}

\newwrite\tempfile % this must be outside the definition of \writetotempfile
\immediate\openout\tempfile=\jobname.tmp % I want all three occurrences
\newcommand{\writetotempfile}[1]{%
%  \immediate\openout\tempfile=\jobname.tmp
\protected@iwrite\tempfile{\let\ensuremath\write@ensuremat\let\xspace\@empty}{#1}%
%  \immediate\closeout\tempfile
#1%
}
\makeatother

\def\PA{\ensuremath{\mathrm{A}}\xspace}

\begin{document}

\writetotempfile\PA   % to be expanded to $\mathrm{A}$

$\writetotempfile\PA$ % to be expanded to \mathrm{A}

$$\writetotempfile\PA % to be expanded to \mathrm{A}$$

\end{document}


I moved the opening of the stream outside the macro, in order to show the effect in all three occurrences (and changed the file name not to clobber my files).

Here's the contents of the .tmp file:

$\protect \mathrm {A}$
\protect \mathrm  {A}
\protect \mathrm  {A}


As you see, the first occurrence has the dollars, the other two don't.

• BEUTIFUL! This will save me some regex replacement. Thank you. – Gabriele Nicolardi Jun 4 '17 at 18:00

I found a solution (that still needs some regexp replacement) with the \ifmmode command.

\newcommand{\writetotempfile}[1]
{#1\newwrite\tempfile%
\immediate\openout\tempfile=expandedCommand.tmp%
\ifmmode%
\immediate\write\tempfile{\unexpanded\expandafter{#1}}%
\else%
\immediate\write\tempfile{$\unexpanded\expandafter{#1}$}%
\fi%
\immediate\closeout\tempfile}


Now I have the \$ in the right places so I have only to clean the code from the \ensuremath string.

• it is impossible to understand this answer or the question. However you almost certainly do not want to have \newwrite inside the definition otherwise a new write stream will be allocated every use (and there are at most 16 write streams). – David Carlisle Jun 4 '17 at 9:16
• @DavidCarlisle I'm sorry for that. May be my english is not good enough to explain my purpose. Luckily I found the solution that I needed by myself and my script now works great. Thank you for your effort. – Gabriele Nicolardi Jun 4 '17 at 9:51