9

I would like a command \lineseprule that appears as a horizontal line of customizable width. It should neither take up a full line's height (\linesepruleA below) nor close up the lines above and below (in a way that ascender and descender height affect the spacing between the surrounding lines; \linesepruleB below). Instead it should simply insert between the lines, as if it were its own very thin line.

illustration with shopping list

The vertical spacing for \linesepB depends on ascenders and descenders: dependence on ascenders and descenders

\documentclass{article}
\usepackage{chancery}

\parindent0pt % disablement of paragraph indentation

\newcommand*{\linesepruleA}[1]{\par \rule{#1}{.4pt}\par}
\newcommand*{\linesepruleB}[1]{\par \hrule width#1 height.4pt}


\begin{document}

{\large\underline{Shopping list}}
\bigskip

toilet paper \par
kitchen rolls \par
detergent \par
\linesepruleA{4em} % too high
toothbrush \par
toothpaste \par
\linesepruleB{4em} % see below
milk \par
cereals \par


\vspace{2\baselineskip}

\hrulefill\par
{\small\verb|The vertical spacing for \linesepruleB depends on ascenders and descenders:|}

\medskip

a \par
\linesepruleB{4em} % much too close
o \par

\medskip

g \par
\linesepruleB{4em} % still too close
b \par

\end{document}

A clarification: I was making an assumption about lines having specific top and bottom boundaries. A meaningful interpretation of my question is: (1) Either pick a meaningful placement (e.g., place the horizontal rule in the middle of "half-x-height above the first row's baseline" and "half-x-height above the second row's baseline" or (2) let the user customize it with a parameter that lets the user pick something like the vertical distance below the first row's baseline or the vertical deviation from the default described in (1) above.

Addendum to clarification: Martin Scharrer tells us that \ht\strutbox and \dp\strutbox are .7\baselineskip and .3\baselineskip, respectively.

(Steven B. Segletes has written a solution covering all I had in mind, using the default of .7\baselineskip above the lower line's baseline.)

  • 1
    How about \newcommand*{\lineseprule}[1][4em]{\smallbreak\hrule width #1\smallskip}? – Thruston Dec 15 '13 at 13:53
  • @Thruston It looks close to what I need, but the vertical spacing is a bit too large. Btw, the answer by user Steven B. Segletes solves my problem and is impressive. – Lover of Structure Dec 27 '13 at 21:55
2
+50

This approach uses the stackengine package to place a \rule above the baseline by an amount. The rule length is the mandatory argument, the rule elevation is the optional argument (default .7\baselineskip) The rule is smashed to take up zero height and, using stackengine facilities, has zero width as well.

Per the OP's request I EDITED the solution to do two things: 1) provide a macro to set the rule thickness; and 2) have the optional argument indicate the center (not the bottom) of the rule. The third request of the OP, to increase the line spacing, based on the rule thickness, has been added, using a new macro \lineaddrule, rather than \lineseprule (which handles the first two cases). These two macros are similar enough that one could set up a parameter to do one thing or the other in a single macro, rather than setting up two separate macros.

\documentclass{article}
\usepackage{chancery}
\usepackage{stackengine}
\newlength\rulethickness
\newcommand\setlineseprule[1][.2pt]{%
  \setlength\rulethickness{#1}}
\setlineseprule
\newcommand\lineseprule[2][.7\baselineskip]{%
  \def\useanchorwidth{T}\def\stackalignment{l}\def\stacktype{L}%
  \hspace{0pt}\smash{\stackon[#1]{}{%
  \rule[-.5\rulethickness]{#2}{\rulethickness}}}%
  \ignorespaces}
\newcommand\lineaddrule[2][.7\baselineskip]{%
  \def\useanchorwidth{T}\def\stackalignment{l}\def\stacktype{L}%
  \vspace{\rulethickness}%
  \hspace{0pt}\smash{\stackon[#1]{}{%
  \rule{#2}{\rulethickness}}}%
  \ignorespaces}
\parindent0pt % disablement of paragraph indentation
\begin{document}
{\large\underline{Shopping list}}
\bigskip

toilet paper \par
kitchen rolls \par
detergent \par
\lineseprule{4em}
toothbrush \par
toothpaste \par
\lineseprule{4em}
milk \par
cereals \par
\vspace{2\baselineskip}

\hrulefill\par
{\small\verb|The vertical spacing for \lineseprule can be adjusted|\\
\verb|for ascenders and descenders:|}

\medskip\setlineseprule[2pt]
a \par
\lineseprule[.7\baselineskip]{4em}
o \par\setlineseprule[12pt]
a \par
\lineaddrule[.7\baselineskip]{12em}
o \par
\medskip\setlineseprule
g \par
\lineaddrule[.57\baselineskip]{4em}
o \par
\end{document}

enter image description here

7

TeX doesn't add interline glue between a rule and a box (in either order). So \hrule is what you need:

\documentclass{article}
\usepackage{chancery}

\setlength{\parindent}{0pt} % disable paragraph indentation
\newlength{\linesepskip}
\setlength{\linesepskip}{1pt} % adjust to suit

\newcommand*{\linesep}[1]{%
  \par\nobreak\vspace{\linesepskip}
  \hrule width #1 height 0.2pt depth 0.2pt\relax
  \nobreak\vspace{\linesepskip}
}

\begin{document}

{\large\underline{Shopping list}}
\bigskip

toilet paper \par
kitchen rolls \par
detergent \par
\linesep{4em}
toothbrush \par
toothpaste \par
\linesep{4em} % see below
milk \par
cereals \par

\medskip

a \par
\linesep{4em}
o \par

\medskip

g \par
\linesep{4em}
b \par

\end{document}

enter image description here


If you want not to disable the interlineskip computations, a different definition must be used.

\documentclass{article}
\usepackage{chancery}

\setlength{\parindent}{0pt} % disable paragraph indentation
\newlength{\linesepskip}
\setlength{\linesepskip}{1pt} % adjust to suit

\newcommand*{\linesep}[1]{%
  \par\nobreak
  \leaders\vrule width #1\vskip 0.4pt
  \nobreak
}

\begin{document}
\fbox{\begin{minipage}{2cm}
detergent \par
\linesep{4em}
toothbrush
\end{minipage}}
\fbox{\begin{minipage}{2cm}
detergent \par
\vspace{0.4pt}
toothbrush
\end{minipage}}

\end{document}

The second box shows the output is what you'd get by adding the rule's thickness between the paragraphs.

enter image description here

  • Thanks! What my question meant to say was that my \linesepruleB was ascender/descender-dependent, even though the ideal \lineseprule (the naming \linesep is totally fine, but I avoided it to prevent a naming conflict) should not be. The idea was that the letters "a"/"o" and "g"/"b" should have the same distance as if I had typeset them with a \par o and g \par b plus the rule's width (0.4pt, but adding your \linesepskip seems fine). – Lover of Structure Dec 15 '13 at 15:26
  • If in your code in the bottom half of your answer I replace "detergent"/"toothbrush" by "a"/"a", the horizontal line will move up to touch the "a". The distance between the respective lines/baselines will remain identical as intended, but what I was looking for was a way that would keep the horizontal line between the lettered lines, no matter which letters occur in them. (By the way, did you mean to write "want to not disable" or "want to disable" in your answer?) – Lover of Structure Dec 21 '13 at 6:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.