14

I need to write some inlined code on an external file, then load it with listings. I would like to define a new environment, but if I do, filecontents does not save the first line of code (see MWE):

\documentclass[]{article}
\usepackage{listings}
\usepackage{filecontents}

\newenvironment{MyNewEnvironment}[2]{%
  \def\temp{#1}%
  \csname filecontents*\endcsname{\temp}%
  #2%
}%
{\csname endfilecontents*\endcsname%
 \lstinputlisting{\temp}%
}%


\begin{document}

\begin{MyNewEnvironment}{foo.txt}%
one
two
three
four
five

\end{MyNewEnvironment}

\end{document}

The resulting foo.txt contains:

two
three
four
five
  • 2
    You can't use filecontents* like that; I suggest you to check fancyvrb that provides a way to write verbatim to another file. – egreg Aug 27 '13 at 9:34
  • 1
    @egreg i just skimmed the docs of the filecontents package, and i'm not sure what actually is wrong with flodd's use of the command. what is the rule that prevents such use? – wasteofspace Aug 27 '13 at 10:07
  • @wasteofspace Probably you're right, as karlkoeller's answers shows. However, I find VerbatimOut much more flexible. – egreg Aug 27 '13 at 10:12
  • 2
    What is the purpose of the second argument of environment MyNewEnvironment? It causes the trouble, because it is not read in the control of \filecontents* with its changed catcodes and line ends. Removing the second argument solves your problem as shown in karlkoeller's answer. – Heiko Oberdiek Aug 27 '13 at 10:12
  • I see... I guess I just have misunderstood how newenvironment works :) – FloDD Aug 27 '13 at 10:31
13

I suggest using fancyvrb and xparse, that allows also to pass options to \lstinputlisting:

\documentclass{article}
\usepackage{fancyvrb,xparse,listings}

\NewDocumentEnvironment{MyNewEnvironment}{O{}m}
  {\VerbatimOut{#2}}
  {\endVerbatimOut\lstinputlisting[#1]{#2}}

\begin{document}

\begin{MyNewEnvironment}[columns=fullflexible]{foo.txt}
one
two
three
four
five

\end{MyNewEnvironment}

\end{document}
  • What does O{}m denote? I cannot find an explanation in xparse.pdf. – koppor Mar 7 '18 at 14:53
  • @koppor It denotes an optional argument with empty default value and a mandatory argument. – egreg Mar 7 '18 at 16:31
13

Probably it's not the right way to use filecontents*, as egreg says in his comment.

Anyway, changing your MWE to

\documentclass[]{article}
\usepackage{listings}
\usepackage{filecontents}

\newenvironment{MyNewEnvironment}[1]{%
  \def\temp{#1}%
  \csname filecontents*\endcsname{\temp}%
}%
{\csname endfilecontents*\endcsname%
 \lstinputlisting{\temp}%
}%


\begin{document}

\begin{MyNewEnvironment}{foo.txt}
one
two
three
four
five
\end{MyNewEnvironment}

\end{document} 

works fine for me.

  • +1 This solution seems very good ... despite the comments of egreg. ;-) – Paul Gaborit Jan 1 '14 at 23:06

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.