Handy TeX macros

In the time that I've been working with TeX and LaTeX, I've amassed a small collection of very useful and neat helper macros. This page highlights the ones that could actually be useful to others.

1. Embedding PDF documents as thumbnails

This macro includes all pages of a PDF file into the TeX document, placing them in a \hbox two at a time, with a horizontal gap of \columnsep. It keeps writing hboxes until the PDF runs out. The vertical space between the hboxes is set to \columnsep plus 1000pt min 0pt to space them out equally in the vertical. A \vfil \columnsep plus 2fil minus 0pt at the end prevents a sparsely spaced last page.

thumbnailpdf.txt

\def\thumbnailpdf#1{%
    \pdfximage{#1}%
    \newcount\pagenum%
    \newcount\totalpages%
    \pagenum=0%
    \totalpages=\pdflastximagepages%
    \loop%
        \hbox to \hsize{%
            \advance\hsize by -\columnsep%
            \divide\hsize by 2%
            \global\advance\pagenum by 1%
            \ifnum\pagenum<\totalpages%
                \pdfximage width \hsize page \pagenum {#1}%
                \pdfrefximage\pdflastximage%
            \fi%
            \hfil%
            \global\advance\pagenum by 1%
             \ifnum\pagenum<\totalpages%
                \pdfximage width \hsize page \pagenum {#1}%
                \pdfrefximage\pdflastximage%
            \fi%
        }%
        \vskip \columnsep plus 1000pt minus 0pt%
    \ifnum\pagenum<\totalpages\repeat%
    \vskip \columnsep plus 2fil minus 0pt%
}

Usage

\thumbnailpdf{mypdf.pdf}

Output

(Not available yet)

2. Easy typesetting of English dates

This macro creates a complete date from just a month and a day. It also chooses the right superscript for the day and raises it automatically. Not the coolest TeX macro in the world, but it saves time.

endate.txt

\def\endate#1#2{%
    \ifcase#1%            Translate month number to name
        \or January %
        \or February %
        \or March %
        \or April %
        \or May %
        \or June %
        \or July %
        \or August %
        \or September %
        \or October %
        \or November %
        \or December %
    \fi%
    #2%                   Print day number
    \raise 1bp%           Raise the superscript by 1bp
    \hbox{%               Box to contain superscript
        \ifcase#2%        Output the correct superscript:
            \or st%        1st
            \or nd%        2nd
            \or rd%        3rd
            \or th%        4th
            \or th%        5th
            \or th%        6th
            \or th%        7th
            \or th%        8th
            \or th%        9th
            \or th%       10th
            \or th%       11th
            \or th%       12th
            \or th%       13th
            \or th%       14th
            \or th%       15th
            \or th%       16th
            \or th%       17th
            \or th%       18th
            \or th%       19th
            \or th%       20th
            \or st%       21st
            \or nd%       22nd
            \or rd%       23rd
            \or th%       24th
            \or th%       25th
            \or th%       26th
            \or th%       27th
            \or th%       28th
            \or th%       29th
            \or th%       30th
            \or st%       31st
        \fi%
    }%
}

Usage

\endate{3}{1}, \endate{12}{24}

Output

Example output

3. Text in a grey box

This code first creates a \vbox with a margin of \columnsep on all sides, and the paragraph in it. Then it creates a second box, with its only content a \hrule of the exact same height, depth and width as the first box. The colour of the \hrule is set by a raw \pdfliteral command, in this case to light grey. Then the width of this box is set to zero, and it is written out just before the paragraph box. In effect the paragraph box is superimposed on top of the second box, giving it a coloured background.

Experimenting with the r g b values (which can range from 0 to 1) in the first \pdfliteral statement gives you different colours.

greybox.txt

\long\def\greybox#1{%
    \newbox\contentbox%
    \newbox\bkgdbox%
    \setbox\contentbox\hbox to \hsize{%
        \vtop{
            \kern\columnsep
            \hbox to \hsize{%
                \kern\columnsep%
                \advance\hsize by -2\columnsep%
                \setlength{\textwidth}{\hsize}%
                \vbox{
                    \parskip=\baselineskip
                    \parindent=0bp
                    #1
                }%
                \kern\columnsep%
            }%
            \kern\columnsep%
        }%
    }%
    \setbox\bkgdbox\vbox{
        \pdfliteral{0.85 0.85 0.85 rg}
        \hrule width  \wd\contentbox %
               height \ht\contentbox %
               depth  \dp\contentbox
        \pdfliteral{0 0 0 rg}
    }%
    \wd\bkgdbox=0bp%
    \vbox{\hbox to \hsize{\box\bkgdbox\box\contentbox}}%
    \vskip\baselineskip%
}

Usage

\greybox{Some paragraphs...}

Output

Example output

4. Line-filling

This macro fits a given line of text exactly into the width given in \dimen0. It does this by rendering a line of text in a known font size of 1000, then seeing how large the containing box becomes, and then calculating the font enlargement factor that would fit the text on the line. Then the text is output with exactly that font size.

fitbox.txt

\def\fitbox#1{%
    \font\custfont=phvr scaled 1000%      define a Helvetica Regular font of known size
    \setbox0=\hbox{\custfont #1}%         render our text in that font
    \dimen0=5cm%                          the target width
    \dimen1=\wd0%                         the observed width
    \divide\dimen1 by 1000%               normalize
    \divide\dimen0\dimen1%                dimen0 becomes the font enlargement factor
    \count0=\dimen0%                      convert dimen to a count
    \font\custfont=phvr scaled \count0%   redefine the font
    \hbox{\custfont #1}%                  render the box again, this time for real
}

Usage

\fitbox{This text fits.}
\fitbox{This text also fits, I hope.}
\fitbox{And another text, this time a bit longer one to see if it also fits. That would be smashing.}
\fitbox{So there.}

Output

Example output