我目前正在开发一个家庭作业文档类,该类应该具有特定的布局。为此,我为这些问题创建了一个新环境,它已经在一定程度上可以工作,但仍存在一些错误。
问题的布局应如下:问题编号应出现在页面左侧,下方有一个可选框,其中包含问题的要点。 也可以选择打印替代文本,例如“奖励”来代替问题编号。 问题的文本应出现在右侧,第一行从问题编号的基线开始。
我当前对问题环境的实现如下(完整的 MWE 可以在下面找到):
\newcounter{Problem}
\NewDocumentEnvironment{Problem}{o D(){\theProblem)}}
{%
\refstepcounter{Problem}%
% Problem number as margin note
\noindent\marginpar{%
\begin{center}
\textbf{\large #2}
\IfNoValueF{#1}{% If arg1 given
% Create box with points
\vspace*{0.6\baselineskip}\par
\framebox[1.1\width]{#1 Points}}
\end{center}%
}%
\ignorespaces%
}{%
\vspace{\baselineskip}
}
为了获得所需的布局,我调整了页边距并反转了页边距,使其出现在页面的左侧。
我对问题环境的当前实现存在以下问题(所有问题也记录在下面的 MWE 中):
- 如果某道题的文本行数太少,则后一道题的题号会在页边距下移,以避免与前一道题和要点重叠。这会导致后一道题的基线与题号不对齐。
- 如果我给问题添加标签,开头会出现不需要的空格,因为
\ignorespaces
在这种情况下无法按预期工作。这可以通过使用来避免\begin{Problem}\label{prob}%
,但很可能会被遗忘。 - 如果问题始于
enumerate
或itemize
环境,则在开头插入不需要的空行。当然,这可以通过使用来解决\vspace
,但也许有更优雅的解决方案?
我认为,如果问题开头的文本像章节开头的文本一样,那么所有这些问题都会得到解决,其中问题编号被视为章节标题,但我不知道如何实现这一点。
下面是完整的 MWE,它也演示了上述三个问题:
\documentclass[a4paper,12pt]{article}
\usepackage{geometry}
\usepackage{enumitem}
\usepackage{xparse}
% Page layout
\geometry{
top=0.07\paperheight,
bottom=0.1\paperheight,
left=0.2\paperwidth,
right=0.07\paperwidth,
marginparwidth=0.1\paperwidth,
marginparsep=0.03\paperwidth
}
% Put margin notes on left side
\reversemarginpar
% Problem environment
\newcounter{Problem}
\NewDocumentEnvironment{Problem}{o D(){\theProblem)}}
{%
\refstepcounter{Problem}%
% Problem number as margin note
\noindent\marginpar{%
\begin{center}
\textbf{\large #2}
\IfNoValueF{#1}{% If arg1 given
% Create box with points
\vspace*{0.6\baselineskip}\par
\framebox[1.1\width]{#1 Points}}
\end{center}%
}%
\ignorespaces%
}{%
\vspace{\baselineskip}
}
\begin{document}
\begin{Problem}[10]
A problem\\with many lines\\and no label\\works well.
\end{Problem}
\begin{Problem}[10](Bonus)
Another problem with only one line.
\end{Problem}
\begin{Problem}\label{prob:3}
A problem with a label suffers from an unwanted whitespace at the
beginning. Furthermore it does not start at the baseline of the
problem number since the previous problem was very short.
\end{Problem}
\begin{Problem}
\begin{enumerate}[leftmargin=*]
\item A problem that starts with an enumerate or itemize environment
\item has a newline at the beginning such that the first line of
text does not start at the baseline of the problem number.
\end{enumerate}
\end{Problem}
\end{document}
如有任何帮助或建议我将不胜感激!
编辑:我通过在环境定义中使用\trivlist\item\relax
而不是取得了部分成功。这至少解决了问题 2. 和 3.,但在文本开头引入了一些额外的垂直空间,我必须对此进行更正。我当前的实现如下所示:\ignorespaces
\newcounter{Problem}
\NewDocumentEnvironment{Problem}{o D(){\theProblem)}}
{%
\refstepcounter{Problem}%
% Problem number as margin note
\noindent\marginpar{%
\parbox[t]{\marginparwidth}{%
\centering
\textbf{\large #2}%
\IfNoValueF{#1}{% If arg1 given
% Create box with points
\vspace*{0.6\baselineskip}\par%
\framebox[1.1\width]{#1 Points}}%
}%
}%
% trivlist introduces some space which we have to correct
\vspace*{-2.5\topsep}%
\trivlist\item\relax%
}{%
\endtrivlist%
\vspace*{\baselineskip}
}
但是,如果一个问题只有一行,那么后面的问题的编号就会向下移动,因此与文本的对齐不正确。因此,如果您能提供一些关于如何改进我的环境实施的建议,我将不胜感激。
答案1
这是基于使用包的建议xsim
。我这样做是因为它为创建自定义练习和考试提供了许多花哨的功能。
对于手头的例子,它使用\trivlist
您已经找到的例子,并借助重叠框中的表格将数字和点放在边缘。
如果给出了点,它会测量锻炼身体的高度,并在需要时添加一些垂直空间。您可以xsim
使用环境xparse
的b
类型参数和我下面使用的测量方法以类似的方式执行此操作。
上面xsim
是通过定义练习模板并告诉包使用它来完成的。对于奖励问题,bonus
定义了一个布尔属性。
代码
\documentclass{article}
\usepackage[showframe]{geometry}
\geometry{
top=0.07\paperheight,
bottom=0.1\paperheight,
left=0.2\paperwidth,
right=0.07\paperwidth,
marginparwidth=0.1\paperwidth,
marginparsep=0.03\paperwidth
}
\usepackage[no-files]{xsim}
\usepackage{enumitem,array,needspace}
\newbox\problembody
\DeclareExerciseProperty*{bonus}
\DeclareExerciseEnvironmentTemplate{problem}
{%
\trivlist
\item[\llap{%
\smash{%
\tabular[t]{@{}p{\marginparwidth}@{}}
\IfExercisePropertySetTF{bonus}
{\addtocounter{\GetExerciseParameter{counter}}{-1}\textbf{\large Bonus}}
{\textbf{\large\GetExerciseProperty{counter})}}%
\IfExercisePropertySetT{points}{%
\tabularnewline
\framebox[1.1\width]{%
\printgoal{\GetExerciseProperty{points}}%
~\XSIMtranslate{points}%
}%
}%
\endtabular
}%
}]\relax
}
{%
\endtrivlist
\IfExercisePropertySetT{points}{%
\setbox\problembody=\vbox{\GetExerciseProperty{exercise-body}}%
\ifdim\ht\problembody>\baselineskip\else
\vspace*{\baselineskip}
\fi
}%
}
\xsimsetup{
exercise/template = problem
}
\begin{document}
\begin{exercise}[points=10]
A problem\\with many lines\\and no label\\works well.
\end{exercise}
\begin{exercise}[points=10,bonus]
Another problem with only one line.
\end{exercise}
\begin{exercise}\label{prob:3}
A problem with a label suffers from an unwanted whitespace at the
beginning. Furthermore it does not start at the baseline of the
problem number since the previous problem was very short.
\end{exercise}
\begin{exercise}
\begin{enumerate}[leftmargin=*]
\item A problem that starts with an enumerate or itemize environment
\item has a newline at the beginning such that the first line of
text does not start at the baseline of the problem number.
\end{enumerate}
\end{exercise}
\end{document}