5

I have a latex document which in the main part lists a number of "tasks" (for students to solve); to each task belongs a "script", however, all scripts are supposed to be printed in an appendix at the end of the document. For this purpose, the environment "skript" is built to copy its content to a file and re-insert it at the end of the LaTeX run. Tasks and scripts are numbered, and the numbers should correspond to each other.

And here is the problem: TeX seems to expand the script number only after re-inserting the scripts at the end of the document. However, at that time, the task counter is obviously at its maximum value leading to all scripts getting the same number.

Is there a way to get TeX to expand the task counter before storing it to the external file?

A minimal example is the following (where count is the task number):

\documentclass{article}
\usepackage{skripts}
\newcounter{count}

\begin{document}
    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    Now insert the scripts corresponding to the tasks at the document's end:

    \includeSkripts
\end{document}

Which outputs:

enter image description here

Obviously, \thecount, when used inside the "skript" environment has been evaluated only after the counter has been set to its highest value.

The package "skripts" (also in a minimal version) looks as follows:

\ProvidesPackage{skripts}[2009/11/03 v0.1 Styledefinitionen]

\usepackage{verbatim}

\newenvironment{ex@skripts}[1]{#1}{}

\newwrite\verbatim@outSkr % Define file. 
\immediate\openout\verbatim@outSkr=\jobname.skr  % Open file for writing. 

\def\skript{
\@bsphack
\let\do\@makeother\dospecials
\catcode`\^^M\active
\def\verbatim@processline{%
\immediate\write\verbatim@outSkr{\the\verbatim@line}}%
\immediate\write\verbatim@outSkr{\string\begin{ex@skripts}{Script}}
\verbatim@start}

\def\endskript{%
\immediate\write\verbatim@outSkr{\string\end{ex@skripts}}
\@esphack}

\newcommand*{\includeSkripts}{%
\immediate\closeout\verbatim@outSkr    % Close file. 
\InputIfFileExists{\jobname.skr}{}{}
\newwrite\verbatim@outSkr % Datei wird definiert 
\immediate\openout\verbatim@outSkr=\jobname.skr  % Open file for writing. 
}

Now, I am aware that according to this minimal example, there are several solutions to my problem (such as giving "count" as a parameter to the "skript" environment). However, in my actual, more complex context, it is important to solve the problem in the described setting without any structural changes to the environment.

EDIT: I already tried this quite crazy hack:

\romannumeral-`X\foo

which I got from here.

  • I'm not familiar with the skripts package, but you may want to look into expl3 (texdoc interface3). It makes this kind of stuff a lot simpler. – Sean Allred Mar 16 '15 at 14:57
  • let me guess: Lingnau's book on LaTeX Hacks? ;-) – user31729 Mar 16 '15 at 15:01
  • @SoundsOfSilence: Yes! Works like a charm - in principle... – lukas.coenig Mar 16 '15 at 15:03
  • 1
    I think answers in how-to-defer-content-to-a-later-part-of-the-document can help you. – Ignasi Mar 16 '15 at 15:04
  • 1
    texdoc is just another program available to you (like pdflatex, biber, arara, etc.). It's primarily used to pull up package documentation (texdoc <package>), but there is other documentation, too. If you enter texdoc interface3 into your terminal (or command line, same thing), it will open that PDF. – Sean Allred Mar 16 '15 at 15:07
4

One way to achieve this, is to write the content of the counter value explicitly to the file via \string, before the verbatim stuff starts.

\immediate\write\verbatim@outSkr{%
  \string\setcounter{count}{\number\value{count}}% 
}%

Writing \thecount verbatim into the skript file is useless for it will always use the last counter value (4 in this case), not the logical one which belongs to the actual script number.


\documentclass{article}
\usepackage{skripts}
\newcounter{count}

\begin{document}
    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    \refstepcounter{count}
    Here comes task \thecount:
    \begin{skript}
        \thecount
    \end{skript}

    Now insert the scripts corresponding to the tasks at the document's end:

    \includeSkripts
\end{document}

\ProvidesPackage{skripts}[2009/11/03 v0.1 Styledefinitionen]

\usepackage{verbatim}

\newenvironment{ex@skripts}[1]{#1}{}

\newwrite\verbatim@outSkr % Datei wird definiert
\immediate\openout\verbatim@outSkr=\jobname.skr % Datei wrid zum
Schreiben geöffnet

\def\skript{% 
\immediate\write\verbatim@outSkr{%
\string\setcounter{count}{\number\value{count}}% 
}% 
\@bsphack
\let\do\@makeother\dospecials \catcode`\^^M\active
\def\verbatim@processline{%
\immediate\write\verbatim@outSkr{\the\verbatim@line}}%
\immediate\write\verbatim@outSkr{\string\begin{ex@skripts}{Script}}
\verbatim@start}

\def\endskript{%
\immediate\write\verbatim@outSkr{\string\end{ex@skripts}} \@esphack}

\newcommand*{\includeSkripts}{% 
\immediate\closeout\verbatim@outSkr %schließt die Datei
 \InputIfFileExists{\jobname.skr}{}{}
% No good idea!!!!!!
%\newwrite\verbatim@outSkr % Datei wird definiert
%\immediate\openout\verbatim@outSkr=\jobname.skr % Datei wrid zum Schreiben geöffnet 
}
|improve this answer|||||
  • Ah! This looks great! In the minimal context it certainly works! I will need some time to try it in the "real" context, but the question is obviously answered. Thanks! – lukas.coenig Mar 16 '15 at 15:08
  • @lukas.coenig: It's not fail safe, of course – user31729 Mar 16 '15 at 15:09
  • Whatever you mean by that... (Btw. how on earth can you answer so quickly? - You don't have to answer that, too, I'm just really impressed!) – lukas.coenig Mar 16 '15 at 15:12
  • @lukas.coenig: I used a similar approach once :-P (and the dark side is strong in me ;-)) – user31729 Mar 16 '15 at 15:14
  • Ah! ;-) But still... – lukas.coenig Mar 16 '15 at 15:15
2

You could have more counters to take care of, so I define a macro \skriptcounters that accepts a list of counter names; such a list is used to write a second argument to ex@Skript of the form \setcounter{<name>}{<value>}, where the value has been computed when the skript environment starts.

Just for showing how the thing works I used also the section counter (although it's not really good to change the value mid document; it's just by way of example).

\documentclass{article}

%\usepackage{skripts} % the code is in the document
\usepackage{verbatim}

\makeatletter
% here starts the code of skripts.sty
\newenvironment{ex@skripts}[2]{#2#1}{\par}

\newwrite\verbatim@outSkr % Datei wird definiert 
\immediate\openout\verbatim@outSkr=\jobname.skr  % Datei wrid zum Schreiben geöffnet 

\newcommand{\skriptcounters}[1]{%
  \gdef\skript@counters{#1}%
}
\skriptcounters{}% initialize

\newenvironment{skript}
 {%
  \@bsphack
  \let\do\@makeother\dospecials
  \catcode`\^^M\active
  \def\verbatim@processline{%
    \immediate\write\verbatim@outSkr{\the\verbatim@line}%
  }%
  \toks@={}%
  \@for\next:=\skript@counters\do{%
    \edef\skript@temp{\the\toks@\string\setcounter{\next}{\the\value{\next}}}%
    \toks@=\expandafter{\skript@temp}%
  }
  \immediate\write\verbatim@outSkr{%
    \string\begin{ex@skripts}{Script}{\the\toks@}%
  }
  \verbatim@start
 }
 {%
  \immediate\write\verbatim@outSkr{\string\end{ex@skripts}}%
  \@esphack
 }

\newcommand*{\includeSkripts}{%
  \immediate\closeout\verbatim@outSkr    % schließt die Datei 
  \InputIfFileExists{\jobname.skr}{}{}
%  \immediate\openout\verbatim@outSkr=\jobname.skr  % Datei wrid zum Schreiben geöffnet 
}
% end of code for skripts.sty (uncomment the \immediate line above)
\makeatother

\newcounter{count}
\skriptcounters{count,section}

\begin{document}

\section{Title}

\refstepcounter{count}
Here comes task \thecount:
\begin{skript}
  \thecount\ in Section \thesection
\end{skript}

\refstepcounter{count}
Here comes task \thecount:
\begin{skript}
  \thecount\ in Section \thesection
\end{skript}

\section{Another}

\refstepcounter{count}
Here comes task \thecount:
\begin{skript}
  \thecount\ in Section \thesection
\end{skript}

\refstepcounter{count}
Here comes task \thecount:
\begin{skript}
  \thecount\ in Section \thesection
\end{skript}

Now insert the scripts corresponding to the tasks at the document's end:

\section{Scripts}

\includeSkripts

\end{document}

The last \immediate has been commented out just for checking the contents of the skript environment.

Notice that the \end{skript} instruction should not be indented, or the environment will receive a blank line.

enter image description here

Here's the contents of the .skr file:

\begin{ex@skripts}{Script}{\setcounter{count}{1}\setcounter{section}{1}}
  \thecount\ in Section \thesection
\end{ex@skripts}
\begin{ex@skripts}{Script}{\setcounter{count}{2}\setcounter{section}{1}}
  \thecount\ in Section \thesection
\end{ex@skripts}
\begin{ex@skripts}{Script}{\setcounter{count}{3}\setcounter{section}{2}}
  \thecount\ in Section \thesection
\end{ex@skripts}
\begin{ex@skripts}{Script}{\setcounter{count}{4}\setcounter{section}{2}}
  \thecount\ in Section \thesection
\end{ex@skripts}
|improve this answer|||||
  • Cool stuff! I will check that out, too. It may well be more suitable to my real scenario than SoundsOfSilence's solution. – lukas.coenig Mar 16 '15 at 17:48
  • @lukas.coenig I might try making it better with some aliasing in order not to clobber outside values. – egreg Mar 16 '15 at 17:52
  • @lukas.coenig: If you would have posted your real scenario another solution could have been provided ;-) – user31729 Mar 16 '15 at 20:59
  • @SoundsOfSilence: Yes, but then people would have said: Are you crazy? Post an MWE! :-) But I am considering posting a more complex version as I'm afraid (not sure yet, however - it's unfortunately a little confusing) that both solution might not work for me... – lukas.coenig Mar 17 '15 at 6:07
  • @egreg: How would that go? (Just a verbal hint would be nice, so I can estimate how it would affect the applicability to my scenario.) – lukas.coenig Mar 17 '15 at 6:10

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.