使用活动字符延迟扩展 StrSubstitute 参数

使用活动字符延迟扩展 StrSubstitute 参数

这是我的延伸上一个问题。接受的答案为我提供了一种延迟扩展标记easylist列表的方法,直到字符串在环境内处理完毕。我正试图将代码调整到允许方便格式化多项选择题的环境中。MWE 如下(使用 LuaLaTeX 编译):

\documentclass[11pt]{memoir}

\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage{xstring}
\usepackage{easylist}
\usepackage{ifthen}

\newenvironment{question}{
    \newcommand{\choicestext}{}
    \newcommand{\choice}[1]{
        \edef\oldchoicestext{\choicestext}
        \edef\newchoicetext{##1}
        % just append
        \renewcommand{\choicestext}{\oldchoicestext CHOICE\newchoicetext}
    }
}{
    \edef\finchoicestext{\choicestext}
    %wow http://goo.gl/jHcwNY thank you egreg
    \begingroup\catcode`§=\active
    \noexpandarg
    \expandafter\StrSubstitute\expandafter{\finchoicestext}{CHOICE}{ § }[\tempctext]

    \begin{easylist}
        \tempctext
    \end{easylist}
    \endgroup
}

\begin{document}
\begin{question}
    \choice{First choice}
    \choice{Second choice}
\end{question}
\end{document}

choice命令负责将用户给出的选择编译到\choicestext由 分隔的变量中CHOICE,然后我想将其转换为easylist格式。我借用了上一个答案中的代码,通过将活动部分字符替换为 来格式化它CHOICE,但这似乎在我的环境中不起作用。我如何在环境中保留标记然后格式化的行为question

如果我最近的问题听起来类似,我很抱歉。我仍在努力解决 TeX 之\expandafter类的问题。

答案1

正如 egreg 的回答中所说,你需要在进行定义之前让角色处于活动状态。

这运行时没有错误,我不确定这是否是您想要的输出?

\documentclass[11pt]{memoir}

\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage{xstring}
\usepackage{easylist}
\usepackage{ifthen}
\catcode`§=\active

\newenvironment{question}{
    \newcommand{\choicestext}{}
    \newcommand{\choice}[1]{
        \edef\oldchoicestext{\choicestext}
        \edef\newchoicetext{##1}
        % just append
        \renewcommand{\choicestext}{\oldchoicestext CHOICE\newchoicetext}
    }
}{
    \edef\finchoicestext{\choicestext}
    %wow http://goo.gl/jHcwNY thank you egreg
    \noexpandarg
    \expandafter\StrSubstitute\expandafter{\finchoicestext}{CHOICE}{ § }[\tempctext]

    \begin{easylist}
        \tempctext
    \end{easylist}
}
\catcode`\§=12

\begin{document}
\begin{question}
    \choice{First choice}
    \choice{Second choice}
\end{question}
\end{document}

该宏似乎在做同样的事情

\documentclass[11pt]{memoir}

\usepackage{fontspec}



\newenvironment{question}{%
    \begin{enumerate}
        \let\choice\item}{%
    \end{enumerate}
}


\begin{document}
\begin{question}
    \choice{First choice}
    \choice{Second choice}
\end{question}
\end{document}

或者如果您想连接一个字符串easylist

\documentclass[11pt]{memoir}

\usepackage{fontspec}
\usepackage{easylist}
\catcode`§=\active
\makeatletter
\newenvironment{question}{%
    \newcommand{\choicestext}{}%
    \newcommand{\choice}[1]{%
        \g@addto@macro\choicestext{ § ##1}%
    }
}{%
    \begin{easylist}%
        \choicestext
    \end{easylist}%
}
\catcode`\§=12
\makeatother

\begin{document}
\begin{question}
    \choice{First choice}
    \choice{Second choice}
\end{question}
\end{document}

答案2

\choice你忘记了 TeX 使用宏扩展!而且你已经有了可以以任何你想要的方式定义的宏!

因此我们可以定义在问题文本前面\choice提供标记;唯一的预防措施是将标记变成活动字符:easylist

\documentclass[11pt]{memoir}

\usepackage{fontspec}
\usepackage{easylist}

\begingroup\lccode`~=`§
\lowercase{\endgroup\def\easylistmarker{~ }}
\newcommand{\choice}[1]{\easylistmarker#1} 

\newenvironment{question}  
  {\begin{easylist}}
  {\end{easylist}}

\begin{document}

\begin{question}
    \choice{First choice}
    \choice{Second choice}
\end{question}

\end{document}

在此处输入图片描述

如果您想通过替换走很长的路(但不清楚为什么),您可以使用类似的方法:使用宏替换!

\documentclass[11pt]{memoir}

\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage{xstring}
\usepackage{easylist}
\usepackage{ifthen}

\begingroup\catcode`§=\active
\gdef\dosubstitutions{%
  \noexpandarg
  \expandafter\StrSubstitute\expandafter{\finchoicestext}{CHOICE}{ § }[\tempctext]%
}
\endgroup

\newenvironment{question}{%
    \newcommand{\choicestext}{}%
    \newcommand{\choice}[1]{%
        \edef\oldchoicestext{\choicestext}
        \edef\newchoicetext{##1}
        % just append
        \renewcommand{\choicestext}{\oldchoicestext CHOICE\newchoicetext}
    }%
}{
    \edef\finchoicestext{\choicestext}%
    %wow http://goo.gl/jHcwNY thank you egreg
    \dosubstitutions
    \begin{easylist}
        \tempctext
    \end{easylist}
}

\begin{document}
\begin{question}
    \choice{First choice}
    \choice{Second choice}
\end{question}
\end{document}

问题是,一旦一个标记被 TeX 扫描到,它的类别代码就固定了,所以你不能在\catcode`§=\active的定义内部使用该技巧question,而是在其外部使用宏将其放入。

然而使用\edef似乎不是最好的方法。最好防止扩展太深:

\documentclass[11pt]{memoir}

\usepackage{fontspec}
\usepackage{xstring}
\usepackage{easylist}
\usepackage{etoolbox}

\begingroup\lccode`~=`§
\lowercase{\endgroup\def\easylistmarker{~ }}

\newenvironment{question}
 {%
  \def\choicestext{}% initialize
  \def\choice##1{%
    \xappto\choicestext{\expandonce{\easylistmarker} \unexpanded{##1}}%
  }%
 }
 {%
  \begin{easylist}
  \choicestext
  \end{easylist}
 }

\begin{document}
\begin{question}
    \choice{First choice}
    \choice{Second choice}
\end{question}
\end{document}

相关内容