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.

I want to make a macro to import all TeX input files in a directory in which the input file containing the macro exists. When reading an external file, TeX appends a blank line to the last iteration.

In the following code I use a bad algorithm because there are two loops. The first one is used to find the total file, and the other one is used to do the main job.

\documentclass{article}
\usepackage{listings}

\lstset{language={[LaTeX]TeX},breaklines=true}


\def\X
{%
    \immediate\write18{cmd /c dir /b *.tex > \jobname-temp.txt}%
    \newread\myfile
    \openin\myfile=\jobname-temp.txt
    \newcount\counter
    \counter=0
    \loop
        \unless\ifeof\myfile
        \read\myfile to\mydata
        \advance \counter by 1
    \repeat
    \closein\myfile
    \openin\myfile=\jobname-temp.txt
    \advance \counter by -1
    \loop
        \ifnum \counter > 0
        \read\myfile to\mydata
        \section\mydata
        \lstinputlisting{"\mydata"}\newpage
        \advance \counter by -1
    \repeat
    \closein\myfile
}


\begin{document}
\X
\end{document}

I want to use a single loop to increase the performance.

How to detect a blank line inserted by TeX when reading an external file line by line?

share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

Simply check for EOF again after reading the line.

Minimum Working Example:

\documentclass{article}
\usepackage{filecontents}

\begin{filecontents*}{\jobname.dat}
first
second
third
fourth
\end{filecontents*}

\newread\myfile

\newcommand*\readfile{%
    \immediate\openin\myfile=\jobname.dat\relax
     \loop\unless\ifeof\myfile
        \read\myfile to\mydata
        \ifeof\myfile\else
            \section\mydata
        \fi
    \repeat
    \immediate\closein\myfile
}

\begin{document}
\readfile
\end{document}

If you want to avoid the double EOF check than use a recursive macro like the following:

\newcommand*\readfile{%
    \immediate\openin\myfile=\jobname.dat\relax
    \ifeof\myfile\else% file exists?
       \expandafter\readoneline
    \fi
    \immediate\closein\myfile
}

\def\readoneline{%
    \read\myfile to\mydata
    \ifeof\myfile\else
        \section\mydata
        % ...
        \expandafter\readoneline
    \fi
}

The added empty line adds a \par if the (original) external line ends with a line break (2x line breaks => \par, as always). Therefore \mydata will contain \par (which you would know if you would have used \show to debug it as I told you earlier). You can test for this using:

\def\lastline{\par}

%...

\ifx\mydata\lastline
  %...
\fi

Of course this test will also be true for any other implicit or explicit \par line in the input file, so testing for EOF is actually safer in general, but here you want to avoid all of such input lines anyway (not that they will appear anywhere else in you example).

share|improve this answer
    
why did you not think a simpler one as shown below? –  xport Aug 9 '11 at 9:41
add comment

I improve Martin's algorithm. I don't use a recursive approach because it might be broken due to stack overflow (without .com) if there are too many files. I also don't use double testing for EOF. :-)

\def\X
{%
    \immediate\write18{cmd /c dir /b *.txt > \jobname-temp.dat}%
    \newread\myfile
    \openin\myfile=\jobname-temp.dat\relax
    \loop   
        \read\myfile to \mydata 
        \unless\ifeof\myfile                
        \section\mydata
        \lstinputlisting{"\mydata"}\newpage
    \repeat
    \closein\myfile
}
share|improve this answer
    
I forgot that the condition doesn't have to follow \loop directly. However, I disagree with your statement that my recursive suffers from stack build-up (which could lead to an overflow). I'm using \expandafter\readoneline\fi to not stack up conditionals. –  Martin Scharrer Aug 9 '11 at 9:50
    
I accepted this answer because I use it in my real scenario. –  xport Aug 10 '11 at 11:52
    
My answer told you to use \ifeof\myfile again and led you to your final solution. Accepting your own answer like that is not good manners. –  Martin Scharrer Aug 10 '11 at 11:55
    
Because of manner restriction, I return the green check mark to you. :-) –  xport Aug 10 '11 at 11:58
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.