[<< wikibooks] LaTeX/Plain TeX
While you play with LaTeX macros, you will notice that it is quite limited. You may wonder how all these packages you are using every day have been implemented with so little. In fact, LaTeX is a set of Plain TeX macros and most packages use Plain TeX code. Plain TeX is much more low-level, it has much more capabilities at the cost of a steep learning curve and complex programming.
Up to a few exceptions, you can use the full Plain TeX language within a valid LaTeX document whereas the opposite is false.

== Vocabulary ==
To avoid confusion it seems necessary to explain some terms.

A group is everything after an opening brace and before the matching closing brace.
A token is a character, a control sequence, or a group.
A control sequence is anything that begins with a \. It is not printed as is, it is expanded by the TeX engine according to its type.
A command (or function or macro) is a control sequence that may expand to text, to (re)definition of control sequences, etc.
A primitive is a command that is hard coded in the TeX engine, i.e. it is not written in Plain TeX.
A register is the TeX way to handle variables. They are limited in numbers (256 for each type of register in classic TeX, 32767 in e-TeX).
A length is a control sequence that contains a length (a number followed by a unit). See Lengths.
A font is a control sequence that refers to a font file. See Fonts.
A box is an object that is made for printing. Anything that ends on the paper is a box: letters, paragraphs, pages... See Boxes.
A glue is a certain amount of space that is put between boxes when they are being concatenated.
A counter is a register containing a number. See Counters.There may be more terms, but we hope that it will do it for now.

== Catcodes ==
In TeX some characters have a special meaning that is not to print the associated glyph.
For example, \ is used to introduce a control sequence, and will not print a backslash by default.
To distinguish between different meanings of the characters, TeX splits them into category codes, or catcodes for short. There are 16 category codes in TeX.
A powerful feature of TeX is its ability to redefine the language itself, since there is a \catcode function that will let you change the category code of any characters.
However, this is not recommended, as it can make code difficult to read. Should you redefine any catcode in a class or in a style file, make sure to revert it back at the end of your file.
If you redefine catcodes in your document, make sure to do it after the preamble to prevent clashes with package loading.

=== Active characters ===
Active characters resemble macros: they are single characters that will expand before any other command.

Note that an active character needs to be directly followed by a definition, otherwise the compilation will fail.

=== Examples ===
TexinfoTexinfo uses a syntax similar to TeX with one major difference: all functions are introduced with a @ instead of a \. This is not by chance: it actually uses TeX to print the PDF version of the files.
What it basically does is inputting texinfo.tex which redefines the control sequence character. Possible implementation:

With this redefinition, the '@' should now introduce every command, while the '\' will actually print a backslash character.

ItemizeSome may find the LaTeX syntax of list environments a bit cumbersome. Here is a quick way to define a wiki-like itemize:

Dollar and mathIf you have many 'dollar' symbols to print, you may be better off to change the math shift character.

=== \makeatletter and \makeatother ===
If you have done a bit of LaTeX hacking, you must have encountered those two commands, \makeatletter and \makeatother.
In TeX the '@' character belongs to catcode 11 letters by default. It means you can use it for macro names.
LaTeX makes use of the catcode to specify a rule: all non-public, internal macros that are not supposed to be accessed by the end-user contains at least one '@' character in their name.
In the document, LaTeX changes the catcode of '@' to 12, others.
That's why when you need to access LaTeX internals, you must enclose all the commands accessing private functions with \makeatletter and \makeatother. All they do is just changing the catcode:

== Plain TeX macros ==
In Plain TeX, the primitives for macro definition make no check on possible shadowing. It's up to you to make sure you are not breaking anything.
The syntax is

You can use (almost) any sequence of character between arguments. For instance let's write a simple macro that will convert the decimal separator from point  to comma. First try:

This will print (123,4)56. We added the parentheses just to highlight the issue here. Each parameter is the shortest possible input sequence that matches the macro definition, separators included. Thus #1 matches all characters up to the first point, and #2 matches the first token only, i.e. the first character, since there is no separator after it.
Solution: add a second separator. A space may seem convenient:

