How to use luatex callbacks to generate a verbatim copy of the input file

I'm trying to devise a LuaTeX solution for the question Extracting the contents of text in a specified environment into a new file, but it is turning more difficult than expected.

To begin, I need to solve a problem which seemed simple enough, but I'm unable to solve properly. I want to use some of the LuaTeX callbacks or hooks to dump into a file a copy of each line of the main document file.

My first approach was to hook into process_input_buffer, with this code:

-- luafuncions.lua
f = io.open(tex.jobname .. "-copy.tex", "w")

letpass = function(line)
f:write(line.."\n")
return nil
end
callback.register("process_input_buffer",letpass)


When I use the following tex document:

\directlua{dofile("luafunctions.lua")}
% Example.tex
\documentclass{article}
\usepackage{fontspec}
\usepackage{lipsum}

\begin{document}
1. \lipsum[1]
2. \lipsum[2]
3. \lipsum[3]
\end{document}


And compile it through lualatex, I get:

1. The expected Example.pdf file in which all looks correct
2. The file Example-copy.tex which I expected to contain a copy of Example.tex (except perhaps for the first line)

However, I get a 1.4Mb file (gasp!) which starts and ends with:

% Example.tex
\documentclass{article}
\usepackage{fontspec}
%%
%% This is file article.cls',
%% generated with the docstrip utility.

%... 33750 lines omitted

\begin{document}

%... 4874 lines omitted

1. \lipsum[1]
2. \lipsum[2]
3. \lipsum[3]
\end{document}
\relax


So, sort of worked :-) But I guess that what is happening is that all the lines read from .cls, .sty, .def, .aux etc... are being processed by the calback too, and thus they are being dumped.

I want to avoid that. So I hoped that I could hook some other callback to the event of an external file being open (and closed), and set a boolean to let my function know that it should not write those parts.

However I cannot figure which callback can be useful to do this. Callbacks open_read_file and close look promising, but apparently I have to provide a reader if I use those callbacks. I would hoped that if my hooks returned nil, the default readers will be used, but it is not that way.

Is there a simple solution for this problem?

• What's the desired behaviour for an \input or \include line? For example, one might want to have a single .tex file which includes all of the code within the body of the file. Mar 8 '13 at 21:10
• @JosephWright The desired behaviour is to write in the copy the same \input line which is in the source, and nothing else. The resulting copy has to be identical to the original (except perhaps for the first line, which installs the callback and then it will not be processed by it). Mar 9 '13 at 0:46

You can do this without a callback but maybe you need one for some reason. If not, then the following works (as far as I can tell):

--luafunctions.lua

myout = io.open(tex.jobname.."-copy.tex", "w")
myin = io.open(tex.jobname..".tex", "r")
for line in myin:lines() do
myout:write(line.."\n")
end
myout:close()
myin:close()


With your main .tex being.

\directlua{dofile("luafunctions.lua")}
\documentclass{article}
\usepackage{fontspec}
\usepackage{lipsum}

% Example.tex
\begin{document}
1. \lipsum[1]
2. \lipsum[2]
3. \lipsum[3]
\end{document}
`

Also, there is some code here that might help with your original goal.

• Thank you. There were reasons for using a callback, I want to be able to programatically (from tex) interrupt or resume the verbatim copy, so that some parts of the tex file are not copied. However your approach is a lot easier, and gave me another idea to solve the problem, so I'm accepting it. Mar 9 '13 at 0:22