What are the naming rules for \newwrites in TeX? Can \newwrites be created dynamically?
\newwrite\foo
assigns the symbolic name to be equal to a write file register, so anything that is possible with \csname ...\endcsname
is also possible with \newwrite
or \newread
, as well as with \openout
,\openin
, \closein
, \closeout
.
\newwrite
itself is no TeX
primitive but assigns the next free output stream number to a macro name via a \chardef
, the same is true for \newread
-- both stream directions are independent of each other!
In this sense, a file handle is nothing more than a macro expanding to a number, this way \immediate\write6
etc. would be possible too. (or think of writing to the shell with \immediate\write18
(given that shell-escape is enabled)).
If there's another macro inside the \csname...\endcsname
statement, use an \expandafter
.
The point is now: How feasible is this approach? It can be quite tedious to repeat the \csname ... \endcsname
usage all the while!
Here is a similar code from the \@starttoc
command in latex.ltx
:
\def\@starttoc#1{%
\begingroup
\makeatletter
\@input{\jobname.#1}%
\if@filesw
\expandafter\newwrite\csname tf@#1\endcsname
\immediate\openout \csname tf@#1\endcsname \jobname.#1\relax
\fi
\@nobreakfalse
\endgroup}
It can be seen that the file handle of the toc - file is generated on the fly over and over again (for each \@starttoc
- call)
Some points to consider:
My solution is only correct if opening, writing and closing is within the
\foreach
cycle, since this establishes a group, so the filename handle macro name isn't available outside of the\foreach
- cycle. However, this procedure is not recommended.Is it really necessary to use a new handle for each file? No, not really, since apparently the file handle is generated, the file opened etc. and the 'active' file is determined by the
\foreach
loop variable\langcode
, so it's not easily possible to write to more than one file(handle) at the 'same' time.
\documentclass{article}
\usepackage{fontspec}% xelatex
\usepackage{tikz}% foreach
\usepackage{morewrites}% unnecessary for this example, but useful in practice to exceed 16-write limit in TeX
\def\writelangouts{%
\foreach \langcode in {da,de,en} {% from tikz package
\expandafter\newwrite\csname filehandle-\langcode\endcsname
\immediate\openout\csname filehandle-\langcode\endcsname=\jobname-semantically_useful_suffix_\langcode.txt
\immediate\closeout\csname filehandle-\langcode\endcsname
}%
}%
\def\otherwritelangouts{%
\foreach \langcode in {da,de,en} {% from tikz package
\def\fhandle{\csname filehandle-\langcode\endcsname}
\newwrite\fhandle%
\immediate\openout\fhandle=\jobname-semantically_useful_suffix_\langcode.txt
\immediate\closeout\fhandle
}%
}%
\AtEndDocument{\writelangouts}
\begin{document}
\jobname
\end{document}
Assuming the file above is called fhandle.tex
, the .log
- file shows that following file handles are generated (at the end of the document, since \writelangouts
is used in \AtEndDocument
)
ABD: EveryShipout initializing macros
\AtBeginShipoutBox=\box53
\filehandle-da=\write5
\openout4 = `fhandle-semantically_useful_suffix_da.txt'.
\filehandle-de=\write6
\openout4 = `fhandle-semantically_useful_suffix_de.txt'.
\filehandle-en=\write7
\openout4 = `fhandle-semantically_useful_suffix_en.txt'.
If your task is to open a file, write on it and close it all in the same cycle of the \foreach
loop, you need just one file handle.
\documentclass{article}
\usepackage{tikz}% foreach
\newwrite\langouts
\newcommand\writelangouts{%
\foreach \langcode in {da,de,en} {% from tikz package
\immediate\openout\langouts=\jobname-\langcode.txt
\immediate\write\langouts{This is \langcode}
\immediate\closeout\langouts
}%
}
\AtEndDocument{\writelangouts}
\begin{document}
\jobname
\end{document}
The contents of the written files
test-da.txt
This is da
test-de.txt
This is de
test-en.txt
This is en