63

I am interested in the basic mechanism behind writing stuff to the .aux file. (Or some other auxiliary file).

Let's say I want to write myself a basic package for making notes on my files. (I know packages already exist for doing this. The point of this question is not to work out how to get comments on my paper, it is to learn about an aspect of the basics of TeX/LaTeX.)

So I have something like this in my preamble:

\usepackage{xcolor}
\newif\ifcomments
\commentstrue
\newcommand\comment[1]{%
  \ifcomments
  \textcolor{red}{\textsf{#1}}
  \else
  \fi
}

This means I have comments I can turn on and off. Now, the next stage is I want a list of comments to appear in an itemize at the end of the document, each comment listed along with its page number. To achieve this, it seems like the easiest way would be to write each comment (plus its page number) to an auxiliary file, and then have a command \writecomments that prints the contents of that file. (Or something of that sort).

How, in simple terms, could I achieve this?

NB this question is designed to help me learn about the basics of TeX/LaTeX, so solutions that involve packages doing a lot of the work will be frowned upon.

Edit I've had two very interesting answers offering different ways to achieve what I want in my example. Neither answer, however, really gets to the real answer I wanted, which would be a, accessible introduction to TeX's/LaTeX's "write to auxiliary file" mechanism.

What I'd like is a more basic answer that someone newer to TeX/LaTeX could read and understand. I feel the current answers are a little too high level.

7
  • 3
    @Seamus: I don't think this question should be community wiki - it may receive a higher-than-average number of answers, but it is not a big-list/subjective one.
    – lockstep
    Commented Feb 12, 2011 at 16:09
  • @lockstep I guess my reasoning was that it would be cool to have one nice introductory/summary answer that could be CWed into providing a nice resource for people interested in how the auxiliary files work.
    – Seamus
    Commented Feb 12, 2011 at 17:26
  • 1
    @Seamus: I see -- but in this case, only the summary answer (to be added later) should be CWed, while any other answer (and the question itself) should be able to generate reputation.
    – lockstep
    Commented Feb 12, 2011 at 17:34
  • 1
    @lockstep I have removed the suggestion to CW. I agree with you.
    – Seamus
    Commented Feb 12, 2011 at 19:15
  • @Seamus: Well, you said you wanted to learn about an aspect of the basics of TeX/_LaTeX_, and both answers address how it's done in LaTeX. Or am I mistaken? Commented Feb 21, 2011 at 19:37

2 Answers 2

53

There is a user friendly LaTeX package: newfile. You can use it to read and write files easily. It provides normal file IO functions, and also verbatim file IO functions. It is more suitable for your example, than those low-level macros. The package document has some good examples.

A naive example (similar to table of contents):

\documentclass{article}
\usepackage{newfile}
\newoutputstream{comment}
\openoutputfile{\jobname.comment}{comment}

\begin{document}

\section{Test}
text one
\addtostream{comment}{\noexpand\item comment one at page \thepage}

text two
\addtostream{comment}{\noexpand\item comment two}


\section{Comments}

\closeoutputstream{comment}
\begin{enumerate}
    \input{\jobname.comment}
\end{enumerate}

\end{document}

Macros will expand when write to file. It is very important to control the expansion. Some macros should not be expanded, like \item here; while some macros should be expanded, like \thepage and \thesection here.


In TeX, there are \newwrite, \openout, \immediate, \write, \closeout, \ifeof etc. A good resource is chapter 30 of TeX by Topic.

The same example using TeX primitives:

\documentclass{article}
\newwrite\commentfile
\openout\commentfile=\jobname.comment

\begin{document}

\section{Test}
text one
\write\commentfile{\noexpand\item comment one at page \thepage}

text two
\write\commentfile{\noexpand\item comment two in section \thesection}

\section{Comments}

\closeout\commentfile
\begin{enumerate}
    \input{\jobname.comment}
\end{enumerate}

\end{document}

In LaTeX kernel, which you can refer source2e, you can learn from \@starttoc, \@wirtefile, \addcontentsline (for contents) etc.

The same example (works like standard TOC):

\documentclass{article}

\makeatletter
\newcommand\addcommentitem[1]{%
  \write\@auxout{\noexpand\@writefile{comment}{\noexpand\item #1}}}
\newcommand\printcomment{%
  \section*{Comments}
  \begin{enumerate}
    \item[] Here are some comments:
    \@starttoc{comment}
  \end{enumerate}}
\makeatother

\begin{document}

\section{Test}
text one
\addcommentitem{comment one at page \thepage}

text two
\addcommentitem{comment two in section \thesection}

\printcomment

\end{document}
2
  • Concerning your "TeX primitives" example, did you forget a step? I am getting ! LaTeX Error: File writetofile.comment' not found.` (file is called writetofile.tex) Commented Mar 20, 2016 at 12:16
  • Nevermind. Now I understand the purpose of \immediate. It ensures that the file is written to immediately (before the first \input) instead of at page shipout. So for future readers, just add \immediate before \openout (to create the file handle immediately) and in this case before at least one \write to make sure you write immediately (before the first \input call). Otherwise, the list won't have any \item and complain about that. \closeout does not need it. The handle will just get closed at shipout. Commented Mar 20, 2016 at 16:04
32

If you have one write handle left you can do it with the following commands which are also used for .toc, .lof, .lot, etc.

\@starttoc{<extension>}

Reads the file with the given extension (\jobname.<extension>) and opens it for writing afterwards. The file is initially empty. Creates the output file handle \tf@<extension> .

\@writefile{<extension>}{<code>}

Writes code using the output handle \tf@<extension> if it exists.

I have these macros in macros2e and was planning to add a short HowTo for exactly this application.

You can define a \listofcomments initially as \relax and \writecomments (or \makecomments) defines it than to \@starttoc{cmt}, which reads/creates '\jobname.cmt'.


You should be able to write directly to the current .aux file (main or include file) with:

 \write\@auxout{...}

or, if you want to write explicitly to the main .aux file:

 \write\@mainaux{...}

They create an whatsit so the page number should be correct.

For other, new files you need to create a write handle and open the file first. This is done using:

 \newwrite\myhandle% There are only 16 write handles, even with eTeX!
 \openout\myhandle=<filename>\relax% or space
 % ...
 \closeout\myhandle % to close the file

You can prefix all of these commands (except \newwrite) with \immediate to make same execute immediately without creating a whatsit. Then however the page counter won't be correct yet.

1
  • 2
    When you used up all 16 write handles, the morewrites package could be helpful.
    – Stephen
    Commented Nov 16, 2013 at 13:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .