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.

Sorry for the long next code but if I modify a part of the code, another problem appears in another part. The idea is to use an environment to catch an example, then I display the code of the example, then I execute this code and finally I save the code of the example in a file (here named examplefile.tex)

I have two problems :

1) Instead of CR, I get ^^M in the examplefile.tex. I suppose that I made something wrong with some catcodes in the macro \CatchTokensDef

2) I have a minor problem with the comments in the source code of the example. I have lost them.

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{environ}

\makeatletter
\newwrite\example
\newtoks \TokenExample

\def\ExamplePreamble%                    add at the beginning
{%
    \input{preamble.ltx}^^J%
    \begin{document}%
}% 

\def\ExamplePostamble%                   add at the end
{%
    \end{document}%
}% 

\def\ExportExample#1{%                    create the file
    \immediate\openout\example=#1 %
    {%
       \toks@\expandafter{\ExamplePreamble^^J}%
       \toks@\expandafter{\the\expandafter\toks@
                          \the\@temptokena^^J}%
       \toks@\expandafter{\the\expandafter\toks@
                          \ExamplePostamble}%
       \immediate\write\example{\the\toks@}%
    }%
    \immediate\closeout\example
}% 

\def\PrintExample{% display the code
    \begin{minipage}[t]{12cm}
       \@vobeyspaces
       \the\@temptokena
    \end{minipage}
}

\def\ExecExample{\the\@temptokena}%

\def\CatchTokensDef#1{%
                                                  % instead of \input
                                                  % #1 = setup (catcodes)    %
                                                  % original content in \TokenExample
                                                  % result in \@temptokena
    \begingroup \endlinechar-1 %
       \everyeof{\CatchToken@EOF
                 \expandafter \endgroup
                 \noexpand}%
       \long\def\CatchToken@Do ##1\CatchToken@EOF{%
          \global\@temptokena{##1}%
       }%
       #1\expandafter\CatchToken@Do
     \scantokens\expandafter{\the\TokenExample}\relax
}%

% catch the content with \Collect@Body from environ.sty

\newenvironment{exemple}%                               this is the main environment
    {\begingroup 
     \obeylines
     \obeyspaces 
     \Collect@Body 
     \StoreInToken 
     }
    {\endgroup 
     \process@example
     }
\long\def\StoreInToken #1{\global\TokenExample{#1}}

\begin{document}

