一个简单的moodle.sty
数据库包含如下代码:
\begin{multi}{Name of the question}
Text of the question
\item first answer
\item secon answer
\item* the starred is the correct answer
...
\end{multi}
我需要从这样的数据库中提取文本、答案和正确答案。
multi
我基本上成功地通过使用environ
包重新定义环境并在包的帮助下进行解析来做到这一点listofitems
,这要感谢那个问题。
问题是问题和答案可能已经使用了等itemize
。enumerate
在这种情况下,每个都\item
被解释为新答案的开始,整个过程就会崩溃。一种解决方法是将文本分组到括号中,但我需要使用现有数据库并且无法修改它们。
注意:显然,style 包moodle.sty
完全满足了我的需求,因为它工作正常,但我无法从代码中理解它是如何工作的。(如果我可以复制并粘贴 moodle.sty 的一部分或去那里修改一些宏以满足我的需求,我会很高兴,但我对此的了解TeX
并不那么深入)。
注意:软件包moodle.sty
和getitems.sty
是由同一个人编写的。因此,既然moodle.sty
运行良好,我猜它getitems
比效果更好listofitems
。有没有一种简单的方法可以替换上述答案中的listofitems
使用?getitems
答案1
这真是糟糕的标记:您将无法在问题文本中使用列表。
无论如何,这是一个解析器。
\documentclass{article}
\usepackage{amsthm}
\usepackage{enumitem}
\newcounter{exercise}
\ExplSyntaxOn
\NewDocumentEnvironment{multi}{m +b}
{
\par\addvspace{\topsep}\setlength{\parindent}{0pt}
\stepcounter{exercise}
\textbf{Exercise~\theexercise}~--~#1\par\nobreak
\moodle_multi:n { #2 }
\par\addvspace{\topsep}
}
{}
\NewDocumentCommand{\showcorrect}{}
{
\bool_gset_true:N \g_moodle_multi_correct_bool
}
\NewDocumentCommand{\hidecorrect}{}
{
\bool_gset_falsee:N \g_moodle_multi_correct_bool
}
\bool_new:N \g_moodle_multi_correct_bool
\seq_new:N \l__moodle_multi_text_seq
\tl_new:N \l__moodle_multi_text_tl
\cs_new_protected:Nn \moodle_multi:n
{
\seq_set_split:Nnn \l__moodle_multi_text_seq { \item } { #1 }
% the first item will contain the question text
\seq_pop_left:NN \l__moodle_multi_text_seq \l__moodle_multi_text_tl
\tl_use:N \l__moodle_multi_text_tl
% now we rebuild the answers
\begin{enumerate}[label=(\Alph*),nosep,labelsep=0.75em]
\use:e
{% add the first \item and put it also between the other items
\__moodle_multi_item: \seq_use:Nn \l__moodle_multi_text_seq { \__moodle_multi_item: }
}
\end{enumerate}
}
\cs_new_protected:Nn \__moodle_multi_item:
{
\item
\peek_charcode_remove:NT *
{% there is an asterisk
\bool_if:NT \g_moodle_multi_correct_bool { \__moodle_multi_correct: }
}
}
\cs_new_protected:Nn \__moodle_multi_correct:
{
\makebox[0pt][r]{\makebox[0pt][l]{$^{\scriptscriptstyle*}$}\hspace{\labelsep}}
\ignorespaces
}
\ExplSyntaxOff
\begin{document}
\begin{multi}{Name of the question}
Text of the question
\item first answer
\item second answer
\item* the starred is the correct answer
\end{multi}
\showcorrect
\begin{multi}{Name of the question}
Text of the question
\item first answer
\item second answer
\item* the starred is the correct answer
\end{multi}
\end{document}
正确答案的标记不占用水平空间,因此如果显示它,排版与没有它时相同。
我们可以在文本部分支持列表吗?可以,假设“答案”部分没有列表。
\documentclass{article}
\usepackage{amsthm}
\usepackage{enumitem}
\newcounter{exercise}
\ExplSyntaxOn
\NewDocumentEnvironment{multi}{m +b}
{
\par\addvspace{\topsep}\setlength{\parindent}{0pt}
\stepcounter{exercise}
\textbf{Exercise~\theexercise}~--~#1\par\nobreak
\moodle_multi:n { #2 }
\par\addvspace{\topsep}
}
{}
\NewDocumentCommand{\showcorrect}{}
{
\bool_gset_true:N \g_moodle_multi_correct_bool
}
\NewDocumentCommand{\hidecorrect}{}
{
\bool_gset_falsee:N \g_moodle_multi_correct_bool
}
\bool_new:N \g_moodle_multi_correct_bool
\seq_new:N \l__moodle_multi_text_seq
\tl_new:N \l__moodle_multi_text_tl
\tl_new:N \l__moodle_multi_moretext_tl
\tl_new:N \l__moodle_multi_answers_tl
\cs_new_protected:Nn \moodle_multi:n
{
\regex_split:nnN { \{(enumerate|itemize)\} } { #1 } \l__moodle_multi_text_seq
\tl_set:Nx \l__moodle_multi_answers_tl { \seq_item:Nn \l__moodle_multi_text_seq { -1 } }
\tl_set:Nn \l__moodle_multi_text_tl { #1 }
\regex_replace_once:nnN { (.*)\u{l__moodle_multi_answers_tl} } { \1 } \l__moodle_multi_text_tl
\seq_set_split:NnV \l__moodle_multi_text_seq { \item } \l__moodle_multi_answers_tl
% the first item will contain the question text
\seq_pop_left:NN \l__moodle_multi_text_seq \l__moodle_multi_moretext_tl
\tl_use:N \l__moodle_multi_text_tl
\tl_use:N \l__moodle_multi_moretext_tl
% now we rebuild the answers
\begin{enumerate}[label=(\Alph*),nosep,labelsep=0.75em]
\use:e
{% add the first \item and put it also between the other items
\__moodle_multi_item: \seq_use:Nn \l__moodle_multi_text_seq { \__moodle_multi_item: }
}
\end{enumerate}
}
\cs_new_protected:Nn \__moodle_multi_item:
{
\item
\peek_charcode_remove:NT *
{% there is an asterisk
\bool_if:NT \g_moodle_multi_correct_bool { \__moodle_multi_correct: }
}
}
\cs_new_protected:Nn \__moodle_multi_correct:
{
\makebox[0pt][r]{\makebox[0pt][l]{$^{\scriptscriptstyle*}$}\hspace{\labelsep}}
\ignorespaces
}
\ExplSyntaxOff
\begin{document}
\begin{multi}{Name of the question}
Text of the question
\begin{itemize}
\item a
\item b
\end{itemize}
More text
\begin{enumerate}
\item a
\item b
\end{enumerate}
More text
\item first answer
\item second answer
\item* the starred is the correct answer
\end{multi}
\showcorrect
\begin{multi}{Name of the question}
Text of the question
\item first answer
\item second answer
\item* the starred is the correct answer
\end{multi}
\end{document}