
[ОТРЕДАКТИРОВАНО, чтобы показать, где я на самом деле хочу использовать необязательный аргумент]
На этот вопрос можно ответить по адресуКак передать необязательный аргумент в среду с дословным содержимым?, но мне трудно применить этот ответ к моей проблеме. Я удалю этот запрос, если он будет сочтен дублирующим.
Когда я использую среду, подобную дословной, которая принимает необязательный аргумент (vb в MWE ниже), то в случаях, когда необязательный аргумент не указан, первый токен в среде иногда выполняется за пределами среды.
\documentclass{article}
\usepackage{verbatim}
\parskip 1ex\parindent 0em
\makeatletter
\newenvironment{va}{%
\def\verbatim@processline{%
{\setbox0=\hbox{\the\verbatim@line}%
\hsize=\wd0 \the\verbatim@line\par}}%
\setbox0=\vbox\bgroup \verbatim
}
{%
\endverbatim
\unskip\setbox0=\lastbox %
\egroup
\usebox0
}
\newenvironment{vb}[1][]{%
\def\verbatim@processline{%
{\setbox0=\hbox{\the\verbatim@line}%
\hsize=\wd0 \the\verbatim@line\par}}%
\setbox0=\vbox\bgroup #1 \verbatim
}
{%
\endverbatim
\unskip\setbox0=\lastbox %
\egroup
\usebox0
}
\makeatother
\begin{document}
I created two environments based on \verb|boxedverbatim| environment.
Environment \verb|va| takes no arguments. Environment \verb|vb| is
identical but takes an optional argument (which is not actually used for
anything in this MWE). In all the following cases, no optional argument
is actually passed to the \verb|vb| environment
Starting either environment with a letter works:
\begin{va}I will set \def\x{1}\end{va}
\begin{vb}I will set \def\x{1}\end{vb}
But if I start the environments with a command like \verb|\Huge|, the
\verb|vb| environment executes that command outside the environment, even
though it was not in brackets:
\begin{va}\Huge I will set \def\x{1}\end{va}
\begin{vb}\Huge I will set \def\x{1}\end{vb}
If I start the verbatim with a \verb|\def|, the \verb|vb|
environment breaks
\begin{va}\def\x{1}\end{va}
%\begin{vb}\def\x{1}\end{vb}
\end{document}
решение1
Как и для всех команд verbatim, вам необходимо переключить режим catcode перед разбором аргументов. После того, как символ был токенизирован, значения catcode, установленные verbatim, не имеют никакого эффекта, поскольку catcodes не влияют на токены после их создания, они только определяют, как токены создаются из входного файла.
В
\begin{vb}\Huge
\vb
смотрит на следующийтокенчтобы увидеть, является ли он [
. TeX должен прочитать файл, чтобы сгенерировать следующий токен, поэтому считывает все \Huge
и создает токен cs, после чего любые настройки catcode влияют только на символы, считываемые из файла; они не влияют на Huge
.
Вам просто нужно выполнить анализ аргументов после настройки catcodes:
\newcommand\innervb[1][]{}
\newenvironment{vb}{%
\def\verbatim@processline{%
{\setbox0=\hbox{\the\verbatim@line}%
\hsize=\wd0 \the\verbatim@line\par}}%
\setbox0=\vbox\bgroup \verbatim\innervb
}
{%
\endverbatim
\unskip\setbox0=\lastbox %
\egroup
\usebox0
}