7

Why does a \hrule need text around it to work? Example that does not draw a line:

\documentclass{article}

\begin{document}
%foo
\hrule
%bar
\end{document}

If one removes the % before %foo or %bar (or both) the line is drawn perfectly fine. According to the comments, this is because the rule needs not to be in vertical mode. The command \hrule shows a very clear intention: "Dear compiler, please draw a horizontal line!" So, why doesn't \hrule leave vertical mode automatically?

Of course, this probably is a pure "academical" problem, because in any real world document one has some content. ;)

Foo Bar
  • 13,247

2 Answers2

13

\hrule is a "primitive" instruction. The natural or default width of the rule drawn by this instruction is the width of the vertical box that encloses the \hrule instruction (see chap. 21 of the TeXbook, "Making Boxes"). If the width of the enclosing box is zero and if you don't specify an explicit width instead, no horizontal line is generated.

An example of \hrule with an explicit width and no surrounding text would be:

\documentclass{article} 
\begin{document} 
\hrule width3cm 
\end{document}

The reason why

\documentclass{article} 
\begin{document} 
\leavevmode
\hrule
\end{document}

generates a line of width \textwidth is that \leavevmode is defined as follows (see p. 356 of the TeXbook):

\def\leavevmode{\unhbox\voidb@x} % begins a paragraph, if necessary

where \voidb@x (unsurprisingly, given its name) generates a completely empty "box" (in the TeX sense of the word) and \unhbox is a TeX primitive that unpacks the contents ot its argument (which must be a "box") and places them in horizontal mode. (Since \voidb@x has no contents, \unhbox returns nothing. However, it "does nothing" in horizontal mode.) Thus, immediately after \leavevmode is finished, TeX is in "horizontal mode". The width of the enclosing vertical box is given by, you guessed it, \textwidth; hence, \hrule draws a line of width \textwidth.

Mico
  • 506,678
  • 1
    Another example where \hrule adjusts to fit the box size is in the case of leaders. Compare \leavevmode\leaders\hrule height 1pt \hfill \kern 0pt to \leavevmode\leaders\hrule height 1pt \hfill \kern 3in – Steven B. Segletes Aug 18 '15 at 12:03
3

Dear TeX, please end the paragraph, if you're typesetting one, and make a rule with the default height (0.4pt) and depth (0pt), as wide as the box where the rule will end up in.

Now, if I compile the following document

\documentclass{article}

\showoutput

\begin{document}

\hrule

\end{document}

I get the following in the log file:

Completed box being shipped out [1]
\vbox(633.0+0.0)x407.0
.\glue 16.0
.\vbox(617.0+0.0)x345.0, shifted 62.0
..\vbox(12.0+0.0)x345.0, glue set 12.0fil
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0
..\glue 25.0
..\glue(\lineskip) 0.0
..\vbox(550.0+0.0)x0.0, glue set 539.94232fil
...\write-{}
...\glue(\topskip) 9.6
...\rule(0.4+0.0)x*
...\glue 0.0 plus 1.0fil
...\glue 0.0
...\glue 0.0 plus 0.0001fil
..\glue(\baselineskip) 23.55556
..\hbox(6.44444+0.0)x345.0, glue set 170.0fil
...\glue 0.0 plus 1.0fil
...\OT1/cmr/m/n/10 1
...\glue 0.0 plus 1.0fil

The first line after the banner describes the page being shipped out, which has height 633pt (\textheight plus the header and the footer), no depth and width 407pt (\textwidth). Then

..\vbox(12.0+0.0)x345.0, glue set 12.0fil
...\glue 0.0 plus 1.0fil
...\hbox(0.0+0.0)x345.0

is the (empty) header, followed by 25pt of space (\headsep) and \lineskip (because the following box is very high).

The following box is the page body

..\vbox(550.0+0.0)x0.0, glue set 539.94232fil

that has height 550pt (the \textheight) and width 0pt, because it contains no box: just a default \write that's always added to the first page, the \topskip, the rule and fill up glue. What follows, that is,

..\glue(\baselineskip) 23.55556
..\hbox(6.44444+0.0)x345.0, glue set 170.0fil
...\glue 0.0 plus 1.0fil
...\OT1/cmr/m/n/10 1
...\glue 0.0 plus 1.0fil

is the footer with the page number 1 centered.

The rule is represented by

...\rule(0.4+0.0)x*

meaning exactly what I described at the beginning: the width is determined by the (vertical) box the rule ends up in.

Note that \hrule is a vertical command, so it ends the paragraph being typeset; TeX adds no interline glue before and after the rule.

You can try

\hbox{aaa}
\hrule
\hbox{bbb}

instead, getting

enter image description here

because the box width is determined by the widest box inside. Since no paragraph is started, the rule ends up with the same width as the bottom \hbox.

TeX primitives are very peculiar, aren't they?

egreg
  • 1,121,712