Я определил новую среду, которая рисует своего рода поле ответа с помощью fbox вокруг мини-страницы. Среда также помещает некоторый текст над полем ответа.
Вот минимальный рабочий пример:
\documentclass{article}
\usepackage{listings}
\newsavebox{\mybox}
\newenvironment{ansbox}[1]{Write answer in the box:\newline
\begin{lrbox}{\mybox}\begin{minipage}[t][#1]{\linewidth}}
{\vfill\hfill\end{minipage}\end{lrbox}\fbox{\usebox{\mybox}}}
\setlength{\parskip}{\baselineskip}
\setlength{\parindent}{0ex}
\begin{document}
Description of problem.
\begin{ansbox}{2in}
%empty box
\end{ansbox}
What is your name?
\begin{ansbox}{2in}
My name is
\end{ansbox}
Implement a factorial function.
\begin{ansbox}{2in}
\begin{lstlisting}
def factorial(n):
\end{lstlisting}
\end{ansbox}
\end{document}
Для удобства прилагаю скриншот первой страницы:
Как вы видите, есть вертикальный пробел, когда поле пустое или когда оно начинается сразу с окружения lstlisting. Я пробовал искать, но понятия не имею, как добавляется этот пробел или как от него избавиться.
Кроме того, как сохранить текст «заголовка» вместе с полем, когда он переходит на следующую страницу?
решение1
Проблема в том, как вы обеспечиваете ширину блока; в этом случае лучше добавить правило нулевой высоты такой же ширины, как блок. Вам также нужно обрезать некоторую ширину (для \fboxsep
и \fboxrule
).
\documentclass{article}
\usepackage{listings}
\newsavebox{\mybox}
\newenvironment{ansbox}[1]
{%
Write answer in the box:\\*
\begin{lrbox}{\mybox}
\begin{minipage}[t][#1]{\dimexpr\linewidth-2\fboxsep-2\fboxrule}
\hrule width \textwidth height 0pt
}
{\end{minipage}\end{lrbox}\fbox{\usebox{\mybox}}}
\setlength{\parskip}{\baselineskip}
\setlength{\parindent}{0ex}
\begin{document}
Description of problem.
\begin{ansbox}{1.5in}
%empty box
\end{ansbox}
What is your name?
\begin{ansbox}{1.5in}
My name is
\end{ansbox}
Implement a factorial function.
\begin{ansbox}{1.5in}
\begin{lstlisting}
def factorial(n):
\end{lstlisting}
\end{ansbox}
\end{document}
Ваш код, с \begin{ansbox}{1.5in}
, стал
\begin{minipage}[t][1.5in]{\linewidth}
<environment's contents>
\vfill\hfill
\end{minipage}
Когда тело среды пусто, это приводит к
\vfill
\hfill
\par\vfil
(последние токены добавляются, потому что вам нужна [t]
мини-страница; отменяется \vfil
) \vfill
. Точка отсчета поля определяется \vfill
. С другой стороны, при непустом содержимом у вас есть
My name is
\vfill
\hfill
\vfil
и контрольная точка находится на базовой линии верхнего абзаца; теперь высота блока будет измеряться как высота M плюс \fboxsep
плюс \fboxrule
; это составляет 6,83331+3+0,4=10,23331 пунктов. Это явно превышает порог, поэтому TeX будет использовать \lineskip
между строкой «Write answer in the box:» и блоком. В первом случае высота блока составляет всего 3,4 пт, а разделение, которое вы видите, составляет (поскольку строка выше не имеет глубины) \baselineskip
минус 3,4 пт.
В моем решении высота блока всегда будет равна 3,4 пункта, поскольку правило нулевой высоты определяет точку отсчета.
решение2
Мини-страницы обычно следуют правилам интервалов между блоками ( \lineskip
вместо \baselineskip
), поэтому я предпочитаю добавлять \strut
s на границах.
Есть и другие проблемы, кроме той, что отмечена. Честно говоря, я удивлен, что код вообще запустился.
Во-первых, не следует использовать \begin и \end в определении окружения, так как они будут развернуты не по порядку. Такие вещи лучше всего делать с помощью пакета environ.
Во-вторых, lstlisting не любит находиться внутри чего-либо (кроме \hbox). Пакет имеет собственное программное обеспечение окружения.
Если вы хотите предотвратить разрыв страницы между текстом и полем, вы можете использовать пакет needspace.
\documentclass{article}
\usepackage{listings}
\usepackage{environ}
\newsavebox{\mybox}
\NewEnviron{ansbox}[1]{Write answer in the box:\strut\newline
\fbox{\begin{minipage}[t][#1][s]{\dimexpr \linewidth-2\fboxsep-2\fboxrule}
\strut\BODY\vfill\hfill
\end{minipage}}}
\lstnewenvironment{lstbox}{\global\setbox\mybox=\hbox\bgroup}{\egroup}
\setlength{\parskip}{\baselineskip}
\setlength{\parindent}{0ex}
\begin{document}
Description of problem.
\begin{ansbox}{2in}
\end{ansbox}
What is your name?
\begin{ansbox}{2in}
My name is
\end{ansbox}
Implement a factorial function.
\begin{lstbox}
def factorial(n):
\end{lstbox}
\begin{ansbox}{1in}
\usebox{\mybox}
\end{ansbox}
\end{document}