How to write the documentclass into a file

Suppose I have received a selfcontained LaTeX source file, main.tex. It includes a file of macro definitions, my_macros.tex, that the author included in the preamble. This macro file is under my control, but, besides beeing included by the author, shall not interfer with the LaTeXing of the author.

To make it more precise: The file my_macros.tex may well be empty, on the computer the author uses. But because the author is my customer, he agreed to including it. On my computer, I can fill my_macros.tex with whatever I like.

Is it possible to write some macros, and put them into my_macros.tex, that do the following:

After issuing

\$ latex main.tex


I'll find a file in my filesystem, say main.nem, that contains the documentclass of the file main.tex.

So if for example main.tex looked like this

\documentclass{eth_super_article}
% ...
\input{my_macros.tex}
% ....
\begin{document}
%....
\end{document}


then main.nem will contain the line and only the line

\documentclass{eth_super_article}

-
Related Question: How to write the preamble into a file. –  Peter Grill Oct 25 '12 at 16:16

If you can assume that the users will never add \RequirePackage instructions before \documentclass, then the class name will be the first item in \@filelist.

\makeatletter
\def\hr@getclass#1.#2\@nil{\def\hr@class{#1}}
\expandafter\hr@getclass\@filelist\@nil
\immediate\openout\@partaux=\jobname.nem
\immediate\write\@partaux{%
\noexpand\documentclass
\expandafter\ifx\expandafter\\\@classoptionslist\\\else
[\@classoptionslist]\fi{\hr@class}}
\immediate\closeout\@partaux
\makeatother


If the above restriction cannot be assumed something more is needed.

I abused \@partaux rather than allocating a new stream; it's used by \include, which should not appear in the preamble, so it seems quite safe.

An extended version that copes with possible \RequirePackage calls before \documentclass:

\makeatletter
\def\hr@getclass#1.#2,#3\@nil{%
\def\hr@class{#1}\def\hr@ext{#2}\def\hr@filelist{#3}%
\ifx\hr@ext\@clsextension
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\expandafter\hr@getclass\hr@filelist,\@nil}%
}
\let\hr@filelist\@filelist
\expandafter\hr@getclass\hr@filelist,\@nil
\immediate\openout\@partaux=\jobname.nem
\immediate\write\@partaux{%
\noexpand\documentclass
\expandafter\ifx\expandafter\\\@classoptionslist\\\else
[\unexpanded\expandafter{\@classoptionslist}]\fi{\hr@class}}
\immediate\closeout\@partaux
\@onlypreamble\hr@getclass
\@onlypreamble\hr@class
\@onlypreamble\hr@ext
\@onlypreamble\hr@filelist
\makeatother


We start a recursion that ends when a file name of the form filename.cls is found, which surely is the main class; you're out of luck if one user says \input{my_macros} before \documentclass, of course.

-
@HeinzRasched We need \def here, as the macro has delimited arguments. –  egreg Oct 25 '12 at 13:04
@HeinzRasched You didn't ask for the options. ;-) Fixed –  egreg Oct 25 '12 at 13:44
@HeinzRasched I added also the version for devious users. :) –  egreg Oct 25 '12 at 14:12
With xkvltxp, kvoptions-patch, catoptions or skeyval-ltxpatch loaded before \documentclass, \@classoptionslist can contain expandable tokens or undefined commands. So I have added \unexpanded\expandafter{\@classoptionslist} to your solution. Also, if a class file loads another class file with, e.g., \LoadClass, you may want to show all the loaded classes. –  Ahmed Musa Oct 26 '12 at 10:13
@AhmedMusa Thanks for this; my opinion is that using \RequirePackage before \documentclass should be used very sparingly (it changes \jobname, for instance). The OP wants to know the \documentclass line, so what the class does is unimportant. I really don't know why recording the line is needed, to be honest. –  egreg Oct 26 '12 at 11:22