3

My script needs to read a command from one aux file (testFileWriteReadExecute.yposIN.txt), then execute that same command which is a actually a call to a write macro which writes another command to a second file (testFileWriteReadExecute.yposOUT.txt).

Currently it produces the command in the PDF output instead of executing it. At some stage I had something similar working halfway, but have messed it up since, unfortunately.

testFileWriteReadExecute.yposin.txt looks like this:

\writeVerse{A}{1}{F}\comment{30580738}\endcomment
\writeVerse{A}{1}{L}\comment{29138946}\endcomment
\writeVerse{A}{2}{F}\comment{29138946}\endcomment
\writeVerse{A}{2}{L}\comment{27566082}\endcomment
\writeVerse{A}{3}{F}\comment{27566082}\endcomment
\writeVerse{A}{3}{L}\comment{25993218}\endcomment

MWE:

\documentclass[pagesize=pdftex, fontsize=10]{scrbook}
\usepackage[paperwidth=11.2cm, paperheight=17.4cm, top=1cm,bottom=1cm, left=1cm, right=1cm]{geometry}
\usepackage{fontspec}

\AtBeginDocument{%
    \newwrite\yposoutputfile%
    \openout\yposoutputfile=\jobname.yposout.txt%
}
\AtEndDocument{%
    \closeout\yposoutputfile%
}

