6

How can I create a counter which is fixed once it has been set?

The idea is to insert some kind of remarks into a text which should be numbered, but increasing with the date of actual implementation into the source code.

They should not depend on the order in the source code, and they should keep their value even if some of them are removed.

Here not a MWE, but an idea how the implementation should look like:

\documentclass{article}
\begin{document}
  \mynote{Some note I've added first}, 
  \mynote{A fourth note}, 
  \mynote{A second note}, 
  \mynote{A fifth note}, 
  \mynote{A third note}.    
\end{document}

This should give an output as:

Note 1: Some note I've added first
Note 4: A fourth note,
Note 2: A second note,
Note 5: A fifth note,
Note 3: A third note.

If I delete the line with the second note, it should give:

Note 1: Some note I've added first,
Note 4: A fourth note,
Note 5: A fifth note,
Note 3: A third note.

  • At the moment I can only think of manually setting the countervalue on each note. – Martin - マーチン Jul 15 '13 at 15:51
  • @Martin to point why I want to use counters is to avoid searching in the document to find the actual number. – jjdb Jul 15 '13 at 15:56
  • 3
    I guess you can do it with the help of your editor, but not from *tex alone (one reason at least: two identical tex documents are supposed to give the same output, no matter in which order they were written). – T. Verron Jul 15 '13 at 16:01
  • 2
    The idea is to write the current counter value on a temp file and then when you'll use the command again you'll need to read the last line of the temp file to know the new value to be used on the counter. – Sigur Jul 15 '13 at 16:09
  • 1
    Basically, you want your input file to have some "memory". You can achieve that by writing to and reading from some auxiliary file, as suggested by Sigur. See this. – jub0bs Jul 15 '13 at 16:12
7

Here is a proof of concept, but using an auxiliary file in this way is very dangerous, because an error might ruin the previous copy and the order of the notes would be lost. So a routine that backs up the .notes file must be run at the end of the LaTeX job.

\documentclass{article}

\makeatletter
\newwrite\jjdbout
\newcounter{jjdbnotes}
\def\countnotes#1#2{\stepcounter{jjdbnotes}}
\def\savenote#1#2{%
  \expandafter\gdef\csname #1\endcsname{#2}%
  \addnote{#1}{#2}%
}
\makeatletter
\def\addnote#1#2{%
  \toks@=\expandafter{\jjdbnotes}%
  \xdef\jjdbnotes{\the\toks@^^J%
    \noexpand\jjdbnote{#1}{#2}}%
}
\makeatother
\let\jjdbnote\countnotes
\InputIfFileExists{\jobname.notes}{}{}
\let\jjdbnote\savenote
\gdef\jjdbnotes{} % initialize
\InputIfFileExists{\jobname.notes}{}{}

\newcommand{\mynote}[1]{%
  \par
  \ifcsname\pdfmdfivesum{#1}\endcsname
    \textbf{Note \csname\pdfmdfivesum{#1}\endcsname: }#1%
  \else
    \stepcounter{jjdbnotes}%
    \expandafter\addnote{\pdfmdfivesum{#1}}{\thejjdbnotes}%
    \textbf{Note \thejjdbnotes: }#1%
  \fi
}
\AtEndDocument{
  \immediate\openout\jjdbout=\jobname.notes
  \immediate\write\jjdbout{\unexpanded\expandafter{\jjdbnotes}}
}

\begin{document}
  \mynote{Some note I've added first},
  \mynote{A fourth note},
  \mynote{A second note},
  \mynote{A fifth note},
  \mynote{A third note}.

\end{document}

The .notes file is read twice; the first one for counting the entries and the second one to assign a meaning to the lines.

Each note is stored as its MD5 checksum, which should be uniquely associated to the text. Of course, if a note text gets changed, the ordering will be lost again.

So to each checksum the note number is assigned. If during a run we find a new note, it will be added to the \jjdbnotes macro, whose contents will be written out to the .notes file at the end of the job. Note that TeX cannot append lines to an existing file.

The shown output has been obtained by uncommenting the lines one by one according to the stated order.

enter image description here

A better approach would be to have the notes stored in a separate file notes.tex say in the form

\makeatletter
\newcommand{\savenote}[2]{\@namedef{jjdb@note#2}{#1}}
\newcommand{\mynote}[1]{\@nameuse{jjdb@note#1}}
\makeatother

\savenote{Some note I've added first}{1}
\savenote{A second note}{2}
\savenote{A third note}{3}
\savenote{A fourth note}{4}
\savenote{A fifth note}{5}

and do \input{notes} in the preamble. Then in the document you can use

\mynote{1},
\mynote{4},
\mynote{2},
\mynote{5},
\mynote{3}.

In this way you simply add the notes sequentially.

  • 2
    +1. Day after day I'm sure that @egreg is the creator of TeX... lol – Sigur Jul 15 '13 at 17:31
  • @Sigur I never wear traditional Norwegian overalls. ;-) youtube.com/watch?v=cI6tt9QfRdo – egreg Jul 15 '13 at 17:32
  • +1, nice! would give another +1 for the second solution, and another +1 for the command \jjdbnotes – jjdb Jul 16 '13 at 7:46
  • In the third line of the second code block, there is a closing bracket missing. – jjdb Jul 16 '13 at 8:53
  • @jjdb There was, you weren't able to see it. ;-) Thanks. – egreg Jul 16 '13 at 8:58
2

I think that what you want is exactly the case where the cross-referencing in LaTeX doesn't help you : it's enough to hard code them. If you want to format (bold and so on), you can use a description environement, or create you own command like :

\newcommand{\mynote}[1]{\par\noindent\bfseries Note#1}

and use

\mynote{1} some text
\mynote{3} some other text

EDIT : As suggested by other users, add '\writecommand in\mynote` to get something like :

\documentclass{article}
\begin{document}
\newwrite\notenumber
\immediate\openout\notenumber=note.dat
\newcommand{\mynote}[1]{%
           \immediate\write\notenumber{#1}\par\noindent\bfseries Note~#1:}
\mynote{3} the note number 3
\mynote{1} the note number 1
\end{document}

You can then sort them in yourtext editor, or in LaTeX by using the anwswer of this question

  • The bold is not the point, I've just put it as the output was not in separate lines before the edit. Still, if I have a huge document with hundreds of unsorted notes, how should I find the next number I have to put as argument? – jjdb Jul 15 '13 at 16:21
  • Using an auxiliary file is not a good way to go; if it gets corrupted, everything is lost. – egreg Jul 15 '13 at 17:03
  • @egreg: in my approach, this file would only contains a list of the hard-codded numbers, then you have merely nothing to loss, which is not already in the tex field, isn'it ? – Jhor Jul 15 '13 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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