Controle o espaçamento vertical antes de minipáginas vazias

Controle o espaçamento vertical antes de minipáginas vazias

Defini um novo ambiente que desenha uma espécie de caixa de resposta usando fbox em torno de uma minipágina. O ambiente também coloca algum texto acima da caixa de resposta.

Aqui está um exemplo mínimo de trabalho:

\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}

Por conveniência, anexei uma captura de tela da primeira página:

insira a descrição da imagem aqui

Como você pode ver, há um espaço vertical quando a caixa está vazia ou quando ela começa imediatamente com um ambiente lstlisting. Tentei pesquisar, mas não tenho ideia de como esse espaço é adicionado ou como me livrar dele.

Além disso, como posso manter o texto do "cabeçalho" junto com a caixa quando ele for para a próxima página?

Responder1

O problema está em como você garante a largura da caixa; neste caso, é melhor adicionar uma regra de altura zero tão larga quanto a caixa. Você também precisa cortar alguma largura (para \fboxsepe \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}

insira a descrição da imagem aqui

Seu código, com \begin{ansbox}{1.5in}, tornou-se

\begin{minipage}[t][1.5in]{\linewidth}
<environment's contents>
\vfill\hfill
\end{minipage}

Quando o corpo do ambiente está vazio, isso faz com que

\vfill
\hfill
\par\vfil

(os últimos tokens são adicionados porque você deseja uma [t]minipágina; \vfilé cancelado por \vfill). O ponto de referência da caixa é determinado pelo \vfill. Por outro lado, com um conteúdo não vazio, você tem

My name is
\vfill
\hfill
\vfil

e o ponto de referência está na linha de base do parágrafo superior; agora a altura da caixa será medida como a altura de M mais \fboxsepmais \fboxrule; isso perfaz 6,83331+3+0,4=10,23331 pontos. Isso claramente excede o limite, então o TeX usará \lineskipentre a linha “Escrever resposta na caixa:” e a caixa. No primeiro caso, a altura da caixa é de apenas 3,4 pontos e a separação que você vê é (já que a linha acima não tem profundidade) \baselineskipmenos 3,4 pontos.

Com a minha solução a caixa sempre terá altura 3,4pt, pois a regra da altura zero determina o ponto de referência.

Responder2

As minipáginas geralmente seguem regras de espaçamento entre caixas ( \lineskipem vez de \baselineskip), então gosto de adicionar \struts nas bordas.

Existem outros problemas além dos mencionados. Francamente, estou surpreso que o código tenha sido executado.

Primeiro, você não deve usar \begin e \end na definição de um ambiente, pois eles serão expandidos fora de ordem. Esse tipo de coisa é melhor feito usando o pacote environ.

Segundo, o lstlisting não gosta de estar dentro de nada (exceto um \hbox). O pacote possui software de ambiente próprio.

Se quiser evitar uma quebra de página entre o texto e a caixa, você pode usar o pacote 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}

imagem de página inteira

informação relacionada