MWE 下面的程序使用exsheets
包打印书末问题的答案。代码无法正常工作,因为它似乎是一个扩展问题。当\SetQuestionProperties{section-title= \secName }
我将 \secName 变量放在One
第一部分和Two
第二部分中时,而不是 ,一切都正常(即,将前几次出现的“\secName”替换为“One”,将接下来几次出现的“\secName”替换为“Two”)。
有人知道如何使此代码正常工作,以便正确地将 \secName 变量的字符串值传递给 \SetQuestionProperties 吗?
当前结果是“第 节 答案 1). foo 2). bar 第 节 答案 1). baz 2). foobar”,它应该是Section One 1). foo 2). bar Section Two 1). baz 2). foobar
。
\documentclass{scrartcl}
\usepackage{exsheets}
\setlength{\parindent}{0pt}
\SetupExSheets{counter-within=section}
\DeclareQuestionProperty{section-title}
\SetupExSheets{counter-within=section ,
headings=inline-nr ,
counter-format=qu).}
\SetupExSheets{section-hook = \noindent\bfseries
Section \GetQuestionProperty{section-title}{\CurrentQuestionID}
\space}
\newcommand{\secName}{}
\newcommand{\lsection}[1]
{
\renewcommand{\secName}{#1}
\section{#1}
}
\begin{document}
\lsection{One}
\begin{question}
\SetQuestionProperties{section-title= \secName }
say foo
\end{question}
\begin{solution}
foo
\end{solution}
\begin{question}
\SetQuestionProperties{section-title= \secName }
say bar
\end{question}
\begin{solution}
bar
\end{solution}
\lsection{Two}
\begin{question}
\SetQuestionProperties{section-title= \secName }
say baz
\end{question}
\begin{solution}
baz
\end{solution}
\begin{question}
\SetQuestionProperties{section-title= \secName }
say foobar
\end{question}
\begin{solution}
foobar
\end{solution}
\lsection{Answers}
\printsolutions
\end{document}
答案1
确实在\SetQuestionProperties{ section-title = \secName }
宏中\secName
需要扩展一次。否则问题属性章节标题设置为令牌,\secName
它仅在\printsolutions
其当前定义的位置使用时才会扩展Answers
(这是您在示例中看到的)。
扩展 token 的常用方法是使用\expandafter
。这在这里很有用,但很繁琐:我们需要跨越 16 个 token:
\expandafter\SetQuestionProperties\expandafter{\expandafter
s\expandafter e\expandafter c\expandafter t\expandafter
i\expandafter o\expandafter n\expandafter-\expandafter
t\expandafter i\expandafter t\expandafter l\expandafter
e\expandafter=\secName
}
因此,更好的选择是另一种常用的解决方案:定义一个临时宏(\x
),使用\edef
它来彻底扩展替换文本。为了只扩展\secName
一次,我们可以使用\unexpanded\expandafter{\secName}
:
\begingroup
\edef\x{\endgroup
\SetQuestionProperties{
section-title = \unexpanded\expandafter{\secName}
}}\x
(\SetQuestionProperties
不可扩展,因此无需担心。)但是,exsheets
是用 expl3 编写的,并且已经有一个\SetQuestionProperties
扩展其参数的版本:\exsheets_set_question_properties:x
。我们只需要使其在 expl3 语法之外可用:
\ExplSyntaxOn
\NewDocumentCommand \SetQuestionPropertiesX {m}
{ \exsheets_set_question_properties:x {#1} }
\ExplSyntaxOff
在下面的例子中,我也使用了,pre-body-hook
所以我不更改每个开头的行question
。
\documentclass[parskip=half]{scrartcl}
\usepackage{exsheets}
% \setlength{\parindent}{0pt} please don't use this but rather KOMA-Script's
% `parskip' option
\ExplSyntaxOn
\NewDocumentCommand \SetQuestionPropertiesX {m}
{ \exsheets_set_question_properties:x {#1} }
\ExplSyntaxOff
\DeclareQuestionProperty{section-title}
\SetupExSheets{
counter-within = section ,
headings = inline-nr ,
counter-format = qu). ,
section-hook =
\noindent\bfseries Section
\GetQuestionProperty{section-title}{\CurrentQuestionID}\space ,
question/pre-body-hook =
\SetQuestionPropertiesX{ section-title = \unexpanded\expandafter{\secName} }
}
\newcommand{\secName}{}
\newcommand{\lsection}[1]{\renewcommand*{\secName}{#1}\section{#1}}
\begin{document}
\lsection{One}
\begin{question}
say foo
\end{question}
\begin{solution}
foo
\end{solution}
\begin{question}
say bar
\end{question}
\begin{solution}
bar
\end{solution}
\lsection{Two}
\begin{question}
say baz
\end{question}
\begin{solution}
baz
\end{solution}
\begin{question}
say foobar
\end{question}
\begin{solution}
foobar
\end{solution}
\lsection{Answers}
\printsolutions
\end{document}
答案2
这是一个“非法”的答案,因为我提出的代码依赖于定义内部命令的变体。这个答案主要是为了给包开发人员提供思路。
我定义了一个命令\DeclareQuestionPropertyFixed
,该命令以属性名称和应从中获取值的变量作为参数,在本例中
\DeclareQuestionPropertyFixed{section-title}{\secName}
所以人们只需做
\SetupExSheets{
...
question/pre-body-hook = \SetQuestionProperties{section-title},
}
完整代码。
\documentclass[parskip=half]{scrartcl}
\usepackage{exsheets}
\ExplSyntaxOn
\NewDocumentCommand \DeclareQuestionPropertyFixed { m m }
{
\exsheets_declare_question_property:n {#1--fixed}
\keys_define:nn { question / meta }
{
#1 .code:n = \__exsheets_question_set_property:nV { #1--fixed } #2
}
}
\cs_generate_variant:Nn \__exsheets_question_set_property:nn {nV}
\ExplSyntaxOff
\DeclareQuestionPropertyFixed{section-title}{\secName}
\SetupExSheets{
counter-within = section ,
headings = inline-nr ,
counter-format = qu). ,
section-hook = \noindent\bfseries Section
\GetQuestionProperty{section-title}{\CurrentQuestionID}\space ,
question/pre-body-hook = \SetQuestionProperties{section-title}
}
\newcommand{\secName}{}
\newcommand{\lsection}[1]{\renewcommand*{\secName}{#1}\section{#1}}
\begin{document}
\lsection{One}
\begin{question}
say foo
\end{question}
\begin{solution}
foo
\end{solution}
\begin{question}
say bar
\end{question}
\begin{solution}
bar
\end{solution}
\lsection{Two}
\begin{question}
say baz
\end{question}
\begin{solution}
baz
\end{solution}
\begin{question}
say foobar
\end{question}
\begin{solution}
foobar
\end{solution}
\lsection{Answers}
\printsolutions
\end{document}