20

How can I set the width of an epigraph for automatic fitting of text inside epigraph?

I would like that the line between text and source have the same width of the above text. This in every epigraph!

Example of what I don't like:

  1. Too long a line

    \setlength{\epigraphwidth}{0.8\textwidth}
    \epigraph{All models are wrong, but some are useful.}{George E. P. Box}
    

    Too long a line

  2. Too short a line and it adds a new line that I don't like

    \epigraph{All models are wrong, but some are useful.}{George E. P. Box}
    

    enter image description here

UPDATE: the miminal source

\documentclass{book}
\usepackage[italian]{babel}

\usepackage{epigraph}
\renewcommand{\epigraphsize}{\small}

%\setlength{\epigraphwidth}{0.8\textwidth}

\renewcommand{\textflush}{flushright} \renewcommand{\sourceflush}{flushright}

\let\originalepigraph\epigraph 
\renewcommand\epigraph[2]{\originalepigraph{\textit{#1}}{\textsc{#2}}}

\begin{document}

\epigraph{All models are wrong, but some are useful.}{George E. P. Box}

\end{document}
17

Heavy surgery on the \epigraph macro seems to do what you're looking for. With the help of the varwidth package we're able to compute the real width of the text (thanks to David Carlisle for the suggestion).

\documentclass{book}
\usepackage[italian]{babel}

\usepackage{epigraph,varwidth}

\renewcommand{\epigraphsize}{\small}
\setlength{\epigraphwidth}{0.6\textwidth}
\renewcommand{\textflush}{flushright}
\renewcommand{\sourceflush}{flushright}
% A useful addition
\newcommand{\epitextfont}{\itshape}
\newcommand{\episourcefont}{\scshape}

\makeatletter
\newsavebox{\epi@textbox}
\newsavebox{\epi@sourcebox}
\newlength\epi@finalwidth
\renewcommand{\epigraph}[2]{%
  \vspace{\beforeepigraphskip}
  {\epigraphsize\begin{\epigraphflush}
   \epi@finalwidth=\z@
   \sbox\epi@textbox{%
     \varwidth{\epigraphwidth}
     \begin{\textflush}\epitextfont#1\end{\textflush}
     \endvarwidth
   }%
   \epi@finalwidth=\wd\epi@textbox
   \sbox\epi@sourcebox{%
     \varwidth{\epigraphwidth}
     \begin{\sourceflush}\episourcefont#2\end{\sourceflush}%
     \endvarwidth
   }%
   \ifdim\wd\epi@sourcebox>\epi@finalwidth 
     \epi@finalwidth=\wd\epi@sourcebox
   \fi
   \leavevmode\vbox{
     \hb@xt@\epi@finalwidth{\hfil\box\epi@textbox}
     \vskip1.75ex
     \hrule height \epigraphrule
     \vskip.75ex
     \hb@xt@\epi@finalwidth{\hfil\box\epi@sourcebox}
   }%
   \end{\epigraphflush}
   \vspace{\afterepigraphskip}}}
\makeatother

\begin{document}

\epigraph{All models are wrong, but some are useful.}{George E. P. Box}
\epigraph{All models are wrong, but some are usefull.}{George E. P. Box}
\epigraph{All models are wrong, but some are usefulll.}{George E. P. Box}
\epigraph{All models are wrong, but some are usefullll.}{George E. P. Box}
\epigraph{All models are wrong, but some are more useful.}{George E. P. Box}
\epigraph{All models are wrong, but some are more and more useful.}{George E. P. Box}

\end{document}

enter image description here

  • Unbelievable, egreg! :) – Paulo Cereda Feb 4 '13 at 14:32
13

If you want each epigraph to be the width of its line, you could just measure the width of the first argument and set the width inside your redefined epigraph command. I've loaded the calc package to do this easily. Since the measurement of the argument needs to take into account the formatting you set for the epigraph, it's better to use the correct epigraph methods for doing this. So I've created a formatting command which then is used inside a custom environment which is passed to the relevant epigraph commands.

\documentclass{book}
\usepackage[italian]{babel}

\usepackage{epigraph}
\usepackage{calc}

\newcommand{\mytextformat}{\itshape\epigraphsize}
\newenvironment{mytext}{\mytextformat}{}
\newenvironment{mysource}{\scshape\hfill}{}
\renewcommand{\textflush}{mytext} 
\renewcommand{\sourceflush}{mysource}

\let\originalepigraph\epigraph 
\renewcommand\epigraph[2]%
   {\setlength{\epigraphwidth}{\widthof{\mytextformat#1}}\originalepigraph{#1}{#2}}

\begin{document}

\epigraph{All models are wrong, but some are useful.}{George E. P. Box}

\end{document}

output of code

  • Very easy, but the width of the line is longer than the text. – Sigur Feb 3 '13 at 19:54
  • 1
    @Sigur Fixed in the edited version. – Alan Munn Feb 3 '13 at 20:19
  • If I use the new line it doesn't work \epigraph{All models are wrong,\\ but some are useful.}{George E. P. Box} – AlbertoMinetti Feb 3 '13 at 21:22
  • @tyranitar I can fix the linebreak problem, but getting the rule the right width is a difficult problem to solve if the text is set \raggedleft (which is what you need). – Alan Munn Feb 3 '13 at 21:53
  • 1
    @tyranitar The natural width of the text set \raggedleft is bigger than the actual length of the line break. So the rule will end up longer than the line. – Alan Munn Feb 3 '13 at 22:26
6

At the preamble, use this to define a command \epiline to use as \hline but with other sizes.

\newlength\epirule%
\newcommand\epiline{%
\noalign{\global\epirule\arrayrulewidth\global\arrayrulewidth 1pt}\hline%
\noalign{\global\arrayrulewidth\epirule}%
}

Here, the command \epigraph with two arguments (you don't need the package here).

\newcommand\epigraph[2]{%
\hfill\begin{tabular}{@{}r@{}}
{\small\textit{#1}}\\[.5em] \epiline%
{\small\textsc{#2}}
\end{tabular}
}

Then you can use it as

\epigraph{All models are wrong, but some are useful}{George E.\ P.\ Box}

enter image description here

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.