As a general rule, everytime you expect several parameters with specific separators, think out the last separator. If you do not want to play with separators, then Plain TeX macros are used just as LaTeX macros (without default parameter):

=== Expanded definitions ===
TeX has another definition command: \edef, which stands for expanded def. The syntax remains the same:

The content gets expanded (but not executed, i.e. printed) at the point where \edef is used, instead of where the defined macro is used. Macro expansion is not always obvious...
Example:

Here the redefinition of \intro will have no effect on \example.

=== Global definitions ===
Definitions are limited to their scope. However it might be convenient sometimes to define a macro inside a group that remains valid outside the group, and until the end of the document. This is what we call a global definition.

You can also use the \global command with \edef.
Both commands have a shortcut:

\gdef for \global\def
\xdef for \global\edef

=== Long definitions ===
The previous definition commands would not allow you to use them over multiple paragraphs, i.e. text containing the \par command -- or double line breaks.
You can prefix the definition with the \long command to allow multi-paragraph arguments.
Example:

=== Outer definitions ===
This prefix macro prevent definitions from being used in some context. It is
useful to consolidate macros and make them less error-prone because of bad
contexts. Outer macros are meant to be used outside of any context, hence
the name.
For instance the following code will fail:

Outer macros are not allowed to appear in:

macro parameters
skipped conditional
...

=== let and futurelet ===
\let is the same as \expandafter\def\expandafter\expandafter{}. It defines a new control sequence name which is equivalent to the specified token. The token is usually another control sequence.
Note that \let will expand the token one time only, contrary to \edef which will expand recursively until no further expansion is possible.
Example:

\futurelet... works a bit differently. First, token2 is assigned to csname, then TeX processes the ... sequence. So \futurelet allows you to assign a token while using it right after.

=== Special control sequence name ===
Some macros may have a name that is not directly writable as is. This is the case of macros whose name is made up of macro names.
Example:

The last line will print a sentence depending on the \status.
This command actually does the opposite of \string which prints a control sequence name without expanding it:

=== Controlling expansion ===
\expandafter{token1}{token2} will expand token2 before token1. It is sometimes needed when token2 expansion is desired but cannot happen because of token1.

\noexpand is useful to have fine grained control over what gets expanded in an \edef. Example:

\the control sequence will let you see the content of various TeX types:

catcodes
chardef
font parameters
internal parameters
lengths
registers
...Example:

== Registers ==
Registers are kind of typed variables. They are limited in numbers, ranging from 0 to 255.
There are 6 different types:

TeX uses some registers internally, so you would be better off not using them.
List of reserved registers:

\box255 is used for the contents of a page
\count0-\count9 are used for page numberingScratch registers (freely available):

\box0-\box254
\count255
\dimen0-\dimen9
\muskip0-\muskip9
\skip0-\skip9Assign register using the '=' control character. For box registers, use the \setbox command instead.

You may use one of the following reservation macro to prevent any clash:

These macros use the following syntax: \new*.
Example:

These commands can not be used inside macros, otherwise every call to the macro would reserve another register.
You can print a register using the \the command. For counters use the \number command instead. For boxes use the \box command.

== Arithmetic ==
The arithmetic capabilities of TeX are very limited, although this base suffice to extend it to some interesting features.
The three main functions:

register may be of type count, dimen, muskip or skip. It does not make sense for box nor toks.

== Conditionals ==
The base syntax is

where \if* is one command among the following.

Example:

=== Self defined conditionals ===
You can create new conditionals (as a kind of boolean variables) with the \newif command. With this self defined conditionals you can control the output of your code in an elegant way.
The best way to illustrate the use of conditionals is through an example.
Two versions of a document must be generated. One version for group A the other one for the rest of people (i.e. not belonging to group A):
1. We use \newif to define our conditional (i.e. boolean variable).

2. In the following way we set a value (true or false) for our conditional

that is:

