Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

When typesetting letters is common practice to have a reference such as:

   XXX-yl-0001

Where the last number is incremented for each successive letter. Normally, I hand-code the number. When having hundreds of letters one tends to now and then make mistakes and duplicate or miss references.

Can someone propose a method to automate this with TeX? Important is to only increment once for each run, i.e., you don't want the counter to increment if you re-run the file. Please note I am out of inspiration for a MWE.

My suggestion, is probably one needs two files. The first one to totalize and a local per jobname to keep the specific letter reference.

share|improve this question
    
The easiest way is to put the number in the filename and then access it with \jobname and leave your editor the job of allocating a new file for each letter –  David Carlisle Sep 12 '13 at 14:46
    
@DavidCarlisle I am trying to avoid deciding or typing the number in any form:) Currently I have a web interface with old php doing it for me but I want to retire it, as it is not very practical. –  Yiannis Lazarides Sep 12 '13 at 14:49
    
you wouldn't type the number but (assuming you use emacs) M-x new-letter could just look around the disk and invent a new filename by incrementing the number from the highest found, then open the buffer on the new file. –  David Carlisle Sep 12 '13 at 14:52
    
@DavidCarlisle I don't use EMACS and even if I did, my secretary would never figure it out. Idea behind the question is that one can save it under any name but the command say \OurRef would insert the right number. –  Yiannis Lazarides Sep 12 '13 at 14:55
    
If all letters of a certain project are stored in the same directory, and you never compile an old letter again, then define an aux-file, say <jobname>.no. Then run (Lua-)LaTeX to get the jobname.no file and let Lua or TeX count the number of the *.no files in this directory and you've got your number after the second run. –  Keks Dose Sep 12 '13 at 15:56
show 9 more comments

2 Answers

Here is a ConTeXt based solution. It uses datasets, which is the ConTeXt mechanism for multi-pass data. The basic idea is to store the MD5sum of the file and the count of the letter in the auxiliary file. At each run compare the stored value of MD5sum with the current value. If the md5sum has changed, increment the number and store it in the auxiliary file. Of course, if you delete the auxiliary file, the number is reset to zero. (For simplicity, I assume that the file suffix is always .tex)

\definedataset[letterdata]

\startluacode
  local datasets = job.datasets
  local filename = environment.inputfilename .. '.tex' -- temp hack
  local checksum = file.checksum(filename)

  local set = "letterdata"

  datasets.setdata{
    name = set,
    data = { checksum = checksum }
  }

  local oldsum  = datasets.getdata(set, 1, "checksum", "")
  local number  = datasets.getdata(set, 2, "number", 0)

  if oldsum ~= checksum then
    number = tonumber(number) + 1
  end

  datasets.setdata{
    name = set,
    data = { number = number }
  }


  context.setvalue("letternumber", number)
\stopluacode

\starttext

Value: \letternumber

\stoptext

This will increment the number whenever you change the file and recompile. Recompiling the same file will not increment the number.

share|improve this answer
    
I like your solution and will accept it as the correct answer. I will do this a bit later as I want to see if there are any comments to my solution. –  Yiannis Lazarides Sep 12 '13 at 17:21
add comment

Quick LaTeX hack. Maybe not as elegant as the ConTeXt solution proposed by Aditya. Uses two streams. One keeps the totals and another caches the value of a letter.

\documentclass{article}

\begin{document}
\newcounter{total}
\setcounter{total}{1000}
\def\autoinc{%
        \newread\inputstream
        \immediate\openin\inputstream=\jobname.lcl
        \immediate\read\inputstream to \auxcommand
        \immediate\closeout\inputstream
    \gdef\OurRef{XXX-XX-\auxcommand}

}
%% First we check if a file with the jobname exists holding the RefNumber
%% If it does not exist increment the totalizer and write to file
\IfFileExists{\jobname.lcl}{\autoinc}{%
%% Read totals from file
        \newread\inputstream
        \immediate\openin\inputstream=autoincrementtotals.lcl
        \immediate\read\inputstream to \auxcommand
        \immediate\closeout\inputstream
    \setcounter{total}{\auxcommand}        
    \stepcounter{total}
%% Update totals file
    \newwrite\tempfile
    \immediate\openout\tempfile=autoincrementtotals.lcl
    \immediate\write\tempfile{\thetotal}%
    \immediate\closeout\tempfile

    \gdef\OurRef{XXX-XX-\thetotal}
    %% write to jobname.lcl
    \newwrite\tempfile
    \immediate\openout\tempfile=\jobname.lcl
    \immediate\write\tempfile{\thetotal}%
    \immediate\closeout\tempfile
}
\OurRef
\end{document}

Needs a bit more error checking and is good to go. One could also extend to cache the date as well of the letter based on this method.

share|improve this answer
    
Doesn't LaTeX have a standard means of storing variables in the .aux file for storing multi-pass data? Why store the variable in a separate auxiliary file –  Aditya Sep 12 '13 at 17:52
    
@Aditya It does, but is the first file people wipe out, as well if you need to LaTeX twice LaTeX will override it. In this case both the totals as well as the particular letter ref needs to be cached. Although one can use the .aux this way also you only need only one pass. –  Yiannis Lazarides Sep 12 '13 at 17:57
    
Ah, now I see what you actually wanted. Your letters are different TeX document. I was assuming that you edit the same tex file to create an updated reply. My solution is not appropriate for your situation. –  Aditya Sep 12 '13 at 18:45
    
@Aditya Oops! I skimmed over your code and thought was ok:) –  Yiannis Lazarides Sep 12 '13 at 18:52
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.