\newcommand\writeVerse[3][]{%
  \writelines{#1}{#2}{#3}%
}

% Write the position to file.
\def\writelines#1#2#3{%
  \pdfsavepos%
    \write\yposoutputfile{%
    \string\writeVerse%
    \string{#1\string}%
    \string{#2\string}%
        \string{#3\string}%
        \string\comment\string{\the\pdflastypos\string}\string\endcomment%
    }%
}

% Open the file to read the commands.
\def\fromFile{
  \newread\yposinputfile%
  \openin\yposinputfile=\jobname.yposin.txt%
    \readline\yposinputfile to \fromFileLine%
  \closein\yposinputfile%
  \fromFileLine
}

\begin{document}
\fromFile %\writeVerse{A}{1}{F}
 LIBRO de la generación de Jesucristo, hijo de David, hijo de Abraham. \fromFile %\writeVerse{A}{1}{L}
\writeVerse{A}{2}{F} \textbf{2}~Abraham engendró á Isaac: é Isaac engendró á Jacob: y Jacob engendró á Judas y á sus hermanos:\writeVerse{A}{2}{L}
\writeVerse{A}{3}{F} \textbf{3}~Y Judas engendró de Thamar á Phares y á Zara: y Phares engendró á Esrom: y Esrom engendró á Aram:\writeVerse{A}{3}{L}
\end{document}

EDIT

The basic concept of what I want is simple.

  1. The XeLaTeX script grabs a line from the one text file which happens to be a TeX command, i.e. \writeVerse{A}{1}{F}
  2. It places in a particular place of the document this command, where this command gets executed/expanded instead of printed.
  3. The command is a call to a macro which in turn writes to another file.

EDIT 2:

Since the closest answer is this one by egreg I'll accept it, although it does not answer the fundamentals of my question. It does seem that this is a limitation in TeX.

5
  • Your \fromFile command always reads the first line, because it opens and closes the file each time. But the main problem is that it can't be read, because it has been also opened for writing in it, so it's empty when \fromFile is found.
    – egreg
    Mar 4, 2013 at 10:47
  • @egreg Thanks, but I thought I circumvented that issue by using two files. A \jobname.yposIN.txt and a \jobname.yposOUT.txt. Did I miss something there?
    – McGafter
    Mar 4, 2013 at 10:54
  • You want to read an inexistent file.
    – egreg
    Mar 4, 2013 at 11:06
  • @egreg Did you mean the input file? I've created the input file by some other means (manually in this case), that's why I've given the contents thereof separately. The output file gets created by the tex script. Both exists with contents after the xelatex run, although the output is shorting the first two lines, due to the write command not executing.
    – McGafter
    Mar 4, 2013 at 11:13
  • Have a look at \th@mbs@verview from the thumbs package: "The internal command \th@mbs@verview reads a line from file \jobname.tmb and executes the content of that line - if that line has not been processed yet, in which case it is just ignored (see \@unused)."
    – Stephen
    Sep 17, 2016 at 14:59

1 Answer 1

3

I don't really understand what \fromFile should do. However, you can avoid juggling the files by doing the write in the standard .aux file, and then overwriting the old "ypos" file at begin document.

\documentclass[pagesize=pdftex, fontsize=10]{scrbook}
\usepackage[
  paperwidth=11.2cm,
  paperheight=17.4cm,
  top=1cm,bottom=1cm,
  left=1cm,
  right=1cm]{geometry}
%\usepackage{fontspec}

% Allocate an output and an input stream
\newwrite\yposfileout
\newread\yposfilein

% If the file has been written, open it for reading
\AtBeginDocument{%
  \immediate\closeout\yposfileout
  \IfFileExists{\jobname.ypos.txt}
    {\openin\yposfilein=\jobname.ypos.txt}
    {\let\fromFile\relax}
}

% Write the position to file.
\makeatletter
\def\writelines#1#2#3{%
  \pdfsavepos%
  \write\@auxout{%
    \string\rewriteVerse{%
      \string\writeVerse{#1}{#2}{#3}%
      \string\comment\string{\the\pdflastypos\string}\string\endcomment
    }}%
}
\newif\if@writeverseopened
% when the `.aux` file is being read in at begin document, write out a new ypos file
\def\rewriteVerse#1{%
  \if@writeverseopened\else
    \immediate\openout\yposfileout=\jobname.ypos.txt
    \@writeverseopenedtrue
  \fi
  \immediate\write\yposfileout{\unexpanded{#1}}%
}
% Do nothing when the aux file is read in at end document
\AtEndDocument{\let\rewriteVerse\@gobble}

% Read the commands from the ypos file
\def\fromFile{%
  \readline\yposfilein to \fromFileLine
  \texttt{\fromFileLine}
}
\makeatother

% \writeVerse has an optional argument and two mandatory ones
\newcommand\writeVerse[3][]{%
  \writelines{#1}{#2}{#3}%
}


\begin{document}
\fromFile \writeVerse[A]{1}{F} LIBRO de la generación de Jesucristo,
hijo de David, hijo de Abraham. \fromFile \writeVerse[A]{1}{L}
\writeVerse[A]{2}{F} \textbf{2}~Abraham engendró á Isaac: é Isaac
engendró á Jacob: y Jacob engendró á Judas y á sus
hermanos:\writeVerse[A]{2}{L} \writeVerse[A]{3}{F} \textbf{3}~Y Judas
engendró de Thamar á Phares y á Zara: y Phares engendró á Esrom: y
Esrom engendró á Aram:\writeVerse[A]{3}{L}
\end{document}

You can use two files, provided your script changes the name of the former output file to the input file.

\documentclass[pagesize=pdftex, fontsize=10]{scrbook}
\usepackage[
  paperwidth=11.2cm,
  paperheight=17.4cm,
  top=1cm,bottom=1cm,
  left=1cm,
  right=1cm]{geometry}
\usepackage{atveryend,pdftexcmds}

\newwrite\yposfileout
\newread\yposfilein
\AtBeginDocument{%
  \IfFileExists{\jobname.yposin.txt}
    {\openin\yposfilein=\jobname.yposin.txt}
    {\let\fromFile\relax}
  \immediate\openout\yposfileout=\jobname.yposout.txt
}

% Write the position to file.
\def\writelines#1#2#3{%
  \pdfsavepos%
  \write\yposfileout{%
    \string\writeVerse{#1}{#2}{#3}%
    \string\comment\string{\the\pdflastypos\string}\string\endcomment
    }%
}
% Open the file to read the commands.
\def\fromFile{%
  \readline\yposfilein to \fromFileLine
  \texttt{\fromFileLine}
}

\makeatletter
\AtVeryEndDocument{%
  \closein\yposfilein
  \immediate\closeout\yposfileout
  \ifnum\pdf@shellescape>\z@
    \immediate\write18{mv \jobname.yposout.txt \jobname.yposin.txt}
  \fi
}
\makeatother

\newcommand\writeVerse[3][]{%
  \writelines{#1}{#2}{#3}%
}


\begin{document}
\fromFile \writeVerse[A]{1}{F} LIBRO de la generación de Jesucristo,
hijo de David, hijo de Abraham. \fromFile \writeVerse[A]{1}{L}
\writeVerse[A]{2}{F} \textbf{2}~Abraham engendró á Isaac: é Isaac
engendró á Jacob: y Jacob engendró á Judas y á sus
hermanos:\writeVerse[A]{2}{L} \writeVerse[A]{3}{F} \textbf{3}~Y Judas
engendró de Thamar á Phares y á Zara: y Phares engendró á Esrom: y
Esrom engendró á Aram:\writeVerse[A]{3}{L}
\end{document}

The \fromFile macro reads one line of the input file at each call.

If I run the file with -shell-escape, the \write18 istruction takes care of the name switching for the next run. You can do it with your script, of course.

6
  • Thanks but the \fromFile is really a replacement for writing out \writeVerse{A}{1}{F} etc. each time since due to other factors beyond the scope of the MWE the parameters will change for \writeVerse. So in reality you would not see \writeVerse{A}{1}{F} in there at all except in the aux files. This script gets called by an external OS script and might have to be run even up to a 1000 times before the layout would be satisfactory. But that's handled by the external script. This TeX file just need to be able to read an executable command from the first aux file and write to the second.
    – McGafter
    Mar 4, 2013 at 13:38
  • @McGafter Sorry, but I don't get it.
    – egreg
    Mar 4, 2013 at 13:39
  • Ok, Thanks. I've given a small clarification in the OP for what it's worth. The main issue at present is reading a command from an aux file and executing it on the same run.
    – McGafter
    Mar 4, 2013 at 14:07
  • @McGafter You can't do that: if the file is open for writing, you can't (reliably) read from it.
    – egreg
    Mar 4, 2013 at 14:10
  • I understand, but I want to read from the first file then write to a second file on the same run.
    – McGafter
    Mar 4, 2013 at 14:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .