![使用 xparse 将密钥从 multicols 本地传递到 enumitem](https://linux22.com/image/392774/%E4%BD%BF%E7%94%A8%20xparse%20%E5%B0%86%E5%AF%86%E9%92%A5%E4%BB%8E%20multicols%20%E6%9C%AC%E5%9C%B0%E4%BC%A0%E9%80%92%E5%88%B0%20enumitem.png)
key=val
我在尝试使用本地定义xparse
来传递multicols
枚举(包)时遇到了一个小问题enumitem
。我重新定义了环境enumerate
以接受columns=number
和创建的命令\keyans[...]
,\answer{...}
并保存工作表练习的多项选择键和答案,一切都很好,只是当在第一级\showanskey[...]{...}{...}[...]
激活时,会影响嵌套在其中的所有级别。columns
enumerate
columns=2
在第一级使用时它看起来像这样:
所有嵌套环境都分为两列。
我希望输出是这样的:
我尝试将\group_begin:
和\group_end:
放在不同的地方,但只会出现错误。代码改编自定义具有多个可选参数的列表环境和 MWE:
% arara: pdflatex
% arara: clean: { extensions: [ aux, log] }
\documentclass{article}
\usepackage{letltxmacro,enumitem,multicol,xparse}
\usepackage[most]{tcolorbox}
\usepackage[margin=0.6in,noheadfoot,papersize={8.5in,13in}]{geometry} % for mwe
\setlength{\parindent}{0pt}
\pagestyle{empty}
% Set keys for save-ans and save-key in enumitem
\SetEnumitemKey{save-ans}{before={\storecurrentid{#1}\begin{saveanswer}{#1}},after=\end{saveanswer}}%
\SetEnumitemKey{save-key}{before={\storecurrentid{#1}\begin{savekeyans}{#1}},after=\end{savekeyans}}%
% Save a copy enumerate
\LetLtxMacro\oldenum\enumerate
\LetLtxMacro\oldendenum\endenumerate
% Redefine enumerate for multicols
\ExplSyntaxOn
\RenewDocumentEnvironment{enumerate}{ O{} }
{
\tl_clear:N \l_keyanswer_enumitem_tl
\keys_set:nn { keyanswer } { #1 }
\int_compare:nT { \l_keyanswer_columns_tl > 1 }
{
\setlength{\multicolsep}{5.0pt plus 2.0pt minus 1.5pt}
\begin{multicols}{ \l_keyanswer_columns_tl }
}
\keyanswer_beginenum:V \l_keyanswer_enumitem_tl
}
{
\oldendenum
\int_compare:nT { \l_keyanswer_columns_tl > 1 }
{ \end{multicols} }
}
\cs_new_protected:Npn \keyanswer_beginenum:n #1
{ \oldenum[#1] }
\cs_generate_variant:Nn \keyanswer_beginenum:n {V}
\tl_new:N \l_keyanswer_columns_tl
\tl_new:N \l_keyanswer_enumitem_tl
\keys_define:nn { keyanswer }
{
columns .tl_set:N = \l_keyanswer_columns_tl,
columns .initial:n = 1,
unknown .code:n = \tl_put_right:Nx \l_keyanswer_enumitem_tl
{ \l_keys_key_tl \tl_if_empty:nF { #1 } { = \exp_not:n { #1 } } , },
}
% Implementation to save \answer{...} and \keyans[...] in lists
\prop_new:N \g_keyanswer_admin_prop
\cs_new:Npn \storecurrentid #1{%
\prop_gput:Nnn \g_keyanswer_admin_prop {current-id} {#1}
}
\cs_new:Npn \retrievecurrentid {%
\prop_item:Nn \g_keyanswer_admin_prop {current-id}
}
% environments for save \answer{...} and \keyans[...]
\NewDocumentEnvironment{saveanswer}{ m }{%
\setlist[enumerate,2]{leftmargin=16pt,nosep,itemsep=0pt,label=(\alph*),before={\stepdownlevel},after={\stepuplevel}}%
\setlist[enumerate,3]{leftmargin=20pt,nosep,itemsep=0pt,label=\Roman*.,before={\stepdownlevel},after={\stepuplevel}}%
\seq_if_exist:cF { l_keyanswer_data_#1_seq }{ \seq_new:c { l_keyanswer_data_#1_seq }}
}{ \leavevmode }
\NewDocumentEnvironment{savekeyans}{ m }{%
\setlist[enumerate,1]{left=0pt,labelsep=5pt,itemsep=1pt,label=\arabic*.}%
\setlist[enumerate,2]{leftmargin=16pt,nosep,label=\Alph*)}%
\seq_if_exist:cF { l_keyanswer_data_#1_seq }{%
\seq_new:c { l_keyanswer_data_#1_seq }}}{ \leavevmode }
% commands \answer{...} and \keyans[...]
\NewDocumentCommand{\answer}{ +m }{%
\seq_gput_right:cn { l_keyanswer_data_ \retrievecurrentid _seq }{\item #1}
\par%
}
\NewDocumentCommand\keyans{ !o }{%
\IfNoValueTF{#1}{%
\tl_set:Nn \l_tmpa_tl {\protect\item}%
\tl_put_right:Nx \l_tmpa_tl {\protect\space \Alph{enumii}}%
\seq_gput_right:cV { l_keyanswer_data_ \retrievecurrentid _seq }{ \l_tmpa_tl}%
\par%
}{%
\seq_gput_right:cn { l_keyanswer_data_ \retrievecurrentid _seq }{\item #1}%
\par%
}%
}%
% \stepdownlevel and \stepuplevel for save in nested enumerate
\newcommand{\stepdownlevel}{%
\seq_gput_right:cn {l_keyanswer_data_ \retrievecurrentid _seq} {\item \begin{enumerate}}
}
\newcommand{\stepuplevel}{%
\seq_gput_right:cn {l_keyanswer_data_ \retrievecurrentid _seq} {\end{enumerate}}
}
% Display \answer{...} and \keyans[...] in list by id
\cs_new:Npn \displayseqcontent #1#2 {%
\seq_if_empty:cF { l_keyanswer_data_#1_seq } {%
\seq_log:c { l_keyanswer_data_#1_seq }
\setlist[enumerate,1]{labelsep=5pt,label=\arabic*.,leftmargin=15pt,labelsep=3pt,font=\footnotesize,nosep,widest=80}%
\setlist[enumerate,2]{font=\footnotesize,labelsep=5pt,leftmargin=0.6cm,nosep,label=(\alph*)}%
\setlist[enumerate,3]{font=\footnotesize,labelsep=5pt,leftmargin=0.3cm,nosep,label=\Roman*.}%
\begin{enumerate}[#2] \small\setlength{\columnsep}{0pt}
\seq_map_inline:cn { l_keyanswer_data_#1_seq } { ##1 }
\end{enumerate}
}
}
\ExplSyntaxOff
% \showanskey[tcolorbox]{title}{list ref}[columns]
\DeclareTotalTColorBox{\showanskey}{O{} m m O{4}}
{ colback=white,size=small,top=0mm,bottom=1.5mm, left=0mm,width=\columnwidth,title filled,%
fontupper=\small,fonttitle=\small\sffamily, adjusted title={#2},center title,#1}
{ \displayseqcontent{#3}{columns=#4} }%
\begin{document}
\section{Multiple Choice}
\begin{enumerate}[save-key=mchoice,left=0pt,columns=2]
\item First type of questions
\begin{enumerate}
\item value
\item value
\item value
\item correct \keyans
\item value
\end{enumerate}
\item Second type of questions
\begin{enumerate}[leftmargin=2pc,label=\Roman*.]
\item $2\alpha+2\delta=90^{\circ}$
\item $\alpha=\delta$
\item $\angle EDF=45^{\circ}$
\end{enumerate}
\begin{enumerate}[columns=2]%
\item I only
\item II only \keyans
\item I and II only
\item I and III only
\item I, II, and III
\end{enumerate}
%\columnbreak %
\item Third type of questions
\begin{enumerate}[leftmargin=2pc,label=(\arabic*)]
\item $2\alpha+2\delta=90^{\circ}$
\item $\angle EDF=45^{\circ}$
\end{enumerate}
\begin{enumerate}
\item Altenativa A
\item Altenativa B
\item Altenativa C \keyans
\item Altenativa D
\item Altenativa E
\end{enumerate}
\item Fourth type of question, a problem with numerical response \keyans[$\sqrt{2}$]
\end{enumerate}
\section{Worksheet}
\begin{enumerate}[save-ans=Worksheet,left=0pt,labelsep=5pt,nosep,label=\arabic*.,columns=2]
\item Factor $x^{2}-2x+1$ \answer{$\left(x-1\right)^{2}$}
\item Factor $3x+3y+3z$ \answer{$3(x+y+z)$}
\item True False
\begin{enumerate}
\item $\alpha > \delta$ \answer{False}
\item \LaTeX2e\ is cool? \answer{Very True!}
\end{enumerate}
\item Related to Linux
\begin{enumerate}
\item You use linux? \answer{Yes}
\item Usually uses the package manager? \answer{Yes}
\item Rate the following package managers
\begin{enumerate}
\item dnf \answer{good}
\item apt \answer{very good}
\item yum \answer{obsolete}
\end{enumerate}
\end{enumerate}
\end{enumerate}
\section{Answers}
\showanskey[colback=yellow!30!white]{Multiple Choice Keys}{mchoice}[5]
\showanskey[colback=yellow!30!white]{Solution Worksheet}{Worksheet}[2]
\section{Normal enumerate}
\begin{enumerate}
\item First level
\begin{enumerate}
\item Second level
\item value
\item \begin{enumerate}
\item Third level
\item value
\end{enumerate}
\end{enumerate}
\end{enumerate}
\end{document}
如果放入所有子层级,columns=1
则跳过该问题,但是,不能用 来做到这一点。如果我\showanskey
不使用,则直接使用\RenewDocumentEnvironment{enumerate}
\SetEnumitemKey{columns}{before=\begin{multicols}{#1},after=\end{multicols}}%
我收到以下错误:
! LaTeX3 Error: Variable \l_keyanswer_data_mchoice_seq undefined.
我怎样才能解决这个问题?
感激的
答案1
一旦设置了键,值将保持不变。
在设置指定的值之前,您可以通过指定相关键来简单地恢复该值:
\keys_set:nn { keyanswer } { #1 }
应该成为
\keys_set:nn { keyanswer } { columns=1, #1 }