`\iftoggle` 中跳过的行会给出错误:段落结束且 } 太多

`\iftoggle` 中跳过的行会给出错误:段落结束且 } 太多

我正在尝试创建一个新命令,该命令根据切换(带有特定的计数器 - 它基本上用于输出考试的问题和答案)输出第一个或第二个参数。

但是,如果答案或问题中有空行,则命令失败并出现错误:

Runaway argument? {
Paragraph ended before \QR was complete.
Too many }'s. }

MWE 是:

\documentclass{article}
\usepackage{xparse}
\usepackage{enumitem}
\usepackage{etoolbox}
\usepackage{listings}

% Make toggle for teacher and student version of file
\newtoggle{corrige}
\togglefalse{corrige}
\newcommand{\cswitch}[2]{
    \iftoggle{corrige}{%
        #1%
    }{%
        #2%
    }%
}

% Make a fancy QR command
\newcounter{qrIndex} % compteur pour les questions
\newcounter{qrIndexSaved}
\newcommand{\save}{\setcounter{qrIndexSaved}{\theqrIndex}}
\newcommand{\retrieve}{\setcounter{qrIndex}{\theqrIndexSaved}}
\newcommand{\resetQ}{\setcounter{qrIndex}{1}}

\NewDocumentCommand{\QR}{mm}{%
    \begin{enumerate}[start=\theqrIndex]
      \stepcounter{qrIndex}
        \cswitch{\item #2}{\item #1}%
    \end{enumerate}%
}

\begin{document}

\toggletrue{corrige}

Test switch corrige~: \cswitch{corrige}{enonce}

\bigbreak

Test QR~:

\resetQ
\QR{Q1}{A1}

\QR{
    Q2
  }{
    This has no empty line in either the question or answer.
    \smallbreak
    It works well.
}

\QR{
    Q3
}{

    This \textbf{has} an empty line.
    You'd think it works.
    But error:
    \begin{verbatim}
        Runaway argument? {
        Paragraph ended before \QR was complete.
        Too many }'s. }
    \end{verbatim}
    It only shows the last part of answer, skipping anything before, and messes
    up the enumerate etc, even without the \texttt{toggletrue\{corrige\}}!
}

\end{document}

我的猜测是它来自命令和/或中的\iftoggle第二个参数的扩展,但我在网上没有找到类似的案例。xparseNewDocumentCommand

感谢您的帮助!

答案1

TeX 区分长宏(由 声明\long\def),其参数接受空行,以及短宏(由 声明\def)。由于历史原因,LaTeX 宏默认\newcommand创建宏,而您需要带星号的形式来创建短宏。另一方面,来自 的参数默认也是短的,您需要使用说明符来允许宏参数中有空行。\long\newcommand*mxparse+m

还要注意,计数器值应通过\value{counter}而不是传递\thecounter。在这种情况下你很幸运,因为\thecounter默认为阿拉伯语表示,但你不应该依赖它。

最后但同样重要的一点是,verbatim环境从未作为其他宏的参数。

现在轮到你可以修复这些问题并使其正常工作:

\documentclass{article}
\usepackage{enumitem}
\usepackage{etoolbox}

% Make toggle for teacher and student version of file
\newtoggle{corrige}
\togglefalse{corrige}
\newcommand{\cswitch}[2]{%
    \iftoggle{corrige}{%
        #1%
    }{%
        #2%
    }%
}

% Make a fancy QR command
\newcounter{qrIndex} % compteur pour les questions
\newcounter{qrIndexSaved}
\newcommand{\save}{\setcounter{qrIndexSaved}{\value{qrIndex}}}
\newcommand{\retrieve}{\setcounter{qrIndex}{\value{qrIndexSaved}}}
\newcommand{\resetQ}{\setcounter{qrIndex}{1}}

\NewDocumentCommand{\QR}{+m+m}{% or simply \newcommand{\QR}[2]
    \begin{enumerate}[start=\value{qrIndex}]
      \stepcounter{qrIndex}
        \cswitch{\item #2}{\item #1}%
    \end{enumerate}%
}

\begin{document}

\toggletrue{corrige}

Test switch corrige~: \cswitch{corrige}{enonce}

\bigbreak

Test QR~:

\resetQ
\QR{Q1}{A1}

\QR{
    Q2
  }{
    This has no empty line in either the question or answer.
    \smallbreak
    It works well.
}

\QR{
    Q3
}{

    This \textbf{has} an empty line, and it works.
}

\end{document}

但是,既然你正在使用enumitem,为什么不利用它的功能呢?你可以定义一个自动恢复的新列表:

\documentclass{article}
\usepackage{enumitem}
\usepackage{etoolbox}

% Make toggle for teacher and student version of file
\newtoggle{corrige}
\togglefalse{corrige}
\newcommand{\cswitch}[2]{\iftoggle{corrige}{#1}{#2}}

% Make a fancy QR command
\newlist{mylist}{enumerate}{1}
\setlist[mylist]{resume,label=\arabic{mylisti}.}
\newcommand{\resetQ}{\restartlist{mylist}}

\NewDocumentCommand{\QR}{+m+m}{%
   \begin{mylist}
      \item\cswitch{#2}{#1}%
   \end{mylist}%
}

\begin{document}

\toggletrue{corrige}
\QR{Q1}{A1}
\QR{Q2}{A2}
\QR{Q3}{A3}

\togglefalse{corrige}
\resetQ
\QR{QQ1}{AA1}
\QR{QQ2}{AA2}
\QR{QQ3}{AA3}

\end{document}

在此处输入图片描述

相关内容