Thursday, August 13, 2009

LaTeX Macros...

So here are some LaTeX3 macros I've found or written that are pretty useful. This post covers the following packages I've written/patched together:

  • Bourbaki inspired dangerous bend environments
  • Macros for underbrackets and overbrackets, similar to underbrace and overbrace
  • Misner, Thorne, and Wheeler type equations
  • Exercises and Answers in the style of the TeXbook
  • Style like the TeXbook in LaTeX macros

Addendum (9:30 AM (PST) 15 December 2011): I have modified the danger.sty code, and it is now more robust. For more macros, see my Notebk's wiki page for others and documentation.

Dangerous Bends!

Bourbaki used Dangerous Bend symbols to indicate some tricky reasoning. Knuth used this too in his TeX book, among other places.

I too use it in my notes...but I use it as an environment. It's safer this way ;) At any rate the code is contained a file danger.sty, reproduced below:

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{danger}[2009/08/06 Danger and Double Danger Environments]

\usepackage{manfnt}
% or if manfnt is unavailable, uncomment the next two lines
%\font\manual=manfnt
%\def\dbend{{\manual\char127}} % dangerous bend sign

%%
% This macro header is what controls the ``dangerous bend''
% paragraph
%%

% Danger, Will Robinson!
\newenvironment{danger}{\medbreak\noindent\hangindent=2pc\hangafter=-2%
  \clubpenalty=10000%
  \hbox to0pt{\hskip-\hangindent\dbend\hfill}\small\ignorespaces}%
  {\medbreak\par}

% Danger! Danger!
\newenvironment{ddanger}{\medbreak\noindent\hangindent=3pc\hangafter=-2%
  \clubpenalty=10000%
  \hbox to0pt{\hskip-\hangindent\dbend\kern2pt\dbend\hfill}\small\ignorespaces}%
  {\medbreak\par}

The above code is just literally cut/paste from Knuth's TeXbook macros. On the other hand, in LaTeX a better implementation might be:

\font\manual=manfnt
\def\dbend{{\manual\char127}} % dangerous bend sign

% Danger, Will Robinson!
\newenvironment{danger}{\medbreak\noindent\hangindent=2pc\hangafter=-2%
  \clubpenalty=10000%
  \hbox to0pt{\hskip-\hangindent\dbend\hfill}\small\ignorespaces}%
  {\medbreak\par}

% Danger! Danger!
\newenvironment{ddanger}{\medbreak\noindent\hangindent=3pc\hangafter=-2%
  \clubpenalty=10000%
  \hbox to0pt{\hskip-\hangindent\dbend\kern2pt\dbend\hfill}\small\ignorespaces}%
  {\medbreak\par}

Underbrackets and Overbrackets

In math mode, you can use underbrace and overbrace, but there are no corresponding brackets macros. This is sad, because I'm more fond of brackets than I am of braces.

So I fiddled around and pieced together the brackets.sty file:

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{brackets}[2009/08/06 Overbracket and Underbracket racket]

