Definí un nuevo entorno que dibuja una especie de cuadro de respuesta usando fbox alrededor de una minipágina. El entorno también coloca texto encima del cuadro de respuesta.
Aquí hay un ejemplo de trabajo mínimo:
\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}
Para mayor comodidad adjunto una captura de pantalla de la primera página:
Como puede ver, hay un espacio vertical cuando el cuadro está vacío o cuando comienza inmediatamente con un entorno de lista. Intenté buscar pero no tengo idea de cómo se agrega este espacio o cómo deshacerme de él.
Además, ¿cómo puedo mantener el texto del "encabezado" junto con el cuadro cuando pasa a la página siguiente?
Respuesta1
El problema está en cómo se asegura el ancho del cuadro; en este caso es mejor agregar una regla de altura cero tan ancha como el cuadro. También necesitas recortar algo de ancho (para \fboxsep
y \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}
Tu código, con \begin{ansbox}{1.5in}
, se convirtió
\begin{minipage}[t][1.5in]{\linewidth}
<environment's contents>
\vfill\hfill
\end{minipage}
Cuando el cuerpo ambiental está vacío, esto genera
\vfill
\hfill
\par\vfil
(los últimos tokens se agregan porque desea una [t]
minipágina; \vfil
se cancela con \vfill
). El punto de referencia de la caja está determinado por el \vfill
. Por otro lado, con un contenido no vacío, tienes
My name is
\vfill
\hfill
\vfil
y el punto de referencia está en la línea base del párrafo superior; ahora la altura de la caja se medirá como la altura de M más \fboxsep
más \fboxrule
; esto equivale a 6,83331+3+0,4=10,23331 puntos. Esto claramente excede el umbral, por lo que TeX lo usará \lineskip
entre la línea "Escribir respuesta en el cuadro:" y el cuadro. En el primer caso, la altura del cuadro es solo 3,4 puntos y la separación que ve es (ya que la línea de arriba no tiene profundidad) \baselineskip
menos 3,4 puntos.
Con mi solución, la caja siempre tendrá una altura de 3,4 puntos, porque la regla de altura cero determina el punto de referencia.
Respuesta2
Las minipáginas generalmente siguen reglas de espaciado de cuadros ( \lineskip
en lugar de \baselineskip
), por lo que me gusta agregar \strut
letras en los bordes.
Hay otros problemas además del señalado. Francamente, me sorprende que el código se haya ejecutado.
En primer lugar, no debe utilizar \begin y \end en la definición de un entorno, ya que se expandirán desordenadamente. Este tipo de cosas se hace mejor usando el paquete ambiental.
En segundo lugar, a lstlisting no le gusta estar dentro de nada (excepto \hbox). El paquete tiene su propio software ambiental.
Si desea evitar un salto de página entre el texto y el cuadro, puede utilizar el paquete 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}