2

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
        %% https://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}
1

1 Answer 1

5
 \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}
1
  • 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. Apr 27, 2014 at 2:08

You must log in to answer this question.

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