CSS

Showing posts with label macros. Show all posts
Showing posts with label macros. Show all posts

Saturday, November 27, 2021

ISO-2145 numbering in Plain TeX

I've been writing terse notes using something like the ISO-2145 standard. Could some TeX macros be written to support writing such notes? Of course!

Like amsart's subsections and subsubsections, I wanted my sections to be "runin style" (i.e., an unindented paragraph with a leading number, possibly with some label in bold, which is separated by vertical space from the previous paragraph). Following Knuth's WEB macros, I use \M to create a new unlabeled "section", and \N{label} to create a new labeled "section". These macros increment the section number, makes the section number (and label, if present) in bold, and does not indent the section's first paragraph.

But I wanted to allow arbitrary depths for "section numbers". What I did was treat the section number like a stack. When I wanted to work on a new subsection level, I call \M[1] (or, for labeled subsections, \N[1]{My label for the new subsection.}).

If I want to "ascend" back to the parent section, I call \M[-1] (and \N[-1]{...}) which will pop the section stack, then increment the top of the stack.

Should I want to move more than one level up or down, I simply call \M[n] (or \N[n]{...}) for any nonzero integer n. If called with n=0, then it's treated as \M (and \N{...}, resp.).

Retrospective

If I were to do this all over again, I would probably use different variable names (for example, I would probably use \chunkctr instead of \section for the counter name). But I just wanted to see if it was possible.

Also, this code could work in LaTeX, but needs some small modifications. (Well, mostly dealing with making \chunkctr a bona fide counter, so \refstepcounter could use its magic for referencing things properly.)

I guess if I wanted to be fully general, I would have some additional parameters to allow customizing the vertical spacing for separating the sections, the horizontal space between the section number and the next symbol, etc.

Code and Worked Example

\newcount\section
\section=0

% technically, sectionDepth is not needed, but it's to avoid popping off
% "too many sections"
\newcount\sectionDepth \sectionDepth=0

% \secprefix will be redefined to append the current section number
% followed by a period
\def\secprefix{}

% \pushSection simply appends "\the\section." to \secprefix's current value
\def\pushSection{
  \global\advance\sectionDepth by1
  \let\sectmp\secprefix
  \xdef\secprefix{\sectmp\the\section.}
}

% update \secprefix from "a.b.(...).c.d" to "a.b.(...).c"
% and set \section to "d" (as a number)
\def\popSection{
  \def\newPrefix{}
  \global\advance\sectionDepth by-1
  \def\updatePrefix##1.##2\endUpdate{
    \ifx\relax##2 % if we are at the last number
      % globally set \secprefix to be the leading (n-1) section numbers
      \xdef\secprefix{\newPrefix}
      % globally set \section to be the last section number from \secprefix
      \global\section=\number##1
    \else
      \xdef\newPrefix{\newPrefix##1.}
      \updatePrefix##2\endUpdate
    \fi}
  \ifx\secprefix\relax % if \secprefix is empty
  \else
    \expandafter\updatePrefix\secprefix\relax\endUpdate
  \fi
}

\def\thesection{\secprefix\the\section.}
\def\stepSec{\global\advance\section by1}

\def\downOne{
  \pushSection
  \global\section=0
}

\def\upOne{
  \popSection
}

\newcount\secIter \secIter=0

% \up ascends back to one of the parent sections, ascending #1 levels
\def\up#1{ % #1 is a negative integer
  \ifnum\sectionDepth>0%
    \secIter=#1%
    \multiply\secIter by-1
    % but \sectionDepth is a non-negative integer, so transform it
    \ifnum\secIter>\sectionDepth%
      \global\secIter=\sectionDepth
    \fi%
    \loop
      \ifnum\secIter>0
      \upOne
      \advance\secIter by-1
    \repeat%
  \fi%
}

% down appends #1 subsections to the given section number
\def\down#1{ % #1 is a positive integer
  \global\secIter=#1%
  \loop
    \ifnum\secIter>0
    \downOne
    \advance\secIter by-1
  \repeat%
}