\def\process@example{%                                first we catch some tokens
    \CatchTokensDef {\let\do 
                     \@makeother 
                     \dospecials
                     \obeylines 
                     \@vobeyspaces}%
    \PrintExample%                                    display the code of the exammple
    \ExportExample{examplefile.tex}%                  export the example in a file
    \CatchTokensDef {\catcode`\^^M=9\relax}
 % the problem is resolved if I put the last line 
 % before \ExportExample{examplefile.tex}

    \ExecExample%                                     execute the example
}%

\begin{exemple}
\begin{tikzpicture}
%                                                      main code
\filldraw[black,fill=green!15]
          (0,0) rectangle (5,1)
  node [midway] {I say goodbye, you say hello !};%     Beatles

\end{tikzpicture}
\end{exemple}

\end{document} 

The result :

enter image description here

As you can see, I have lost the comments and the blank lines

But I get ^^M in the examplefile.tex

\input {preamble.ltx}
\begin {document}
^^M\begin {tikzpicture}^^M\filldraw [black,fill=green!15]^^M          (0,0) rectangle (5,1)^^M  node [midway] {I say goodbye, you say hello !}; ^^M\end {tikzpicture}^^M
\end {document}
share|improve this question
    
I get also space after the macros in the source code. –  Alain Matthes Dec 30 '11 at 16:07
1  
Setting \newlinechar=\endlinechar would help with examplefile.tex. \newlinechar states which characters should be turned into a new line in output files. Normally it is set to ^^J, but you need it as ^^M (which is the default of \endlinechar). –  Martin Scharrer Dec 30 '11 at 16:27
    
Note that using \Collect@Body from environ is IMHO the wrong way to get verbatim code. As you see you loose the comments and get a space after every control words. You need to read the text verbatim, write it to a file and read it back twice for both applications, or use \scantokens to turn it back to code. I'm doing something like this in my ydoc bundle. I might want to have a look at that code as well. –  Martin Scharrer Dec 30 '11 at 16:30
1  
You lose the comments because TeX interprets the % character as it is parsing the definitions; they don't even make it into your example macros. Note that the ones that are placed after, say, \def\ExamplePreamble% comments would not be comments in the expansion of the macros anyway, since they come before the braces. Instead, if % were interpreted literally, they would become mandatory prefixes that you'd have to write to use the macros. Anyway, to catch comments at all you'd need to change the catcodes before TeX sees them. –  Ryan Reich Dec 30 '11 at 16:37
    
Finally I found the problem with ^^M. I need only to execute ` \CatchTokensDef {\catcode`\^^M=9\relax}%` before ` \ExportExample{examplefile.tex}. The real good question was about the comments. I agree with Martin, \Collect@Body`seems to be the problem. –  Alain Matthes Dec 30 '11 at 17:42
show 1 more comment

1 Answer

I wouldn't reinvent the wheel: fancyvrb has already the infrastructure needed; it's sufficient to adapt its VerbatimOut file to your needs.

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{fancyvrb,etoolbox,standalone}

\makeatletter
\def\exemple{\FV@Environment{}{exemple}}
\DefineVerbatimEnvironment{exemple}{exemple}{} 
\let\FVB@exemple\FVB@VerbatimOut
\patchcmd{\FVB@exemple}
  {\@bsphack}
  {\def\FV@exemple@file{#1}\@bsphack}
  {}{\ddt}
\patchcmd{\FVB@exemple}
  {\FV@Scan}
  {\immediate\write\FV@OutFile{\string\input{preamble.ltx}}%
   \immediate\write\FV@OutFile{\string\begin{document}}%
   \FV@Scan}
  {}{\ddt}
\def\FVE@exemple{\immediate\write\FV@OutFile{\string\end{document}}%
  \immediate\closeout\FV@OutFile\endgroup\@esphack
  \VerbatimInput{\FV@exemple@file}\input{\FV@exemple@file}%
}
\makeatother


\begin{document}

\begin{exemple}{exemplefile.tex}
\begin{tikzpicture}
%                                                      main code
\filldraw[black,fill=green!15]
          (0,0) rectangle (5,1)
  node [midway] {I say goodbye, you say hello !};%     Beatles

\end{tikzpicture}
\end{exemple}

\end{document} 

With this code you have to provide a file name, but it's easy to avoid it and use a unique name: instead of the \let line and the two \patchcmd, just define \FVB@exemple copying the definition in fancyvrb.sty and doing the necessary adaptations.

\makeatletter
\def\exemple{\FV@Environment{}{exemple}}
\DefineVerbatimEnvironment{exemple}{exemple}{}
\def\FVB@exemple{%
  \@bsphack
  \begingroup
    \FV@UseKeyValues   
    \FV@DefineWhiteSpace
    \def\FV@Space{\space}%
    \FV@DefineTabOut
    \def\FV@ProcessLine{\immediate\write\FV@OutFile}%
    \immediate\openout\FV@OutFile=exemplefile.tex\relax
    \let\FV@FontScanPrep\relax
    \let\@noligs\relax
    \immediate\write\FV@OutFile{\string\input{preamble.ltx}}%
    \immediate\write\FV@OutFile{\string\begin{document}}%
    \FV@Scan}
\def\FVE@exemple{\immediate\write\FV@OutFile{\string\end{document}}%
  \immediate\closeout\FV@OutFile\endgroup\@esphack
  \VerbatimInput{exemplefile}\input{exemplefile}%
}
\makeatother
share|improve this answer
    
I agree with you that it's possible to find another way but actually I want to understand the different problems of my code. After I can make a choice if I'm sure that I was on a wrong way. –  Alain Matthes Dec 30 '11 at 17:32
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.