下面的代码旨在提取发生的标记的值前 \begin{document}
。出于某种原因,宏存在一个\DisablePreamble
我无法弄清楚的问题。令人惊讶的是,它似乎在我的实际使用案例中一直有效,但当我尝试进行 MWE(试图重现另一个问题)时却不起作用。
Filegoo.tex
是一个极其简化的测试用例,因为它没有任何前导码,所以不需要调用\DisablePreamble
——而且这是有效的。但是,在我的实际用例中(如foo.tex
),有一个前导码和一个document
需要忽略的完整环境,因此需要\DisablePreamble
。
下面的例子产生:
MyToken=goobar
MyToken=goobar
因为该\ExtractMyTokenA
行被注释掉了,但是\ExtractMyTokenA
注释掉了应该收益率(注意第二行的变化):
MyToken=goobar
MyToken=foobar
当对 的调用\ExtractMyTokenA
取消注释时,结果如下:
./TeX-SE.tex:75: LaTeX Error: Command \env already defined. Or name \end... illegal, see p.192 of the manual.
参考:
笔记:
- 要使给定的 MWE 失败,您需要取消注释该
\ExtractMyTokenA
行。 - 实际问题在于
\DisablePreamble
,但这个 MWE 看起来比实际情况更复杂,因为:- 我有两个临时文件
foo.tex
和goo.tex
测试用例。 - 宏
\ExtractMyTokenA
和\ExtractMyTokenA
几乎完全相同:一次调用\DisablePreamble
,另一个不调用。
- 我有两个临时文件
代码:
\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
\providecommand{\env@document@save@env}{}% To keep environ happy
\env@document@save@env
如果这样定义的话会更开心\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}