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:
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 \fboxsep
e \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}
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 \fboxsep
mais \fboxrule
; isso perfaz 6,83331+3+0,4=10,23331 pontos. Isso claramente excede o limite, então o TeX usará \lineskip
entre 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) \baselineskip
menos 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 ( \lineskip
em vez de \baselineskip
), então gosto de adicionar \strut
s 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}