# Efficient way to write backslash to a file

Say I have a writer and an environment (actually an Environ) defined as

\documentclass{article}
\usepackage{environ} % www.ctan.org/pkg/environ
\newwrite\mywriter
\NewEnviron{writethis}
{\immediate\write\mywriter{\BODY}}
\begin{document}
\immediate\openout\mywriter=writehere.txt
...
\immediate\closeout\mywriter
\input{writehere.txt}
\begin{document}


What I want to do is copy everything in a writethis environment to writehere.txt and include it in the document later on.

It becomes problematic when I want to write a backslash. Not just a \textbackslash or $\backslash$ (in math mode) but one that can be used to write commands such as in \textbf{abc}. (The compiler refuses to write a \ via \textbackslash.)

I know of the solution

\makeatletter
\begin{writethis}\@backslashchar textbf{abc}\end{writethis}
\makeatother


but it would be really tedious to write \makeatletter...\makeatother every time I need a \. Somewhat naively, I tried to define a command to replace the above:

\newcommand\back
{\makeatletter\@backslashchar\makeatother}


for the sake of writing simply

\begin{writethis}\back textbf{abc}\end{writethis}


but the compiler refuses. (It says Improper alphabetic constant. \spacefactor, I have no clue why this \spacefactor pops up.)

So here is my question:

Is there a way to write a \ to a file, shorter than \makeatletter\@backslashchar\makeatother?

This may have something to do with this question (perhaps even a duplicate?). I read it but didn't understand how to use Philippe Goutet's solution.

-
Isn't \immediate\write\mywriter{\detokenize\expandafter{\BODY}} what you need? –  egreg Jul 16 '14 at 14:11
@egreg works perfect! You can post an answer if you want. –  barto Jul 16 '14 at 14:14

You want an “almost verbatim” write:

\documentclass{article}
\usepackage{environ} % www.ctan.org/pkg/environ

\newwrite\mywriter
\NewEnviron{writethis}
{\immediate\write\mywriter{\unexpanded\expandafter{\BODY}}}
\begin{document}

\immediate\openout\mywriter=\jobname-later.tex
\begin{writethis}\textbf{abc}\end{writethis}
\immediate\closeout\mywriter

Something

\input{\jobname-later}
\end{document}


Here's the contents of \jobname-later (I use \jobname not to clobber my files, use whatever name you prefer):

\textbf {abc}


The space will be ignored in input.

If you want to add fixed text before and after the contents of the environment, do

\NewEnviron{writethis}{%
\immediate\write\mywriter{%
\unexpanded{<before>}%
\unexpanded\expandafter{\BODY}}%
\unexpanded{<after>}%
}%
}


where <before> and <after> stand for arbitrary TeX code. You don't want \expandafter for them, in general, which is needed in the middle term in order to get the expansion of \BODY.

-
I was playing around a bit, and strangely things like \immediate\write\mywriter{\unexpanded\expandafter{\textbf{abc}\BODY}} do not work. But it's just a remark, I don't need it for my purposes. (It can be solved by placing the \textbf{abc} in a seperate \unexpanded\expandafter.) –  barto Jul 16 '14 at 14:35
@barto Of course it doesn't work: you're just expanding \textbf and not \BODY, which is then written literally in the output file. You don't need \expandafter for writing \textbf{abc} before the body; I'd rather say you don't want it. –  egreg Jul 16 '14 at 14:37
Oh well. I'm not such a TeXpert –  barto Jul 16 '14 at 17:51

You've already given egreg the tick for the easy part-) so I'll answer

I have no clue why this \spacefactor pops up.)

You have

\newcommand\back
{\makeatletter\@backslashchar\makeatother}


\makeatletter changes the catcode of @ to make it a letter but catcodes affect the conversion of input characters to tokens. they have no effect on tokens that have already been read.

The argument to \newcommand has already been read tokenized and stored using the catcodes in force at this point so the definition is (showing one token per line)

\makeatletter
\@
b%
a%
a%
c%
k%
s%
l%
a%
s%
h%
c%
h%
a%
r%
\makeatother


so when \back is used \makeatletter executes but it has no effect on following tokens so the next token to execute is \@ which is designed to be used next to a . to affect the sentence space, its definition is

\def\@{\spacefactor\@m}


so you end up trying to assign 10000 to \spacefactor in vertical mode. the solution (in general, although in this case the problem can be avoided in different ways) is to change the catcodes while making the definition not while using it so:

\makeatletter
\newcommand\back
{\@backslashchar}
\makeatother

-
wouldn't \protect\xxx or \string\xxx work? or would it only survive just one expansion when more are needed? (no time to experiment.) –  barbara beeton Jul 16 '14 at 15:03
Waw, I didn't expect that to work. I'd think the compiler refuses when being asked to write (or being referenced to) \@backslashchar in a non-atletter 'environment', but apparently we can just do this. I'll keep egreg's answer as the accepted because it is the easiest way, but thanks for shedding light on this approach! –  barto Jul 16 '14 at 17:50
@barto it's just the same as (say) \section that expands to a definition based on \@startsection it doesn't stop working when @ is not a letter, so long as it's a letter when \section is defined. You should give the tick to me, egreg is always so happy when I steal a tick from him. –  David Carlisle Jul 16 '14 at 18:22