18

I've been playing around with dropcaps in LaTeX (with the yfonts and lettrine packages), and one typographical effect you often see after dropcaps is having the entire first line of the paragraph typeset in small caps. It's clear how to get this effect by trial and error—run LaTeX, see what's on the first line, \textsc that, rerun LaTeX, see what's moved, and re-\textsc the appropriate text—but that's a royal pain, and it's too easy to forget to do. Is there a good way to get (La)TeX to detect the location of linebreaks in its typeset output? I presume I'd have to run LaTeX at least twice, since things could change mid-processing, but such is life with LaTeX.


Edit 1: I need this to work for math-mode ($...$) code as well—from the solutions so far suggested, this is not necessarily non-trivial.

Caramdir
  • 89,023
  • 26
  • 255
  • 291

3 Answers3

14

Donald Arseneau's magaz package will do this for you. From memory, it uses roughly the same idea shown by Yiannis — that is, only a single pass is necessary — but I think it may be slightly more robust.

This solution will work with inline maths provided the maths does not break over the end of the line, as here:

\documentclass{article}
\usepackage{magaz}
\begin{document}
\FirstLine{There is no just \emph{ground}, therefore, $a+b=c$ for the charge $x\in\{0,1,2\}$ brought against me by certain ignoramuses.}
\end{document}

But putting the maths inside an \mbox seems to fix this problem.


Readers of this answer may wish to select a color for the first line. This requires a slightly different approach which is discussed in David Carlisle's answer in the thread Why does color meant for first typeset line ONLY (with package magaz) affect ENTIRE document?

  • This seems really nice—it parses the entire paragraph, which should let it do more optimal line-break detection—but it doesn't work. If I feed it the lorem ipsum paragraph, I get a "Bad text for \FirstLine" error; if I feed it just a fragment (less than a line) of it, said fragment gets deleted and the rest is typeset. Have you ever had any luck using magaz? – Antal Spector-Zabusky Oct 14 '10 at 23:43
  • By the lipsum text, do you mean \lipsum[1]? That might not work because it ends with a \par. I'll try the package out myself later today. – Will Robertson Oct 14 '10 at 23:54
  • Sorry, I should have been clearer; I mean the literal text \FirstLine{Lorem ipsum dolor sit amet, … mollit anim id est laborum.} (except with the full text instead of the …, but I don't think that's quite necessary in this comment :-) ). It's odd behavior, that's for sure—I'm going to see if I can isolate it to a weird package interaction. – Antal Spector-Zabusky Oct 15 '10 at 00:01
  • 3
    Well, that was faster than it had any right to be, and easier too—magaz and pdfsync don't play nice together. Removing pdfsync made everything work. The hyphenation is slightly different than manual-small-capitalization, but it's only off by something like half a word. It looks like the only remaining problem is integrating it with dropcaps, which should be doable. – Antal Spector-Zabusky Oct 15 '10 at 00:09
  • Good to hear. You shouldn't need the pdfsync package any more; for a couple of years now the various TeX engines all have SyncTeX support, which does it automatically behind the scenes. – Will Robertson Oct 15 '10 at 02:48
  • 1
    @Will Robertson: I compiled your example and got the piece "for the charge" twice. Strange! – Hendrik Vogt Oct 16 '10 at 11:30
  • @Hendrik — That was my point: if the maths would normally break then things screw up. Haven't looked into why this happens, though. – Will Robertson Oct 16 '10 at 14:23
  • I just realized I hadn't accepted your answer! I'm sorry about that—it was exactly what I wanted. – Antal Spector-Zabusky Oct 27 '10 at 07:27
  • 1
    @Antal Were you able to get magaz to play nicely with lettrine? I am trying to get initial capitals + first line small capitals, but it appears that \FirstLine gets tripped up by the initial capital, and winds up applying the special formatting to too much text. – Aaron Mar 06 '11 at 06:31
  • @Aaron: In the end, I scrubbed the whole thing, so I'm afraid I won't be much help, sorry. – Antal Spector-Zabusky Apr 29 '11 at 19:39
11

Here is a TeXie solution!

    \documentclass[11pt]{article} 
    \begin{document}

    \def\firstline{\par\begingroup\Firstlinefont
      \def\zzz{}\dimen0\parindent
      \setbox0=\hbox{ }\advance\dimen0by-\wd0
      \x}
    \def\x{\afterassignment\y\z}
    \def\z#1 {\xdef\zz{#1\ }}
    \def\y{\setbox0=\hbox{\zz}
      \advance\dimen0 by\wd0
      \ifdim\dimen0<\hsize\let\next=\x
        \edef\zzz{\zzz\zz}
      \else\let\next=\endgroup
        \leavevmode\zzz\unskip\break\aftergroup\zz
      \fi
      \next}


    \let\Firstlinefont=\scshape  

    \firstline The first line of this paragraph is in small caps font series. You
    will need to hack the rest of the code to get it working with the lettrine package!

