Управление вертикальным интервалом перед пустыми мини-страницами

Управление вертикальным интервалом перед пустыми мини-страницами

Я определил новую среду, которая рисует своего рода поле ответа с помощью 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), поэтому я предпочитаю добавлять \struts на границах.

Есть и другие проблемы, кроме той, что отмечена. Честно говоря, я удивлен, что код вообще запустился.

Во-первых, не следует использовать \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}

изображение полной страницы

Связанный контент