帮助我的自定义环境

帮助我的自定义环境

我目前正在开发一个家庭作业文档类,该类应该具有特定的布局。为此,我为这些问题创建了一个新环境,它已经在一定程度上可以工作,但仍存在一些错误。

问题的布局应如下:问题编号应出现在页面左侧,下方有一个可选框,其中包含问题的要点。 也可以选择打印替代文本,例如“奖励”来代替问题编号。 问题的文本应出现在右侧,第一行从问题编号的基线开始。

我当前对问题环境的实现如下(完整的 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 中):

  1. 如果某道题的文本行数太少,则后一​​道题的题号会在页边距下移,以避免与前一道题和要点重叠。这会导致后一道题的基线与题号不对齐。
  2. 如果我给问题添加标签,开头会出现不需要的空格,因为\ignorespaces在这种情况下无法按预期工作。这可以通过使用来避免\begin{Problem}\label{prob}%,但很可能会被遗忘。
  3. 如果问题始于enumerateitemize环境,则在开头插入不需要的空行。当然,这可以通过使用来解决\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使用环境xparseb类型参数和我下面使用的测量方法以类似的方式执行此操作。

上面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}

相关内容