# Defining rules for line breaks in \newcommand

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.

-
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 2: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 2:44
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

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}


-
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
@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
@jamaicanworm See edit –  egreg Dec 14 '11 at 16:32
@jamaicanworm Change to 1000. You are putting too heavy requirements to the paragraph maker. –  egreg Dec 14 '11 at 16:54

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) {};

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}


-
This works, but might there be a simpler solution? –  jamaicanworm Dec 14 '11 at 5:24

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:

\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".

-