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.

This is a follow-up to How to ignore everything in the document environment?.

The code below is intended to extract the value of a token that occurs before \begin{document}. For some reason, there is a problem with the \DisablePreamble macro that I can not figure out. Surprisingly, it seems to have been working in my actual use case, but not when I try to make a MWE (in an attempt to reproduce another problem).

File goo.tex is an extremely simplified test case as it does not have any preamble so it doesn't need to invoke \DisablePreamble -- and this works. But, in my real use case (as in foo.tex), there is a preamble and a complete document environment that needs to be ignored, and hence the need for \DisablePreamble.

The example below produces:

MyToken=goobar

MyToken=goobar

as the \ExtractMyTokenA line is commented, but with \ExtractMyTokenA uncommented it should yield (note change in second line):

MyToken=goobar

MyToken=foobar

When the call to \ExtractMyTokenA is uncommented, this yields:

./TeX-SE.tex:75: LaTeX Error: Command \env already defined.
            Or name \end... illegal, see p.192 of the manual.

References:

Notes:

  • To get the given MWE to failure you need to uncomment the \ExtractMyTokenA line.
  • The actual problem is in \DisablePreamble, but this MWE seems more complicated than it really is as:
    1. I have two temp files foo.tex and goo.tex as test cases.
    2. The macros \ExtractMyTokenA and \ExtractMyTokenA are pretty much identical: Once calls \DisablePreamble and the other does not.

Code:

\documentclass{article}
\usepackage{environ}

%  This file is ONLY needed once we get past the error message.
%\usepackage{filecontents}% Comment out so as to NOT overwrite foo.tex and goo.tex.
\begin{filecontents*}{foo.tex}
    \documentclass{standalone}
    \usepackage{MyStandardPackages}
    \input{MyStandardSetup}

    \MyToken={foobar}%   <----- Only this line should be executed. ALL other lines in foo.tex are to be ignored.

    \begin{document}
       lots of text here

       \SetSomeVarable{\SomeVar}{Some Value}

       \begin{SomeEnvironment}
           lots more stuff here as well
       \end{SomeEnvironment}
    \end{document}
\end{filecontents*}

% This file does not have a preamble so won't need a call to "\DisablePreamble"
\begin{filecontents*}{goo.tex}
    \MyToken={goobar}%   <----- Only this line should be executed. ALL other lines in foo.tex are to be ignored.
\end{filecontents*}

%% ------------------------------
%% Problem is in here somewhere!!  Shows up once we uncomment "\ExtractMyToken{foo}" below.
\newcommand{\DisablePreamble}{%
        \renewcommand{\documentclass}[2][]{}%  remove def'n of \documentclass
        %% http://tex.stackexchange.com/questions/165258/how-to-ignore-everything-in-the-document-environment
        \providecommand{\env@document@save@env}{}% To keep environ happy
        \providecommand{\env@document@process}{}%
        \RenewEnviron{document}{}% Ignore everything within the "document" environment.
        \renewcommand{\usepackage}[2][]{}% 
}%