\end{document}
yannisl
  • 117,160
  • Clever! I like it. – TH. Oct 14 '10 at 23:09
  • Thanks for this! I just plugged this into my document, and it mostly works, except for a couple of things. First: running it with lorem ipsum text yields suboptimal results for the first line. Since this just grabs words and sets them, it can't do any reflowing; thus, the first line is awkwardly widely spaced compared to a hand-tuned solution (which can fit an extra word). I don't know if there's a way around this, though Second: this chokes on math text, and while I can read your code, I don't know if I could modify it :-) Do you know if it'd be possible to support that? Again, thanks. – Antal Spector-Zabusky Oct 14 '10 at 23:40
  • After Will's suggestion I had a look at http://ftp.riken.go.jp/pub/CTAN/macros/latex/contrib/magaz/magaz.sty I did not try it but perhaps you should give it a go. Problem with my code it will not do hyphenation. What you are looking for is not easy:) – yannisl Oct 14 '10 at 23:53
  • 1
    Very elegant! but it fails to compile when the paragraph is shorter than a line ;-) (try with \firstline The first line of this paragraph). I shamelessly point this out because I had the same problem with the first version of my answer and it took me some toil to fix it! –  May 03 '11 at 07:12
  • @jfbu Thanks I would have a look! Donald Arseneau's code is the best, as it iterates 3-4 times to get everything right! – yannisl May 04 '11 at 16:12
5

(I came to this from the duplicate question Emphasize first line of paragraph in LaTeX)

Yiannis solution is very nice. Here is another method, which leads to less visual differences between the first two lines in the way the inter-word spaces are treated. My code presumably leads to inferior results in general compared to Yiannis's (the emphasizing can extend to the beginning of the second line or end a bit too short in the first line), but I do propose it as it is simpler minded than Yiannis's sophisticated macros! Also it seems to work with the example including inline mathematics, and allows hyphenation at the end of the first line (but the emphasizing applies to entire words).

Inline math should be written (whenever there is a chance it will belong to the emphasized text) either without spaces (e.g. $a+b=c$) or be enclosed in doubled braces (e.g. {{$ a + b = c $}}). Then, breaking at the end of lines will work correctly.

