不使用可选参数会导致环境中断

不使用可选参数会导致环境中断

我正在定义一个包装环境,filecontents以便我可以修改它的行为。

大多数测试用例都运行良好。例如,我定义了一个环境testenv,它接受一个强制参数并将其值写入控制台:

\newenvironment{testenv}[1]{%
  \typeout{Argument = #1}%
  \filec@ntents{\jobname.pfc}%
}{}

所以当我打电话时

\begin{testenv}{hello}
  hi
\end{testenv}

LaTeX 打印Argument = hello到控制台并写入一个名为的文件\jobname.pfc,其中包含

hi

这适用于无参数环境和强制参数环境。对于带有可选参数的环境,只要可选参数存在,它就会起作用,否则会失败。

下面的代码说明了所有的情况。最后一个会抛出一个Missing \begin{document}错误:

\documentclass{book}

\usepackage{filecontents}
\makeatletter

\newenvironment{testenv}{%
  \filec@ntents{\jobname.pfc}%
}{}
% The environment works without arguments
\begin{testenv}
  hi
\end{testenv}

\renewenvironment{testenv}[1]{%
  \typeout{Argument = #1}%
  \filec@ntents{\jobname.pfc}%
}{}
% and with mandatory arguments
\begin{testenv}{hello}
  hi
\end{testenv}

\renewenvironment{testenv}[1][abcde]{%
  \typeout{Argument = #1}%
  \filec@ntents{\jobname.pfc}%
}{}
% and it works with optional arguments
% only if the argument is given
\begin{testenv}[hello]
  hi
\end{testenv}

% otherwise it fails :/
\begin{testenv}
  hi
\end{testenv}

\begin{document}
\end{document}

该参数的实际用途是在环境内容之后排版一些文本,因此 catcode 并不那么重要。

答案1

在您的环境处理任何参数之前,请确保文件内容环境使用的 catcode-régime 有效。

在 filecontents-catcode-régime 下可以处理可选参数,因为应用该régime 不会改变 的 catcode [

根据您希望在实际应用程序中对可选参数执行的操作,您可能需要在正常的 catcode 机制下对其进行重新标记。
(对于简单来说,\typeout这不是必需的。)

\scantokens这可以通过 eTeX 扩展来完成。

如果 eTeX 扩展不可用,则可以通过将其未扩展写入临时文件并通过\input(TeX) / \@@input(LaTeX2e) 使 (La)TeX 读取/标记该临时文件来完成。

\documentclass{book}
\usepackage{filecontents}
\makeatletter
\newcommand\setcatcodesoffilecontents{%
  \let\do\@makeother\dospecials
  %
  \count0=128\relax
  \loop %
    \catcode\count0=11\relax
    \advance\count0 by 1\relax
  \ifnum\count0<256 %
  \repeat 
  %
  \catcode`\^^L\active
  \catcode`\^^I\active
  \catcode`\^^M\active
}%
\newenvironment{testenv}{%
  \begingroup
  \setcatcodesoffilecontents
  \innertestenv
}{}%
\newcommand\innertestenv[1][abcde]{%
  \endgroup
  \typeout{Argument = #1}%
  \@tempswatrue   %<-As file-preamble write the phrase
                  %   %% LaTeX2e file `\jobname.pfc'
                  %   %% generated by the `testenv' environment
                  %   %% from source `test' on 2018/06/30.
  %\@tempswafalse  %<-Don't write a file-preamble.
  \filec@ntents{\jobname.pfc}%
}%


% With optional argument:
%
%\begin{testenv}[hello]
%  hi
%\end{testenv}

% Without optional argument:
%
\begin{testenv}
  hi
\end{testenv}

\begin{document}
\end{document}

答案2

使用或类似方法收集材料时filecontents会使用逐字方法。这意味着任何标记化都可能(并且会)导致问题。您看到的问题是,当查找可选的 时[,TeX 会标记直到 为止(包括) h。具体来说,这意味着行尾已“消失”。收集标记依赖于抓取到行尾(^^M),因此我们在这里“丢失”h了 ,\everypar从而触发错误。

在 中也出现了类似情况beamer,即采取额外步骤来“确保”行开始后的第一个标记的安全。但是,这充其量也有些脆弱,我不会依赖它。

相关内容