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.

  • 5
    You do know that you are using \readline rather than \read, don't you? \readline is deliberately verbatim-like. – Joseph Wright May 25 '13 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 May 25 '13 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 May 25 '13 at 9:01
  • 4
    If you read each command and execute it, how do you want the behaviour to differ from just using \input ? – David Carlisle May 25 '13 at 10:10
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

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.