9

Thanks to the help of this answer, I've defined a command for creating a blank line:

\newcommand{\blank}[1]{\rule{#1}{0.4pt}}

However, because this is a user-defined command, LaTeX doesn't seem to factor it in to its calculations of when to start a new line. For example, if I write:

This is a long line and the blank line at the end is going to run off the page \blank{6cm}

then the blank line at the end runs off the page. How can I prevent this from happening?

EDIT: This actually only happens in a specific case: when I'm in the amsthm package's proof environment, and I have at least one line of writing followed by an enumeration.

\documentclass{article}
\usepackage{amsthm}
\newcommand{\blank}[1]{\rule[-3pt]{#1}{0.4pt}}  % nice blank underscores
\begin{document}
\begin{proof}
Here is my proof:
\begin{enumerate}
\item This is a long line and the blank line is going to run off \blank{8cm}
\item This is the second line.
\end{enumerate}
\end{proof}
\end{document}

Even when the blank line doesn't run off the page, I still get an overfull hbox warning for each instance of \blank I have within an enumerate in a proof.

jamaicanworm
  • 29,114
  • 2
    Can you explain in more detail where is this line to appear? Do you want a line to fill the remaining space on a line, or a line to separate paragraphs? – Gonzalo Medina Dec 14 '11 at 02:14
  • You're right, this only happens in a very specific case--when I'm in the amsthm package's proof environment, and I have at least one line of writing followed by an enumeration. I've edited the question to explain this. – jamaicanworm Dec 14 '11 at 02:44
  • 1
    this could happen in any enumerate environment, not just within a proof with amsthm. (remove amsthm and the proof environment to demonstrate.) it's still a useful question though. – barbara beeton Dec 14 '11 at 13:54

3 Answers3

10

If you want that the rule goes automatically on the next line if it can't be placed in the current one, just say

\newcommand{\blank}[2][100]{\hfil\penalty#1\hfilneg\rule[-3pt]{#2}{0.4pt}}

This is modeled on the \filbreak macro in the TeXbook.

The default penalty is 100, which discourages a line break. In cases of emergency you can insert a different one as optional argument:

 \blank[0]{3cm}

enter image description here

egreg
  • 1,121,712
  • This actually automatically puts the rule on the next line, even if it COULD fit on the current one... – jamaicanworm Dec 14 '11 at 16:02
  • 1
    @jamaicanworm Change -100 into 0 – egreg Dec 14 '11 at 16:05
  • In the following code, I'm still getting this problem:

    \documentclass{article} \newcommand{\blank}[1]{\hfil\penalty0\hfilneg\rule[-3pt]{#1}{0.4pt}} \begin{document} \begin{enumerate} \item We can write $A^n$ as \[ A^n = \bigcup_{a^{n-1} \in A^{n-1}} {(a^{n-1}, a) ,:, a \in A }, \] which by the inductive hypothesis is a \blank{2cm} union of countable sets, so by Corrolary \blank{2cm}, $A^n$ is at most countable. But $A$ is infinite $\Rightarrow A^n$ is \blank{2cm}. \end{enumerate} \end{document}

    The blank between is a and union is on a new line, even thought there's space for it...

    – jamaicanworm Dec 14 '11 at 16:25
  • 1
    @jamaicanworm See edit – egreg Dec 14 '11 at 16:32
  • Whether the \hfill parameter is 0 or 100, I'm still having problems. In the following example, the blank between $x \in$ and (for some $i$) appears on a new line... \documentclass{article} \newcommand{\blank}[1]{\hfil\penalty100\hfilneg\rule[-3pt]{#1}{0.4pt}} \begin{document} \begin{enumerate} \item \blank{2cm} and \blank{2cm} $\Rightarrow x \in$ \blank{2cm} (for some $i$) $\Rightarrow x \in A \cap B_{i}$ (\blank{2cm}) $\Rightarrow$ \blank{2cm} or $x \in A \cap B_{2}$ or ... or \blank{2cm} $\Rightarrow x \in \bigcup_{i=1}^n (A \cap B_{i})$. \end{enumerate} \end{document} – jamaicanworm Dec 14 '11 at 16:42
  • 1
    @jamaicanworm Change to 1000. You are putting too heavy requirements to the paragraph maker. – egreg Dec 14 '11 at 16:54
4

The following example shows the definition of a \IntRule command which will typeset the rule immediately after the text if there's enough space in the line; otherwise, the line will be moved to a new line. The main code comes from Martin Scharrer's answer to Is there a way to measure the remaining space of a line of text?:

\documentclass{article}
\usepackage{amsthm}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{ifthen}

\newcommand{\currentsidemargin}{%
  \ifodd\value{page}%
    \oddsidemargin%
  \else%
    \evensidemargin%
  \fi%
}

\newlength\whatsleft

\newcommand\measureremainder[1]{%
\begin{tikzpicture}[overlay,remember picture]
    % Helper nodes
    \path (current page.north west) ++(\hoffset, -\voffset)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\paperwidth, minimum height=\paperheight]
        (pagearea) {};

    \path (pagearea.north west) ++(1in+\currentsidemargin,-1in-\topmargin-\headheight-\headsep)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\textwidth, minimum height=\textheight]
        (textarea) {};

    % Measure distance to right text border
    \path let \p0 = (0,0), \p1 = (textarea.east) in
        [/utils/exec={\pgfmathsetlength#1{\x1-\x0}\global#1=#1}];

\end{tikzpicture}%
}

\newcommand\IntRule[1]{%
  \measureremainder\whatsleft%
  \ifthenelse{\lengthtest{\the\whatsleft<#1}}{\mbox{}\\}{}\rule{#1}{0.4pt}}

\begin{document}

This is a long line and the blank line at the end is not going to run off\IntRule{6cm}

This is a short line \IntRule{6cm}

This is a long line and the blank line at the end is not going to run off\IntRule{1cm}

This is a short line \IntRule{\textwidth}

\begin{proof}
Here is my proof:
\begin{enumerate}
\item This is a long line and the black line is not going to run off \IntRule{8cm}
\item This is the second line.
\end{enumerate}
\end{proof}

\end{document}

enter image description here

Gonzalo Medina
  • 505,128
3

The linegoal package provides the \linegoal dimension which gives the remaining length of a line. Taking @Gonzalo's answer as a start, here's a shorter alternative:

enter image description here

\documentclass{article}
\usepackage{amsthm}% http://ctan.org/pkg/amsthm
\usepackage{linegoal}% http://ctan.org/pkg/linegoal
\usepackage{ifthen}% http://ctan.org/pkg/ifthen

\newlength{\remainder} \newcommand{\blank}[1]{% \setlength{\remainder}{\linegoal}% Store remaining line dimension \ifthenelse{\lengthtest{\the\remainder<#1}}{\mbox{}\}{}\rule{#1}{0.4pt}}

\begin{document}

This is a long line and the blank line at the end is not going to run off\blank{6cm}

This is a short line \blank{6cm}

This is a long line and the blank line at the end is not going to run off\blank{1cm}

This is a short line \blank{\textwidth}

\begin{proof} Here is my proof: \begin{enumerate} \item This is a long line and the black line is not going to run off \blank{8cm} \item This is the second line. \end{enumerate} \end{proof}

\end{document}

Since linegoal ultimately uses zref, you need to compile a couple of times (at least twice, maybe three times) for the savepos module's PDF labels to "settle".

Werner
  • 603,163