\makeatletter
\def\overbracket{\@ifnextchar [ {\@overbracket} {\@overbracket
[\@bracketheight]}}
\def\@overbracket[#1]{\@ifnextchar [ {\@over@bracket[#1]}
{\@over@bracket[#1][0.3em]}}
\def\@over@bracket[#1][#2]#3{%\message {Overbracket: #1,#2,#3}
\mathop {\vbox {\m@th \ialign {##\crcr \noalign {\kern 3\p@
\nointerlineskip }\downbracketfill {#1}{#2}
                              \crcr \noalign {\kern 3\p@ }
                              \crcr  $!\hfil$ \displaystyle {#3}\hfil $%
                              \crcr} }}\limits}
\def\downbracketfill#1#2{$!\m@th$ \setbox \z@ \hbox {$!\braceld$$}
                  \edef\@bracketheight{\the\ht\z@}\downbracketend{#1}{#2}
                  \leaders \vrule \@height #1 \@depth \z@ \hfill
                  \leaders \vrule \@height #1 \@depth \z@ \hfill
\downbracketend{#1}{#2}$}
\def\downbracketend#1#2{\vrule depth #2 width #1\relax}


\def\underbracket{%
  \@ifnextchar[{\@underbracket}{\@underbracket [\@bracketheight]}%
}
\def\@underbracket[#1]{%
  \@ifnextchar[{\@under@bracket[#1]}{\@under@bracket[#1][0.4em]}%
}
\def\@under@bracket[#1][#2]#3{%\message {Underbracket: #1,#2,#3}
 \mathop{\vtop{\m@th \ialign {##\crcr $!\hfil$ \displaystyle {#3}\hfil $!$%
 \crcr \noalign {\kern 3\p@ \nointerlineskip }\upbracketfill {#1}{#2}
       \crcr \noalign {\kern 3\p@ }}}}\limits}
\def\upbracketfill#1#2{$!\m@th$ \setbox \z@ \hbox {$!$\braceld$!$}
                    \edef\@bracketheight{\the\ht\z@}\bracketend{#1}{#2}
                    \leaders \vrule \@height #1 \@depth \z@ \hfill
                    \leaders \vrule \@height #1 \@depth \z@ \hfill \bracketend
               {#1}{#2}$}
\def\bracketend#1#2{\vrule height #2 width #1\relax}
\makeatother


% Makes limits on sums and integrals pretty
\def\mathllap{\mathpalette\mathllapinternal}
\def\mathllapinternal#1#2{\llap{$\mathsurround=0pt#1{#2}$}}
\def\clap#1{\hbox to 0pt{\hss#1\hss}}
\def\mathclap{\mathpalette\mathclapinternal}
\def\mathclapinternal#1#2{\clap{$\mathsurround=0pt#1{#2}$}}
\def\mathrlap{\mathpalette\mathrlapinternal}
\def\mathrlapinternal#1#2{\rlap{$\mathsurround=0pt#1{#2}$}}

The other part of the code, which % Makes limits pretty, allows stuff to be written on top of the sum's limits. It's taken from Voss's math mode notes.

Equations with Misner, Thorne and Wheeler type Arrows

This is going to be a bit harder to explain (it's one of those "You have to have seen it to understand what I'm talking about" type situations). So look at page 139, equation 5.15a for example. Note the arrows pointing to the terms in the equation? Yeah, I'd like to do that in LaTeX, but how?

Unfortunately you have to use the picture environment (or, at least, that's the only way I know how to do it!). Consider the following example document:

\documentclass{amsart}
\usepackage{brackets}

\newlength\textwidthcm
\textwidthcm=.03514598035146\textwidth

\begin{document}
{\catcode`p=12 \catcode`t=12 \gdef\cm#1pt{#1cm}}
{\catcode`p=12 \catcode`t=12 \gdef\dimensionless#1pt{#1}}

\begin{equation}\label{eq:one}
E=mc^{2}
\end{equation}


\setlength{\unitlength}{1cm}
\begin{picture}(\expandafter\dimensionless\the\textwidthcm, 2.5)(0,0)
  \linethickness{0.5pt}
  \put(5,1.5){$\displaystyle Z[0]=\underbracket[0.25pt]{\int ~\mathcal{D}\phi\;\;\; }
               \!\!\!\exp(\int\mathcal{L}d^{4}x)$}
  \put(-.4,1.5){\refstepcounter{equation}{(\arabic{equation})\label{eq:four}}}
  \put(6.75,0.55){\vector(0,1){0.4}}
  \put(6.75,0.55){\line(1,0){1.4}}
  \put(8.15,0.5){\makebox{$\begin{pmatrix}
                        $!sum$$\ 
                        $!over$$\\ 
                        $!histories$$
                        \end{pmatrix}$}}
\end{picture}
Woah what is eq \eqref{eq:four} again? Don't forget the text width is \the\textwidth ~or 
equivalently \expandafter\cm\the\textwidthcm ~or 
\expandafter\dimensionless\the\textwidthcm
\end{document}

This produces the following text:

The only disadvantage is that for each equation you want to do, you have to do this by hand.

Exercises and Answers Macros From The TeXbook

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{exercises}[2009/08/06 LaTeX version of exercise macros from the TeXbook]
%%%%%%
% Options: number within either the chapter or the part
%          default is to number the exercises/answers via sections
%%%%%%%%
\newif\if@dump
\@dumpfalse
\newif\if@section
\newif\if@ch@pter
\newif\if@p@rt
\@sectiontrue\@ch@pterfalse\@p@rtfalse
\DeclareOption{chapter}{\@sectionfalse\@ch@pterfalse\@p@rtfalse}
\DeclareOption{part}{}
\def\dump@nswer{0}
\DeclareOption{dump}{\@dumptrue}
\ProcessOptions\relax

\usepackage{manfnt}


\newcounter{sectionCtr}
\newcounter{exno}
\setcounter{exno}{0}


\refstepcounter{sectionCtr}
\if@section
\newcommand{\upd@teCtr}{\ifnum \value{sectionCtr}=\value{section}%
\refstepcounter{exno}\else\setcounter{exno}{1}\setcounter{sectionCtr}{\value{section}}\fi}
\else\if@ch@pter%
\newcommand{\upd@teCtr}{\ifnum \value{sectionCtr}=\value{chapter}
\refstepcounter{exno}\else\setcounter{exno}{1}\setcounter{sectionCtr}{\value{chapter}}\fi}
\else\if@p@rt%
\newcommand{\upd@teCtr}{\ifnum \value{sectionCtr}=\value{part}%
\refstepcounter{exno}\else\setcounter{exno}{1}\setcounter{sectionCtr}{\value{part}}\fi}
\else\@sectiontrue\setcounter{exno}{1}\setcounter{sectionCtr}{\value{section}}
\newcommand{\upd@teCtr}{\ifnum \value{sectionCtr}=\value{section}%
\refstepcounter{exno}\else\setcounter{exno}{1}\setcounter{sectionCtr}{\value{section}}\fi}
\fi\fi\fi

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Exercise Environment
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% well, to make it an environment, one would instead do the following:
% \newenviornment{exercise}{\medbreak\upd@teCtr%
%  \noindent\llap{\mantriangleright\kern.15em}% triangle in margin
%  \small{\textbf{EXERCISE \thesection.\arabic{exno}}}\\%
%  \noindent}{}
% that is, stuff the command into an environment
\newcommand{\exercise}{\medbreak\upd@teCtr%
  \noindent\llap{\mantriangleright\kern.15em}% triangle in margin
  \small{\textbf{EXERCISE \thesection.\arabic{exno}}}\\%
  \noindent}
\newcommand{\dexercise}{\medbreak\upd@teCtr%
  \noindent\llap{\mantriangleright\kern.15em}% triangle in margin
  \small{\textbf{EXERCISE \arabic{sectionCtr}.\arabic{exno}}}\\%
  \noindent}
\newcommand{\dangerexercise}{\dbend \dexercise}
\newcommand{\ddangerexercise}{\dbend\dbend \dexercise}


% formatting macro
\if@dump
  \def\ansno#1.#2:{\medbreak\noindent%
    \hbox to\parindent{\bf\hss(Answer to #1.#2)\enspace}\ignorespaces}
\else
  \def\ansno#1.#2:{\medbreak\noindent%
    \hbox to \parindent{\bf\hss #1.#2.\enspace}\ignorespaces}
\fi

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Answers Command
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\if@dump % if we are dumping the answers directly where they're placed
  \def\ans{} % ans is defined as nothing
  \newcommand{\answer}[1]{\par\medbreak % \answer simply
      \ansno\arabic{sectionCtr}.\arabic{exno}: \\% prints directly
      #1} % out when it's called 
  \newcommand{\dumpanswers}{} % \dumpanswers is empty
\else % else we are dumping it into a file
  \newwrite\ans%
  \immediate\openout\ans=answers % file for answers to exercises
  \newcommand{\answer}[1]{\par\medbreak
    \immediate\write\ans{}%
    \immediate\write\ans{\string\ansno\arabic{sectionCtr}.\arabic{exno}:}%
    \immediate\write\ans{ \detokenize{#1}}}
  \newcommand{\dumpanswers}{\immediate\closeout\ans\input{answers}}
\fi

One could easily turn the exercises command into an environment, but it'd be trickier to turn the \answer command into an environment. The \answer spits out all the answers to a file answers.tex which can be included at the end of the main document.

To write the answers, one should call the \dumpanswers command in its own section/chapter. It does everything necessary to include the answers in the document.

The Poor Man's TeXbook Style

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{TeXbook}[2009/08/06 Poor man's \TeX{}book style for \LaTeX]

% the following is the TeXbook's exact specifications
%\usepackage[textheight=38pc,headsep=10pc,top=16pc,%
% textwidth=30pc,inner=6pc,marginparwidth=8pc,marginparsep=1cm]{geometry}
% the following is OUR preferred specifications!
\usepackage[top=6pc,textwidth=30pc,inner=6pc,%
marginparwidth=10pc,marginparsep=1cm]{geometry}
\normalbaselineskip=12pt
\baselineskip=12pt
\abovedisplayskip=6pt plus 3pt minus 1pt
\belowdisplayskip=6pt plus 3pt minus 1pt
\abovedisplayshortskip=0pt plus 3pt
\belowdisplayshortskip=4pt plus 3pt

\usepackage{fancyhdr,marginnote}

\pagestyle{fancy}
\if@twoside
\fancyhead[LE,RO]{\thepage}
\fancyheadoffset[OR,EL]{8pc}
\else
\fancyhead[L]{\S\thesection~\nouppercase{\rightmark}}
\fancyhead[R]{\thepage}
\fancyheadoffset[R]{8pc}
\renewcommand{\sectionmark}[1]{\markboth{}{#1}}
\fi
\cfoot{}
\renewcommand{\headrulewidth}{0.4pt}

\if@twoside
\renewcommand\marginpar[1]{\-\marginnote{\footnotesize{\emph{#1}}}}
\else
\renewcommand\marginpar[1]{\-\marginnote{\raggedright\footnotesize{\emph{#1}}}}%
\fi

This has a decent sized margin, the header is also slightly extended. It's really just a poor man's TeXbook style file, using the exact specifications from the manmac.tex macros file that is freely available from CTAN.

Note that the style file is not exactly as the TeXbook specifies, I thought the \headsep was too large. The textwidth and placement from the inner margin are the same, the marginparwidth is slightly larger so one can write annotations in the margins (I love using \marginpar).

I'm writing up some notes on slice and comma categories, as well as adjoint functors, so sit tight while I polish them up in the next couple of days...

No comments:

Post a Comment