depending on which value we want to set in our conditional.
3. Now we can use our conditional anywhere after in an if control structure.

A full example is:

=== Case statement ===
The syntax is \ifcase \or\or...\else\fi. If number is equal to the case number, its content will be printed. Note that it starts at 0.

\else is used to specify the default case (whenever none of the previous cases have matched).

== Loops ==
The base syntax is

As always, content and true action are arbitrary TeX contents. \if* refers to any of the conditionals. Note that there is no false action, you cannot put an \else between \if* and \repeat. In some case this will be the opposite of what you want; you have to change the condition or to define a new conditional using \newif.
Example:

The above code will print TeX ten times.

== Doing nothing ==
Sometimes it may be useful to tell TeX that you want to do nothing.
There is two commands for that: \relax and \empty.
Classic example:

The \relax prevents undesired behaviour if a plus or a minus is encountered after the command.
The difference between \empty and  \relax lies in the expansion: \empty disappears after macro expansion.

== TeX characters ==

=== char ===
We can print all characters using the \char {charcode} command. The charcode is actually the byte value.
For example

Most characters correspond to the ASCII value (e.g. A-Za-z), some replace the non-printable characters from ASCII.

=== chardef and mathchardef ===
You can define control sequence to expand to a specific char. The syntax is \chardef=.
The following sequences do the same thing.

Example:

=== Font encoding map ===
We can use the above primitive to print the font encoding map.

Another version, with different fonts, one entry per line:

== Verbatim lines and spaces ==
It is rather confusing to discover (La)TeX treats all whitespace as the same type of spacing glue. Plain TeX provides some commands to preserve the spacing and newlines as you wrote it:

which means that you will probably need to combine your own verbatim environment, and your command:

and then in your tex file:

== Macros defining macros ==
This is useful in some case, for example to define language commands as explained in Multilingual versions, where the end user can write

and make sure it switches to the appropriate Babel language.
Let's define a macros that will define language commands for instance. These commands are simple: if the argument is the value of the \locale variable, then the corresponding macro prints its content directly. Otherwise, it does nothing.
Basically, what we want to do is extremely simple: define a bunch of macros like this:

In the previous snippet of code, only the \de command in going to output its content, \en and \fr will print nothing at all. That's what we want. The problem arises when you want to automate the task, or if you have a lot of languages, and you want to change the language selection. You just have to move the #1, but that's not convenient and it makes it impossible to choose the Babel language from command line. Think this out...
What we are going to do is to define the language commands dynamically following the value of the \locale variable (or any variable of your choice). Hence the use of the \equal command from the ifthen package.
Since it is hardly possible to write it in LaTeX, we will use some Plain TeX.

Another problem arises: how to define a command whose name is a variable? In most programming languages that's not possible at all. What we could be tempted to write is

It will fail for two reasons.

The two last '#1' are supposed to refer to the arguments of the new macro, but they get expanded to the \localedef macro first argument because they are in the body of that macro.
\#1 gets expanded to two tokens: '#' and '1', and the \def command will fail as it requires a valid control sequence name.The solution to problem 1 is simple: use '##1', which will expand to '#1' when the macro is executed.
For problem 2, it is a little bit tricky. It is possible to tell tex that a specific token is a control sequence. This is what the \csname...\endcsname is used for. However

will fail because it will redefine \csname to '#1', which is not what we want, then tex will encounter \endcsname, which will result in an error.
We need to delay the expansion of \def, i.e. to tell tex to expand the \csname stuff first, then to apply \def on it. There is a command for that: \expandafter{token1}{token2}. It will expand {token2} before {token1}.
Finally if we want to set language from command line, we must be able to set the \locale variable so that the one in the source code is the default value that can be overridden by the one in the command line. This can be done with \providecommand:

The final code is

And you can compile with

latex '\providecommand\locale{en}\input{mydocument.tex}'

== Notes and References ==

TeX for the Impatient, Paul W. Abrahams, Karl Berry and Kathryn A. Hargreaves