% move up or down #1 layers, does nothing if #1 is zero
\def\adjustSection#1{\ifnum#1<0\up{#1}\else{\ifnum#1>0\down{#1}\fi}\fi}

% \M is used for unlabeled paragraphs
\def\Mlabel{\medbreak\noindent\ignorespaces%
  {\bf\thesection\ignorespaces}\enspace\ignorespaces}
\def\Mnone{\stepSec\Mlabel}
\def\Mmany[#1]{\adjustSection{#1}\Mnone}
\def\xM{\ifx\tmp[\expandafter\Mmany\else\Mnone\fi}
\def\M{\futurelet\tmp\xM}

% \N is used for labeled paragraphs
\def\Nlabel#1{\medbreak\noindent\ignorespaces%
  {\bf\thesection\ignorespaces\enspace#1\ignorespaces}\enspace\ignorespaces}
\def\Nnone#1{\stepSec\Nlabel{#1}}
\def\Nmany[#1]#2{\adjustSection{#1}\Nnone{#2}}
\def\xN{\ifx\tmp[\expandafter\Nmany\else\Nnone\fi}
\def\N{\futurelet\tmp\xN}

\M
This is a test to see if this works.

\M I hope it works.

\M[1]
And this should be \S{2.1}, I hope.

\N[1]{Claim:} This should be \S{2.1.1}.

\M[-1]
This should be \S{2.2}.

\M[3]
This should be \S{2.2.0.0.1}, I hope?

\N[-3]{Theorem.}%
This is \S3, yes?

\M[-1]
No, this is \S3.

\bye

Addendum: in LaTeX

It turns out to be a straightforward generalization to LaTeX:

\documentclass{article}
\usepackage{fullpage}
\newcounter{chunk}

\def\setSection#1{\setcounter{chunk}{#1}}
\def\stepSec{\refstepcounter{chunk}}

% technically, sectionDepth is not needed, but it's to avoid popping off
% "too many sections"
\newcount\sectionDepth \sectionDepth=0

% \secprefix will be redefined to append the current section number
% followed by a period
\def\secprefix{}
\renewcommand\thechunk{\secprefix\arabic{chunk}.}

% \pushSection simply appends "\arabic{chunk}." to \secprefix's current value
\def\pushSection{
  \global\advance\sectionDepth by1
  \let\sectmp\secprefix
  \xdef\secprefix{\sectmp\arabic{chunk}.}
}

% update \secprefix from "a.b.(...).c.d" to "a.b.(...).c"
% and set \chunk counter to "d" (as a number)
\def\popSection{
  \def\newPrefix{}
  \global\advance\sectionDepth by-1
  \def\updatePrefix##1.##2\endUpdate{
    \ifx\relax##2 % if we are at the last number
      % globally set \secprefix to be the leading (n-1) section numbers
      \xdef\secprefix{\newPrefix}
      % globally set \chunk to be the last section number from \secprefix
      \setSection{\number##1}
    \else
      \xdef\newPrefix{\newPrefix##1.}
      \updatePrefix##2\endUpdate
    \fi}
  \ifx\secprefix\relax % if \secprefix is empty
  \else
    \expandafter\updatePrefix\secprefix\relax\endUpdate
  \fi
}

\def\downOne{\pushSection\setSection{0}}

\def\upOne{\popSection}

\newcount\secIter \secIter=0

% \up ascends back to one of the parent sections, ascending #1 levels
\def\up#1{ % #1 is a negative integer
  \ifnum\sectionDepth>0%
    \secIter=#1%
    % but \sectionDepth is a non-negative integer, so transform it
    \multiply\secIter by-1
    \ifnum\secIter>\sectionDepth%
      \global\secIter=\sectionDepth
    \fi%
    \loop
      \ifnum\secIter>0
      \upOne
      \advance\secIter by-1
    \repeat%
  \fi%
}

% down appends #1 subsections to the given section number
\def\down#1{ % #1 is a positive integer
  \global\secIter=#1%
  \loop
    \ifnum\secIter>0
    \downOne
    \advance\secIter by-1
  \repeat%
}
\def\adjustSection#1{\ifnum#1<0\up{#1}\else{\ifnum#1>0\down{#1}\fi}\fi}

%% \M is used for unlabeled paragraphs
\newcommand\M[1][0]{\adjustSection{#1}\medbreak%
  \stepSec\noindent\ignorespaces%
  \textbf{\thechunk\ignorespaces}\enspace\ignorespaces}

%% \N is used for labeled paragraphs
\newcommand\N[2][0]{\adjustSection{#1}\medbreak%
  \stepSec\noindent\ignorespaces%
  \textbf{\thechunk\ignorespaces\enspace#2\ignorespaces}\enspace\ignorespaces}

\begin{document}

\M
This is a test to see if this works.

\M I hope it works.

\M[1]
And this should be \S{2.1}, I hope.

\N[1]{Claim:} This should be \S{2.1.1}.

\M[-1]
This should be \S{2.2}.

\M[3]
This should be \S{2.2.0.0.1}, I hope?

\N[-3]{Theorem.}%
This is \S3, yes?

\M[-1]
No, this is \S3.

\M[0] This should be \S4.

\N[0]{Corollary.} This is \S5?
\end{document}

Friday, March 16, 2012

End notes and Foot notes in LaTeX

So I was writing up notes for a reading group on Afghanistan, and it has apparently become fashionable to use endnotes in the humanities. Being fond of Edward Gibbon, I use footnotes excessively. Irritating everyone, I use both while making it indistinguishable whether I refer to a footnote or endnote by a superscripted number.

How to do this in LaTeX? Quite simple:

\documentclass{article}

\usepackage{endnotes}

\makeatletter
\newcommand*{\dupcntr}[2]{%
    \expandafter\let\csname c@#1\expandafter\endcsname\csname c@#2\endcsname
}
\dupcntr{endnote}{footnote}
\renewcommand\theendnote{\thefootnote}
\makeatother

\begin{document}
Blah blah blah.
\end{document}

It turns out to work quite well.

I modified some macros from a TeX Stackexchange discussion on "slave counters"...so I get only partial credit.

Thursday, December 15, 2011

Basic Physics Macros

Continuing from my post LaTeX Macros for Personal Notes, I'd like to discuss some macros for physics.

I am using the "ISEE" approach to tackling examples, where we have four major steps:

  1. "Identify" what do we have and what are we looking for?
  2. "Set Up" what are the relevant concepts and equations? Set up the equations.
  3. "Execute" Carry out the scratch work
  4. "Evaluate" Look back, reflect, what were the key points and key ideas?

We are working with a lot of examples, and the examples are long (compared to math!). So we need to indicate when the examples are done.

Following Euclid, we introduce a \qefsymbol which is used at the end of examples and constructions. This is done just as QED is used at the end of proofs.

I will use the amsthm package.

\usepackage{amsthm}

\theoremstyle{plain}
\newtheorem{thm}{Theorem}[chapter]
\newtheorem{prop}[thm]{Proposition}

\theoremstyle{definition}
\newtheorem{defn}[thm]{Definition}
\newtheorem{ex}[thm]{Example}
\newtheorem{fact}{Experimental Fact}
\newtheorem{prob}[thm]{Problem}
\newtheorem{construction}[thm]{Construction}
\newtheorem{con}[thm]{Conjecture}
\newtheorem*{notation}{Notation}
\newtheorem*{assume}{Assumption}
\newtheorem*{quest}{Question}

\theoremstyle{remark}
\newtheorem{rmk}[thm]{Remark}
\newtheorem{sch}[thm]{Scholium}

\newcommand\qefsymbol{\ensuremath\blacksquare}
%{\ensuremath\triangle} % perhaps \ensuremath\triangle if one prefers...

\makeatletter
\newenvironment{example}{\begin{ex} %
  \let\qedsymbol\qefsymbol % this is a temporary "let"
  \pushQED{\qed}}%
  {\popQED\@endpefalse\end{ex}}

\newenvironment{construct}%
  {\begin{construction}\pushQED{\qed}}%
  {\popQED\end{construction}}
\makeatother

Now, to keep track of which step of ISEE we are at, I'd like to introduce the following code:

\font\manual=manfnt

\newcommand\identify{\noindent\llap{\manual\char'170\rm\kern.5em}\textbf{Identify:}}
\newcommand\setup{\noindent\llap{\manual\char'170\rm\kern.5em}\textbf{Set up:}}
\newcommand\execute{\noindent\llap{\manual\char'170\rm\kern.5em}\textbf{Execute:}}
\newcommand\evaluate{\noindent\llap{\manual\char'170\rm\kern.5em}\textbf{Evaluate:}}

There are other matters to discuss, like units and so forth, which I'll tackle next time...

LaTeX Macros for Personal Notes

So last time, I discussed the notion of personal mathematical notes (as opposed to expository mathematical notes) and would like to discuss some LaTeX macros which enable writing personal notes.

The basic scheme is to write in "chunks" (to borrow a term from literate programming). We've all seen examples of this, Bagchi and Wells refer to it as "labeled style" in their paper Varieties of Mathematical Prose

But each "chunk" is a self-contained concept, example, discussion, etc.

For a good example of this writing style, see On Euler's Footsteps.

LaTeX Code

I am taking CWEB's style. So, the code listing I have is as follows:

% chunk.sty
\ProvidesPackage{chunk}[2011/12/15 Cunking commands for personal notes]
\makeatletter

\@ifundefined{@addpunct}{
  \def\@addpunct#1{\ifnum\spacefactor>\@m \else#1\fi}
  }{}

\newcounter{chunk@ctr}

\newcommand\M{\medbreak\noindent%
  \refstepcounter{chunk@ctr}%
  \textbf{\thechunk@ctr\@addpunct{.}}\quad\ignorespaces}

% deprecated macro:
% \newcommand\N[1]{\M\textbf{#1\@addpunct{.}}\quad\ignorespaces}

% superior implementation:

\def\N{\@ifstar
        \NStar%
        \NNoStar%
}
\def\NStar#1{\medbreak\noindent\textbf{#1\@addpunct{.}\quad}\ignorespaces}
\def\NNoStar#1{\M\textbf{#1\@addpunct{.}\quad}\ignorespaces}

% permits writing \N*{Un-numbered chunk} for a chunk
% without a numeric label!

\makeatother
% end of cunk.sty

Note that it is completely self-contained code, and you do not need amsgen package. If you already loaded it, then no worries!

Each chunk is numbered. We use \M for unlabeled chunks, and \N{My favorite chunk!} for labeled chunks (which is labeled "My favorite chunk!").

So lets write up some example usage:

\documentclass{article}
\usepackage{chunk} % make it in the same directory
% or put it in ~/texmf/tex/latex/ and run "sudo texhash"
\title{Example Notes}
\author{Alex Nelson}
\date{\today}
\begin{document}
\maketitle

\N{Introduction}
Today we will solve all the problems in the universe. 

\M Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna 
aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis 
aute irure dolor in reprehenderit in voluptate velit esse 
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat 
cupidatat non proident, sunt in culpa qui officia deserunt 
mollit anim id est laborum.

\N{Conclusion?} Nobel Prize please!

\end{document}

As far as bugs, I don't think there are any...it's too minimalistic!

To Do

The chunk counter is rather minimalistic, and doesn't count within any section. This has to be changed by hand if the user wants to use these macros and number chunks within each chapter...

In the time honored tradition of mathematicians, this exercise is left for the reader!

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...