summaryrefslogtreecommitdiff
path: root/Master/texmf-doc/doc/english/FAQ-en/html/FAQ-spinmacro.html
blob: 1f75263bada38744140bffd6f759a9e779659f56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<head>
<title>UK TeX FAQ -- question label spinmacro</title>
</head><body>
<h3>Spaces in macros</h3>
<p>It&rsquo;s very easy to write macros that produce space in the typeset
output where it&rsquo;s neither desired nor expected.  Spaces introduced by
macros are particularly insidious because they don&rsquo;t amalgamate with
spaces around the macro (unlike consecutive spaces that you
type), so your output can have a single bloated space that proves
to be made up of two or even more spaces that haven&rsquo;t amalgamated.
And of course, your output can also have a space where none was wanted
at all.
<p>Spaces are produced, inside a macro as elsewhere, by space or tab
characters, or by end-of-line characters.  There are two basic rules
to remember when writing a macro: first, the rules for ignoring spaces
when you&rsquo;re typing macros are just the same as the rules that apply
when you&rsquo;re typing ordinary text, and second, rules for ignoring
spaces do <em>not</em> apply to spaces produced while a macro is being
obeyed (&ldquo;expanded&rdquo;).
<p>Spaces are ignored in vertical mode (between paragraphs), at the
beginning of a line, and after a command name.  Since sequences of
spaces are collapsed into one, it &lsquo;feels as if&rsquo; spaces are ignored if
they follow another space.  Space can have syntactic meaning after
certain sorts of non-braced arguments (e.g., <em>count</em> and
<em>dimen</em> variable assignments in Plain TeX) and after certain
control words (e.g., in <code>\</code><code>hbox</code> <code>to</code>, so again we have instances
where it &lsquo;feels as if&rsquo; spaces are being ignored when they&rsquo;re merely
working quietly for their living.
<p>Consider the following macro, fairly faithfully adapted from one that
appeared on <i>comp.text.tex</i>:

<blockquote>
<pre>
\newcommand{\stline}[1]{ \bigskip \makebox[2cm]{ \textbf{#1} } }
</pre>
</blockquote><p>
The macro definition contains five spaces:
<ul>
<li> after the opening <code>{</code> of the macro body; this space will be
  ignored, not because &ldquo;because the macro appears at the start of a
  line&rdquo;, but rather because the macro was designed to operate between
  paragraphs
<li> after <code>\</code><code>bigskip</code>; this space will be ignored (while the macro
  is being defined) because it follows a command name
<li> after the <code>{</code> of the mandatory argument of <code>\</code><code>makebox</code>; even
  though this space will inevitably appear at the start of an output
  line, it will <em>not</em> be ignored
<li> after the <code>}</code> closing the argument of <code>\</code><code>textbf</code>; this space
  will not be ignored, but may be overlooked if the argument is well
  within the <code>2cm</code> allowed for it
<li> after the <code>}</code> closing the mandatory argument of <code>\</code><code>makebox</code>;
  this space will not be ignored
</ul>
The original author of the macro had been concerned that the starts of
his lines with this macro in them were not at the left margin, and
that the text appearing after the macro wasn&rsquo;t always properly
aligned.  These problems arose from the space at the start of the
mandatory argument of <code>\</code><code>makebox</code> and the space immediately after the
same argument.  He had written his macro in that way to emphasise the
meaning of its various parts; unfortunately the meaning was rather
lost in the problems the macro caused.
<p>The principal technique for suppressing spaces is the use of
<code>%</code> characters: everything after a
<code>%</code> is ignored, even the end of line itself (so
that not even the end of line can contribute an unwanted space).  The
secondary technique is to ensure that the end of line is preceded by a
command name (since the end of line behaves like a space, it will be
ignored following a command name).  Thus the above command would be
written (by an experienced programmer with a similar eye to
emphasising the structure):
<blockquote>
<pre>
\newcommand{\stline}[1]{%
  \bigskip
  \makebox[2cm]{%
    \textbf{#1}\relax
  }%
}
</pre>
</blockquote><p>
Care has been taken to ensure that every space in the revised
definition is ignored, so none appears in the output.  The revised
definition takes the &ldquo;belt and braces&rdquo; approach, explicitly dealing
with every line ending (although, as noted above, a space introduced
at the end of the first line of the macro would have been ignored in
actual use of the macro.  This is the best technique, in fact &mdash; it&rsquo;s
easier to blindly suppress spaces than to analyse at every point
whether you actually need to.  Three techniques were used to suppress
spaces:
<ul>
<li> placing a <code>%</code> character at the end of a line
  (as in the 1st, 3rd and 5th lines),
<li> ending a line &lsquo;naturally&rsquo; with a control sequence, as in line 2,
  and
<li> ending a line with an &lsquo;artificial&rsquo; control sequence, as in line
  4; the control sequence in this case (<code>\</code><code>relax</code>) is a no-op in many
  circumstances (as here), but this usage is deprecated &mdash; a
  <code>%</code> character would have been better.
</ul>
Beware of the (common) temptation to place a space <em>before</em> a
<code>%</code> character: if you do this you might as well omit
the <code>%</code> altogether.
<p>In &ldquo;real life&rdquo;, of course, the spaces that appear in macros are far
more cryptic than those in the example above.  The most common spaces
arise from unprotected line ends, and this is an error that
occasionally appears even in macros written by the most accomplished
programmers.
<p><p>This question on the Web: <a href="http://www.tex.ac.uk/cgi-bin/texfaq2html?label=spinmacro">http://www.tex.ac.uk/cgi-bin/texfaq2html?label=spinmacro</a>
</body>