Wiki: TeX

Your best resource for TeX is the TeXBook, particularly chapter 20 ("Definitions (also called Macros)") and Appendix D ("Dirty Tricks"). Appendix B provides a list of almost all macros defined at startup.

The reference for plain TeX at tug.org is also a good resource.

Basics

Differences from Plain TeX

The TeX language on the site is very similar to Knuth's plain TeX, with a few small modifications:

Looping over a string

The following code loops over all tokens until \relax, replacing all - tokens with (DASH)

\def\f#1{\ifx#1\relax%
    \let\n\relax%
\else%
    \let\n\f%
    \ifx#1- (DASH)%
    \else #1%
    \fi%
\fi\n}

\f 0-185186-70-\relax

Spaces

Space characters can be annoying to manage. Important spacing rules:

Math operations

Math can be performed in counters. Define a counter with \newcount, and print the value with \the.

\newcount\x
\x=15  % equivalent to the following line
\x15   % (the equals sign is optional)
\the\x % prints 15 as two tokens, "1" then "5"

Counters are 32-bit signed integers. Operations that overflow cause the program to instantly halt with no output.

\x\y            % x = y
\advance\x5     % x += 5
\advance\x by\y % equivalent to the following line
\advance\x\y    % x += y (the "by" text is optional)
\advance\x-\y   % x += -y
\multiply\x\y   % x *= y
\divide\x\y     % x /= y (floor divide)

There is no modulo operator. Modulo can be calculated (if you must) using the definition x % y = x - x / y * y, where x/y is floor division

% d = x - x % y, x = x % y (requires an extra counter)
\d\x\divide\d\y\multiply\d\y\advance\x-\d

Or modulo can be computed by repeated subtraction, assuming x and y are positive.

% x = x % y (slow)
\loop\ifnum\x>\y\advance\x-\y\repeat

ASCII conversions

Convert a char code to corresponding character with \char: \char97 gives the token a.

Convert a character to char code with a backtick: \number`a gives the two tokens 97, and \newcount\x\x=`a assigns 97 as the value of the counter \x.

Golfing

One-byte macro ending

If a macro you define takes an argument longer than one token, you might be tempted to use curly braces. However, \def can allow for a single end character, saving one byte per usage.

\def\f#1{something #1 something}
\f{123}\f{456}
% compare
\def\f#1;{something #1 something}
\f123;\f456;

\let

Commonly-used macros can be aliased with \let

\newcount\a\newcount\b\newcount\c
% compare
\let\N\newcount\N\a\N\b\N\c

At the top of a long solution, you might see a block of \lets like \let\N\newcount\let\I\ifnum\let\A\advance

Tilde is active

Tilde (~) is an active character (\catcode`\~=\active), so you can use it in lieu of one control sequences.

\let\N\newcount\N\a\N\b\N\c
% compare
\let~\newcount~\a~\b~\c

Form Feed

Form-feed (0x0c) is an active character (like tilde ~) defined as \par (\catcode`\^^L=\active \outer\def^^L{\par}). It is "outer," so you can only use it outside of constructs such as definitions and loops.

Form-feed can be typed in the editor by typing "0c" while holding down the Alt key.

1\par2\par3
% compare
1

2

3
% compare
1•2•3

Repeated macro vs loop

Repeating a macro several times is often shorter than a loop.

\newcount\i\loop\ifnum10>\i\the\i,\advance\i1\repeat
% compare (though kinda cheating because it uses ~)
\newcount\i\def~{\the\i\advance\i1,}~~~~~~~~~~

Newline inside loop

\newcount\i\loop\ifnum10>\i\the\i\endgraf\advance\i1\repeat
% compare
\newcount\i\def\f{\ifnum10>\i\the\i\advance\i1

\f\fi}\f

The recursive approach saves 3 bytes.