The code defines two user commands \decorate and \Decorate (as well as other commands to decide the style of the emphasized text). \decorate is used as \decorate{TEXT} (where TEXT cannot contain a \par token), and \Decorate is to be put at the beginning of a paragraph (so can't be used in a \parbox for example, contrarily to the lowercase form).

Both admit an optional parameter (default value 0.95) which gives a rough idea of the number of lines to which the emphasizing will be applied.

And \Decorate has a starred version \Decorate* which tries to provoke expansion of the paragraph to which it is applied (see the end of the code for a comparative illustration). It is not possible though to use \lipsum[1] as an argument (even with option nopar to package lipsum), but lipsum@i is ok.

\documentclass[a4paper]{article}
\makeatletter

\def\addtobufferwithaspace#1#2{\expandafter\def\expandafter#1%
               \expandafter{#1 #2}}

\def\deco@step#1{%
   \setbox1=\hbox{\deco@buffer{} #1}%
   \dimen0\hsize\advance\dimen0-\parindent\relax
   #1
   \ifdim\wd1>\deco@scale\dimen0
     \expandafter\deco@trail
   \else
     \addtobufferwithaspace\deco@buffer{#1}%
     \expandafter\deco@parsei
   \fi
}

\def\deco@trail#1\@nil{\deemphasizingcommand #1}

\def\deco@parsei#1{\ifnot@nil{#1}{\deco@parse #1}}

\def\deco@parse #1 {\deco@step{#1}}

\newcommand*{\decorate}[2][.95]{%
   \def\deco@scale{#1}%
   \def\deco@buffer{\emphasizingcommand}%
   \emphasizingcommand
   \deco@parse #2 \@nil
   \deemphasizingcommand
}

\def\@@Decorate[#1] #2\par{\decorate[#1]{#2}\par}

\def\@@eDecorate[#1] #2\par{%
     \def\@decorate{\decorate[#1]}%
     \edef\@Decorated{\noexpand\@decorate{#2}}%
     \@Decorated\par}

\newcommand*\@Decorate[1][.95]{\@@Decorate[#1] }
\newcommand*\@eDecorate[1][.95]{\@@eDecorate[#1] }

\newcommand*\Decorate{\@ifstar{\@eDecorate}{\@Decorate}}

\makeatother

\newcommand{\emphasizingcommand}{\bfseries} 
\newcommand{\deemphasizingcommand}{\normalfont\normalsize} 
\usepackage[nopar]{lipsum}

\begin{document}

\Decorate
  I am (of course) shocked! and appalled! I have a particular typesetting
  task, described below. Trying to find out how to emphasize the line of text
  automatically. The issue here is that I have no idea where the line would
  break.  Ideally it would be start paragraph with slanted shape and then
  revert to upright shape upon first line break.  

\Decorate[.5] I am (of course) shocked! and appalled! I have a particular
  typesetting task, described below. Trying to find out how to emphasize the
  line of text automatically.

\renewcommand{\emphasizingcommand}{\bfseries\slshape}

\noindent\parbox{5cm}{\decorate{
  I am (of course) shocked! and appalled! I have a particular typesetting
  task, described below. Trying to find out how to emphasize the line of text
  automatically. The issue here is that I have no idea where the line would
  break.  }}
\parbox{3cm}{\decorate{
  I am (of course) shocked! and appalled! I have a particular typesetting
  task, described below. Trying to find out how to emphasize the line of text
  automatically. The issue here is that I have no idea where the line would
  break.  }}
\parbox{2.5cm}{\raggedright\decorate{
  I am (of course) shocked! and appalled! I have a particular typesetting
  task, described below. Trying to find out how to emphasize the line of text
  automatically. The issue here is that I have no idea where the line would
  break.  }}
\parbox{2.5cm}{\raggedleft\decorate{
  I am (of course) shocked! and appalled! I have a particular typesetting
  task, described below. Trying to find out how to emphasize the line of text
  automatically. The issue here is that I have no idea where the line would
  break.  }}

\renewcommand{\emphasizingcommand}{\ttfamily\Large\frenchspacing}
\renewcommand{\deemphasizingcommand}{\normalfont\normalsize\nonfrenchspacing}

\begin{center}
  \begin{minipage}{0.5\linewidth}
    \centering
    \Decorate[1.5] 
    I am (of course) shocked! and appalled! I have a
    particular typesetting task, described below. Trying to find out how to
    emphasize the line of text automatically. The issue here is that I have no
    idea where the line would break.  Ideally it would be start paragraph with
    slanted shape and then revert to upright shape upon first line break.
    \par
  \end{minipage}
\end{center}

\renewcommand{\emphasizingcommand}{\scshape}

\Decorate There is no just \emph{ground}, therefore, \mbox{$ a + b = c $} for
  the charge $x\in\{0,1,2\}$ brought against me by certain ignoramuses $ x
  \in\{ 0,1,2 \}$.

\Decorate Lorem ipsum dolor sit amet, consectetuer
adipiscing elit. Ut purus elit, vestibulum ut, placerat ac,
adipiscing vitae, felis. Curabitur dictum gravida mauris. Nam arcu
libero, nonummy eget, consectetuer id, vulputate a, magna.

\Decorate[4] Lorem ipsum dolor sit amet, consectetuer
adipiscing elit. Ut purus elit, vestibulum ut, placerat ac,
adipiscing vitae, felis. Curabitur dictum gravida mauris. Nam arcu
libero, nonummy eget, consectetuer id, vulputate a, magna.


\renewcommand{\emphasizingcommand}{\bfseries}
%% \clearpage

\decorate{Let's try with  a short sentence.}
\decorate[.2]{And another one.}
\decorate[.2]{And another one.}
\decorate[.2]{And another one.}

\makeatletter

\Decorate* \lipsum@v

\Decorate* \lipsum@vi

\Decorate*[1] \lipsum@vii

\makeatother

\def\tmpa{dolor sit amet, consectetuer
adipiscing elit. Ut purus elit, }

\Decorate[.1] \tmpa \tmpa

\Decorate*[.1] \tmpa \tmpa

\end{document}
  • Regarding inline math, $ a + b = c $, or more generally any space inbetween the two $, will make decorate choke; but the fix is simply to add braces: {$ a + b = c $}. No need here for an mbox. Also, the braces are needed only for the math which will belong to the first line or the very beginning of the second... –  Apr 29 '11 at 20:41
  • I have edited my answer, as the previous version was faulty in case of an argument shorter than a (typeset) line. Inline math which will end up in the first line should be typed either without spaces ($a+b=c$) or enclosed in an \mbox (contrarily to my previous comment, with the new version braces are not enough). –  Apr 30 '11 at 10:05
  • I again edited my answer, this time to add the \Decorate form which is more convenient to use in the source. I also added a starred variant which tries to expand its argument before formatting; this is not always usable, but does help sometimes. See the code and its output. –  Apr 30 '11 at 17:50
  • Regarding inline mathematics, in fact no \mbox is necessary: but one should use doubled braces like {{$ a + b = c$}}, or as mentioned before write up the code without any space $a+b=c$. –  May 01 '11 at 21:42