Sunday, January 30, 2011

Text font sizes

One of the most commonly asked questions is how to change font sizes in LaTeX beyond those offered by \tiny through \Huge. There are a number of different font parameters that can be selected using the New Font Selection Scheme. In particular, one can select the exact font size and line height (the leading). To select a 10pt font on 12pt leading, one can use
\fontsize{10}{12}%
\selectfont
Of course, 10 and 12 can be replaced with any values. Since \fontsize uses \@defaultunits (see here), units other than pt can be used.

Saturday, January 29, 2011

Knuth quote III

Here's a great one from the source code to TeX. It's the beginning of section 1154.
The simplest math formula is, of course, ‘$ $’, when no noads are generated. The next simplest cases involve a single character, e.g., ‘$x$’. Even though such cases may not seem to be very interesting, the reader can perhaps understand how happy the author was when ‘$x$’ was first properly typeset by TeX.
Being a programmer myself, I most certainly can.

A noad, by the way, is what TeX calls (most of) the elements of a math list. (It can also contain nodes, which are what appear in horizontal and vertical lists.)

Sunday, January 16, 2011

Knuth quote II

Okay, this one isn't a comment in code, yet it amuses me anyway. This is Exercise 24.1 in The TeXbook.
Can you think of a reason why you might want ‘A12’ to be a ‹hex digit› even though the letter A has category 11? (Don't worry if your answer is “no.”)
For the record, my answer was “yes.” Unfortunately, my reason wasn't correct.

Friday, January 14, 2011

Knuth quote I

Scattered throughout Knuth's programs are a number of great comments. I really enjoy encountering these and I thought I'd share them. (As I wrote in my first post, this blog is mostly a way for me to collect pieces of information. As such, I'm mostly collecting these quotes for me.)

In tex.web, line 950 is
last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
This line of code is assigning first to the variable last. You can find many versions of that verse here. The King James version is
But many [that are] first shall be last; and the last [shall be] first.

Wednesday, January 12, 2011

Better \mbox and \fbox

As currently implemented in LaTeX, \mbox and \fbox (among others) have a bizarre limitation: their arguments cannot change category codes. One practical consequence of this is that \verb is not allowed in the arguments.

This limitation is completely artificial and with a little care can be removed. To see why this limitation exists, it's helpful to take a look at the implementation of \mbox.
\long\def\mbox#1{\leavevmode\hbox{#1}}
From this, it becomes clear why category codes cannot be changed. The reason is simple; parameters to macros are tokenized so the parameter for \mbox has fixed category codes.

The fix for this is simple and has two consequences.
\def\bettermbox{\leavevmode\hbox}
Here, we see that \bettermbox takes no arguments and so \bettermbox{foo} will expand to \leavevmode\hbox{foo}. The first consequence is that the parameter is not tokenized before being executed so we are free to write
\bettermbox{\verb!&^%$#!}
The second consequence is slightly more subtle. We can give box specifications such as to 3in or spread 12pt before the left brace.

Okay, fixing \mbox was easy, but what about something more complicated like \fbox? First we need to look at its definition.
\long\def\fbox#1{%
        \leavevmode
        \setbox\@tempboxa\hbox{%
                \color@begingroup
                \kern\fboxsep
                {#1}%
                \kern\fboxsep
                \color@endgroup
        }%
        \@frameb@x\relax
}
The actual framing of the box happens in \@frameb@x. Again, the parameter is tokenized when it need not be. Unfortunately, this time, it's not immediately obvious how to proceed. The trick is to use \afterassignment to insert code just after the opening brace (and before the tokens from \everyhbox, if any, are inserted) and then to use \aftergroup to close the box and typeset it using \@frameb@x.

Here is the code.
\def\betterfbox{%
        \leavevmode
        \afterassignment\bfb@i
        \setbox\@tempboxa\hbox
}
\def\bfb@i{%
        \color@begingroup
        \kern\fboxsep
        \bgroup
        \aftergroup\bfb@ii
}
\def\bfb@ii{%
        \kern\fboxsep
        \color@endgroup
        \egroup
        \@frameb@x\relax
}
If we expand this all out, we see that \betterfbox{foo} becomes
\leavevmode
\setbox\@tempboxa\hbox{%
        \color@begingroup
        \kern\fboxsep
        \bgroup
        foo}%
        \kern\fboxsep
        \color@endgroup
\egroup
\@frameb@x\relax
The only difference between that and \fbox is the braces for the \hbox are { \egroup and the braces around foo are \bgroup } whereas for \fbox they are all explicit brace tokens.

So did the LaTeX team make the right choice? I'm not sure. The original definitions are certainly clearer. A general rule of thumb I try to follow when writing TeX code that others might use is to delay tokenization as long as possible.

As a final point, this is much easier to do with environments than macros because the code that ends the box can just go in the \endfoo macro. LaTeX makes extensive use of this.

Tuesday, January 11, 2011

A simpler .dtx template

Two things that annoyed me with making LaTeX packages using a .dtx file were the duplication of the copyright/license info and that nearly every line in the file was commented out. About the only thing that wasn't commented out was a small batch file that generated the output.

For the most part, both of those annoyances are unnecessary. The following is a simple template file for making a .sty file from a .dtx. Almost every place that the name of the package would appear has been replaced with \jobname. The exceptions are in the license at the top of the file (I am not a lawyer and so I'd rather not give an opinion on what it means to claim that \jobname.dtx and \jobname.sty are covered by the license) and then near the end where the SVN keyword Id has been expanded out.
% \iffalse The license starting three lines down applies to this file
%<*batchfile>
{\obeylines\obeyspaces \gdef\thepreamble{
Copyright (C) 2011 by YOUR NAME

This file may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either
version 1.3c of this license or (at your option) any later
version.  The latest version of this license is in:

    http://www.latex-project.org/lppl.txt

and version 1.3c or later is part of all distributions of
LaTeX version 2005/12/01 or later.

This work has the LPPL maintenance status 'maintained'.

The Current Maintainer of this work is YOUR NAME.

This work consists of THISFILE.dtx and the derived file
THISFILE.sty.
}}
\begingroup
\input docstrip
\keepsilent
\usedir{tex/latex/\jobname}
\expandafter\preamble\thepreamble\endpreamble
\askforoverwritefalse
\generate{\file{\jobname.sty}{\from{\jobname.dtx}{}}}
\endgroup
\documentclass{ltxdoc}
\usepackage{\jobname}
\usepackage[margin=1.5in]{geometry}
\usepackage[pdfborder={0 0 0}]{hyperref}

\CheckSum{0}
\CharacterTable
 {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
  Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
  Digits        \0\1\2\3\4\5\6\7\8\9
  Exclamation   \!     Double quote  \"     Hash (number) \#
  Dollar        \$     Percent       \%     Ampersand     \&
  Acute accent  \'     Left paren    \(     Right paren   \)
  Asterisk      \*     Plus          \+     Comma         \,
  Minus         \-     Point         \.     Solidus       \/
  Colon         \:     Semicolon     \;     Less than     \<
  Equals        \=     Greater than  \>     Question mark \?
  Commercial at \@     Left bracket  \[     Backslash     \\
  Right bracket \]     Circumflex    \^     Underscore    \_
  Grave accent  \`     Left brace    \{     Vertical bar  \|
  Right brace   \}     Tilde         \~}

\DoNotIndex{\def}

\EnableCrossrefs
\CodelineIndex
\RecordChanges
\GetFileInfo{\jobname.sty}
\title{The \textsf{\jobname} package\thanks{This document
corresponds to \textsf{\jobname}~\fileversion, dated \filedate.}}
\author{YOUR NAME\\\texttt{YOU@YOUR.ADDRESS}}

\begin{document}
\maketitle

\phantomsection
\addcontentsline{toc}{section}{\abstractname}
\begin{abstract}
The \textsf{\jobname} package XXX.
\end{abstract}

\phantomsection
\addcontentsline{toc}{section}{\contentsname}
\tableofcontents

\section{Introduction}
The \textsf{\jobname} package XXX

\section{Usage}
XXX

\StopEventually{
        \typeout{**************************************************}
        \typeout{*}
        \typeout{* To finish the installation, you have to move the}
        \typeout{* following file into a directory searched by TeX:}
        \typeout{*}
        \typeout{* \space\space \jobname.sty}
        \typeout{*}
        \typeout{* Documentation is in \jobname.\ifpdf pdf\else dvi\fi.}
        \typeout{*}
        \typeout{* Happy TeXing!}
        \typeout{**************************************************}
        \end{document}
}
\clearpage
\DocInput{\jobname.dtx}
\clearpage
\phantomsection
\addcontentsline{toc}{section}{Change History}
\PrintChanges
\phantomsection
\addcontentsline{toc}{section}{Index}
\PrintIndex
\Finale
%</batchfile>
% \fi
%
% \section{Implementation}
% XXX This is the only part of the file where the main text is written
% with leading comments.
%
% \changes{v1.0}{2011/01/09}{Initial version}
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\RequirePackage{svn-prov}
\ProvidesPackageSVN
        {$Id: example.dtx 1 2011-01-11 07:21:05Z TH $}
        [v1.0 \revinfo\ SHORT DESCRIPTION.]

% YOUR PACKAGE CONTENTS HERE.
\endinput
%    \end{macrocode}
% \endinput
A quick description of how this works. It first saves the copyright/license text into a macro \thepreamble. Then the code between the begin and end group use docstrip to create \jobname.sty from \jobname.dtx. This works by stripping out all lines that start with comments and all lines between %<*batchfile> and %</batchfile> prepending the preamble text. So what results is the copyright/license text and the actual code of the package.

After \endgroup, we have the standard LaTeX documentation class, packages to use, the check sum, character, etc. that are normally used with the doc/ltxdoc package/class.

If the implementation is not going to be typeset, the code in \StopEventually will run, outputting some instruction. Otherwise, \DocInput{\jobname.dtx} executes. This causes the .dtx file to be input, but this time, % is ignored. If we look at the top of the file, there is an % \iffalse and just after the </batchfile> is the matching % \fi. Thus, all of that will be skipped by TeX.

And that brings us to the only part of the code that is prefixed with comments: the implementation documentation. As usual, the code appears between %    \begin{macrocode} and %    \end{macrocode}. Finally, the input is finished by % \endinput. After this, you can put something like
% vim: set ts=4 sts=4 expandtab:
which will be ignored by docstrip because it starts with a comment and by \DocInput because of the \endinput just before it.

After \DocInput is finished, this prints the change history and the index. Lastly, \Finale expands to the argument of \StopEventually, ending the document.

If you name the file example.dtx, it can be compiled as follows.
$ pdflatex example.dtx
$ makeindex -s gglo -o example.gls example.glo
$ makeindex -s gind example
$ pdflatex example.dtx
$ pdflatex example.dtx
Happy TeXing!

Friday, January 7, 2011

Center last line in a paragraph

I'm not totally sure why one would want to center the last line in a paragraph, but the excellent TeX by Topic provides a surprising solution.
\leftskip=0pt plus.5fil
\rightskip=0pt plus-.5fil
\parfillskip=0pt plus1fil
The reason this works is that for all lines except for the last, the amount of stretch in the line is 0, so no skips are inserted. In the last line, the addition of the \parfillskip gives a skip of .5fil on the left and right so the line is centered.

Sunday, January 2, 2011

Counting the number of lines in a file

The simplest way to count the number of lines in a file seems to be to use the ε-TeX primitive \readline. (One could probably get away with using the TeX primitive \read instead, but that reads lines according to the current catcodes set. Also, the code is slightly more complicated since we cannot use \unless without ε-TeX.)
\newread\lf
\newcount\linecount
\newcommand\linesinfile[1]{%
        \linecount-1
        \openin\lf#1
        \unless\ifeof\lf
                \loop\unless\ifeof\lf
                        \readline\lf to\lfline
                        \advance\linecount by1
                \repeat
                \closein\lf
        \fi
}
If the file does not exist, \linecount will be -1. Otherwise, it'll contain the number of lines in the file.