8

I have a file, that contains a list of latex commands each command per line. Now I want to read this file line per line and execute/expand the macros automatically. I tried the following but this only prints out the command instead of executing it.

\makeatletter
\newread\myread
\newcount\linecnt
\openin\myread=testfile.tex
\@whilesw\unless\ifeof\myread\fi{%
  \advance\linecnt by \@ne
  \readline\myread to \line
  \line
}
\makeatother

How can I fix this? I don't think that there is something like \forceexpand\line. How can I make this to ignore comments in testfile.tex?

Edit:

As Joseph Wright pointed out in a comment, I should use \read instead of \readline. This also ignores comments but it doesn't solve my comment problem completely. To illustrate this, here is my original motivation for this question:

I wanted to test multiple fonts in xelatex in different documents (which where put together via pdfpages in a later step, but this is too complicated and doesn't matter here). However for this situation I wanted to have a single file with the list of fonts I wanted to try, like this (testfile.tex):

\setmainfont{font1}
%\setmainfont{font2}
\setmainfont{font3}

Then I have a document file, something like this:

\documentclass{article}

\usepackage{fontspec}
\usepackage{xunicode}
\usepackage{xltxtra}

\newcommand{\testtext}{Some Text}

\begin{document}
    \makeatletter
    \newread\myread
    \newcount\linecnt
    \openin\myread=testfile.tex
    \@whilesw\unless\ifeof\myread\fi{%
      \advance\linecnt by \@ne
      \read\myread to \line
      \line
      \testtext
      \newline %\newpage
    }
    \makeatother
\end{document}

This should output the content of \testtext twice, one time with font1 and one time with font3, the commented entry with font2 should be ignored completely (instead of printing the text with font1 twice). So I should detect somehow in the loop if the line was a comment and don't execute \testtext and \newline in this case.

4
  • 5
    You do know that you are using \readline rather than \read, don't you? \readline is deliberately verbatim-like.
    – Joseph Wright
    Commented May 25, 2013 at 8:47
  • Thanks, that solves the problem. Since I want to print some text after \line it would be great to explicitely detect if the line in testfile.tex was a comment or not, is this possible?
    – student
    Commented May 25, 2013 at 8:51
  • 2
    The \read primitive applies normal category codes, so you will see nothing if the line is a comment. An alternative approach is to use \readline and \scantokens: what we need is a bit more context to see what you actually want to do. Could you edit in a small demo file and required output?
    – Joseph Wright
    Commented May 25, 2013 at 9:01
  • 4
    If you read each command and execute it, how do you want the behaviour to differ from just using \input ? Commented May 25, 2013 at 10:10

2 Answers 2

10

If the % comes first in the line you want to omit, just test whether the line just read is empty; setting \endlinechar to –1 while reading the file avoids the appended end of line that becomes a space or \par.

\begin{filecontents*}{\jobname.tst}
\fontspec{Linux Libertine O}
%\fontspec{Old Standard}
\fontspec{TeX Gyre Cursor}
\end{filecontents*}

\documentclass{article}
\usepackage[a4paper,margin=.5cm]{geometry}
\usepackage{fontspec}
\newcommand{\testtext}{Some Text \fontname\font}
\setlength{\parindent}{0pt}

\begin{document}

\makeatletter
\newread\myread
\newcount\linecnt
\begingroup\endlinechar=\m@ne
\openin\myread=\jobname.tst
\loop\unless\ifeof\myread
  \advance\linecnt by \@ne
  \read\myread to \line
  \ifx\line\@empty\else
    {(\number\linecnt) \line\testtext}%
    \par %\newpage
  \fi
\repeat
\endgroup
\makeatother
\end{document}

enter image description here

Using \loop...\repeat is easier than \@whilesw.

9

Also the deleted idea of David Carlisle with \input{testfile} works. The data does already contain TeX macro markup. All we need is to define the macro to do the job we want to do. The following modifies egreg's example:

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.tst}
\fontspec{DejaVu Sans}
\fontspec{Linux Libertine O}
%\fontspec{Old Standard}
\fontspec{TeX Gyre Cursor}
\end{filecontents*}

\documentclass{article}
\usepackage[a4paper,margin=.5cm]{geometry}
\usepackage{fontspec}
\newcommand{\testtext}{Some Text}
\setlength{\parindent}{0pt}

\begin{document}

\begingroup
  \let\OrgFontSpec\fontspec
  \renewcommand*{\fontspec}[2][]{%
    (\the\inputlineno) %
    \begingroup
      \OrgFontSpec[{#1}]{#2}%
      \testtext\ [#2] \fontname\font
    \endgroup
    \par
    % \newpage
  }%
  \input{\jobname.tst}%
\endgroup

\end{document}

Result

You must log in to answer this question.

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