\newtoks{\MyToken}
\newcommand{\FileWithPath}{}%
\newcommand{\ExtractMyTokenA}[1]{% Same as \ExtractMyTokenB, except invokes "\DisablePreamble" 
    % #1 = File Name with path
    \begingroup%
        \DisablePreamble%
        % -----------
        \let\OldInput\input%         Need to redefine \input as the file being read uses
        \renewcommand*{\input}[1]{}% \input before \begin{document}.
        % -----------
        \edef\FileWithPath{#1}%
        \OldInput{\FileWithPath}%
        \global\MyToken=\expandafter{\the\MyToken}
    \endgroup%
}%

\newcommand{\ExtractMyTokenB}[1]{% Same as \ExtractMyTokenA, except "\DisablePreamble" is commented.
    % #1 = File Name with path
    \begingroup%
        %\DisablePreamble% This works great for the case where there is no preamble.
        % -----------
        \let\OldInput\input%         Need to redefine \input as the file being read uses
        \renewcommand*{\input}[1]{}% \input before \begin{document}.
        % -----------
        \edef\FileWithPath{#1}%
        \OldInput{\FileWithPath}%
        \global\MyToken=\expandafter{\the\MyToken}
    \endgroup%
}%


\begin{document}
    \ExtractMyTokenB{goo}%  <----- This does not invoke \DisablePreamble, and works 
    MyToken=\the\MyToken\par
    % ------------
    %\ExtractMyTokenA{foo}%   <----- This invokes \DisablePreamble, which fails 
    MyToken=\the\MyToken\par
\end{document}
share|improve this question
1  
Related: No \makeatletter required? –  Werner Apr 27 at 5:22

1 Answer 1

up vote 5 down vote accepted
 \providecommand{\env@document@save@env}{}% To keep environ happy

It would make it happier if that defined \env@document@save@env rather than \env :-)

\documentclass{article}
\usepackage{environ}

%  This file is ONLY needed once we get past the error message.
%\usepackage{filecontents}% Comment out so as to NOT overwrite foo.tex and goo.tex.
\begin{filecontents*}{foo.tex}
    \documentclass{standalone}
    \usepackage{MyStandardPackages}
    \input{MyStandardSetup}

    \MyToken={foobar}%   <----- Only this line should be executed. ALL other lines in foo.tex are to be ignored.

    \begin{document}
       lots of text here

       \SetSomeVarable{\SomeVar}{Some Value}

       \begin{SomeEnvironment}
           lots more stuff here as well
       \end{SomeEnvironment}
    \end{document}
\end{filecontents*}

% This file does not have a preamble so won't need a call to "\DisablePreamble"
\begin{filecontents*}{goo.tex}
    \MyToken={goobar}%   <----- Only this line should be executed. ALL other lines in foo.tex are to be ignored.
\end{filecontents*}

%% ------------------------------
%% Problem is in here somewhere!!  Shows up once we uncomment "\ExtractMyToken{foo}" below.
\makeatletter% <---- This was missing!!!!!
\newcommand{\DisablePreamble}{%
        \renewcommand{\documentclass}[2][]{}%  remove def'n of \documentclass
        %% http://tex.stackexchange.com/questions/165258/how-to-ignore-everything-in-the-document-environment
        \providecommand{\env@document@save@env}{}% To keep environ happy
        \providecommand{\env@document@process}{}%
        \RenewEnviron{document}{\endgroup\begingroup}% Ignore everything within the "document" environment.
        \renewcommand{\usepackage}[2][]{}% 
}%
\makeatother

\newtoks{\MyToken}
\newcommand{\FileWithPath}{}%
\newcommand{\ExtractMyTokenA}[1]{% Same as \ExtractMyTokenB, except invokes "\DisablePreamble" 
    % #1 = File Name with path
    \begingroup%
        \DisablePreamble%
        % -----------
        \let\OldInput\input%         Need to redefine \input as the file being read uses
        \renewcommand*{\input}[1]{}% \input before \begin{document}.
        % -----------
        \edef\FileWithPath{#1}%
        \OldInput{\FileWithPath}%
        \global\MyToken=\expandafter{\the\MyToken}
    \endgroup%
}%

\newcommand{\ExtractMyTokenB}[1]{% Same as \ExtractMyTokenA, except "\DisablePreamble" is commented.
    % #1 = File Name with path
    \begingroup%
        %\DisablePreamble% This works great for the case where there is no preamble.
        % -----------
        \let\OldInput\input%         Need to redefine \input as the file being read uses
        \renewcommand*{\input}[1]{}% \input before \begin{document}.
        % -----------
        \edef\FileWithPath{#1}%
        \OldInput{\FileWithPath}%
        \global\MyToken=\expandafter{\the\MyToken}
    \endgroup%
}%


\begin{document}
    \ExtractMyTokenB{goo}%  <----- This does not invoke \DisablePreamble, and works 
    MyToken=\the\MyToken\par
    % ------------
    \ExtractMyTokenA{foo}%   <----- This invokes \DisablePreamble, which fails 
    MyToken=\the\MyToken\par
\end{document}
share|improve this answer
    
So basically I forgot the \makeatletter...\makeatother.. I had a feeling this was probably going to be embarrassing, but didn't think it was that obvious!!!! Thanks again David. –  Peter Grill Apr 27 at 2:08

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.