这是我的延伸上一个问题。接受的答案为我提供了一种延迟扩展标记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}