From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- info/impatient/tips.tex | 1011 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1011 insertions(+) create mode 100644 info/impatient/tips.tex (limited to 'info/impatient/tips.tex') diff --git a/info/impatient/tips.tex b/info/impatient/tips.tex new file mode 100644 index 0000000000..3d0f1b8b97 --- /dev/null +++ b/info/impatient/tips.tex @@ -0,0 +1,1011 @@ +% This is part of the book TeX for the Impatient. +% Copyright (C) 2003, 2014 Paul W. Abrahams, Kathryn A. Hargreaves, Karl Berry. +% See file fdl.tex for copying conditions. + +\input macros +\chapter{Tips and techniques} + +\chapterdef{tips} + +\TeX\ is a complex program that occasionally works its will in +mysterious ways. In this section we offer some tips on solving +problems that you might encounter and explain some handy techniques. + + +\section Correcting bad page breaks + +\bix^^{page breaks//bad} +Sometimes \TeX\ breaks a page right in the middle of material that you +want to keep together---for example, +a section heading and the text that follows it, +or a short list of related items. There are two ways to correct the +situation: +\ulist\compact +\li You can force the material to be kept together. +\li You can force a page break at a different place. +\endulist + +The simplest way to force \TeX\ to keep material together on a page is +to enclose the material in a vbox using the |\vbox| command \ctsref{\vbox}. +^^|\vbox//fixing page breaks with| +A vbox is ordinarily better than an hbox for this purpose because most +often the material to be kept together, +e.g., a sequence of paragraphs, will be vertical mode material. +You should +precede and follow the vbox by an implicit or explicit paragraph command +(either a blank line or |\par|); otherwise +\TeX\ may try to make the vbox part of an an adjacent paragraph. +The vbox method has an important limitation: +you can't apply it to portions of text smaller than a paragraph. + +You can sometimes keep the lines of a single paragraph together by enclosing +the paragraph in a group and assigning |\interlinepenalty| +\ctsref{\interlinepenalty} +a value of $10000$ at the start of the group (or elsewhere before the +end of the paragraph). +This method causes \TeX\ to consider page breaks within that paragraph to be +infinitely undesirable. +However, if all the page breaks that \TeX\ can find are infinitely undesirable, +it may break the page within the paragraph anyway. + +A ^|\nobreak| command (\xref{vnobreak}) +after the end of a paragraph prevents \TeX\ +from breaking the page at the following item +(unless that item happens to be a penalty of less than $10000$). +This is also the best way to prevent a page break after a heading, +since a heading usually behaves like a paragraph. +The |\nobreak| must follow the blank line or |\par| that ends +the paragraph so that \TeX\ won't treat the |\nobreak| as part of the +paragraph. +For the |\nobreak| to be effective, it must also come before +any legal breakpoint at the end of the paragraph. +The glue that \TeX\ inserts +before the next paragraph is such a breakpoint, +and so is any vertical glue that you insert explicitly after a paragraph. +Thus the |\nobreak| should usually be +the very first thing after the end of the paragraph or heading. + +You can use the ^|\eject| command \ctsref{\eject} +to force \TeX\ to break a page at a +particular place. Within a paragraph, you can use the combination +`|\vadjust{\vfill\eject}|' +\ctsref{\vadjust} +^^|\vadjust| +to force a break after the next complete output line. +The reason for preceding |\eject| by ^|\vfill| +\ctsref{\vfill} is to +get \TeX\ to fill out the page with blank space. +However, using |\eject| to fix page break problems +has a major disadvantage: +if the page boundaries in your document change, +the page breaks that you've inserted may no longer be where you want them. + +If you don't provide \TeX\ with a |\vfill| command to fill out the page +before an |\eject|, +\TeX\ redistributes the extra blank space as best it can and then usually +complains that ``an +underfull |\vbox| (badness $10000$) has occurred while |\output| is active.'' +You may encounter a similar problem with +any of the methods mentioned above for enclosing +material that you want to keep together. + +The ^|\filbreak| command \ctsref\filbreak{} +\xrdef{filbreak} +provides a way of keeping the lines of one or more paragraphs +(or other vertical mode material) together on +a page. If you enclose a paragraph in |\filbreak|s, \TeX\ will effectively +ignore the |\filbreak|s if the paragraph fits on the current page and +break the page before the first |\filbreak| if the paragraph doesn't fit. +If you put |\filbreak|s around each paragraph in a sequence of paragraphs, +like this: +{\obeylines\display{ +{\tt \\filbreak} +\ +{\tt \\filbreak} +\ +{\tt \\filbreak} +\leavevmode\indent\vdots +\ +{\tt \\filbreak} +}} +\vfil\eject +\noindent +\TeX\ will keep the lines of each paragraph together on a page. +If \TeX{} breaks a page at a |\filbreak|, it will fill the bottom of the +page with blank space. + +Sometimes you can get \TeX\ to modify the length of a page by changing +the ^|\looseness| parameter \ctsref\looseness{} for one or more paragraphs. +Setting |\looseness| negative within a paragraph causes \TeX\ to try to squeeze +the paragraph into fewer lines; setting it positive causes \TeX\ to try to +expand the paragraph into more lines. The disadvantage of changing |\looseness| +is that the interword spacing in the affected region won't be optimal. +You can get further information about \TeX's attempted line breaks by +setting |\tracingpages| (\xref\tracingpages) to $1$. + + +\section Preserving the end of a page + +Sometimes you need to modify something on a single page and you want to avoid +reprinting the entire document. If your modification doesn't +change the page length too much, there's hope. You need to fix the end +of the page so that it falls in the same place; +the methods are similar to the ones for fixing a bad page break. + +If the original end of page came between paragraphs, you can +force a page break at the same place +using any of the methods we've described above. Otherwise, +you must force \emph{both} a line break and a page break at a particular +place. If the new page is shorter than the old one, the sequence: +\csdisplay +\vadjust{\vfill\eject}\break +| +^^|\vadjust| +should do the trick. +But if the new page is longer, +the problem is far more difficult because \TeX\ has probably already +squeezed the page as tightly as it can. Your only hopes in this case are +to set ^|\looseness| \ctsref\looseness{} to a negative value, +to shorten some of the vertical skips on the page, to add some shrink to +^|\parskip| (\xref\parskip) if it was nonzero, or, as a last resort, +to decrease |\baselineskip| \ctsref{\baselineskip} ever so slightly. +^^|\baselineskip//and preserving end of page| + +\section Leaving space at the top of a page + +\null +^^{vertical space//reserving at top of page} +You can usually use the |\vskip| command \ctsref\vskip{} +to leave vertical space on a page. +That doesn't work at the top of a page, however, since +\TeX\ discards glue, kerns, and penalties that occur just after a page break. +^^{page breaks//glue at} +Use the ^|\topglue| command \ctsref\topglue\ instead; it produces glue that +never disappears. +\eix^^{page breaks//bad} + + + +\section Correcting bad line breaks + +\null +\bix^^{line breaks//bad} +If \TeX\ breaks a line in the middle of material that you wanted to keep +on a single line, there are several ways to correct the situation: +\ulist\compact +\li You can force a break in a nearby place with the +|\break| command (\xref{hbreak}). +^^|\break//correcting line breaks with| +\li You can insert a tie (|~|) between two words +(see \xref{@not}) to prevent a break between them.\ttidxref{~} +\li You can tell \TeX\ about hyphenations that it wouldn't +otherwise consider by +inserting one or more discretionary hyphens in various words +(see |\-|, \xref{\@minus}). +\ctsidxref{-//in line breaking} +^^{discretionary hyphens//bad line breaks, correcting with} +\li You can enclose several words in an hbox using the ^|\hbox| +command \ctsref{\hbox}. +\endulist + +The disadvantage of all of these methods, except for inserting discretionary +hyphens, is that they may make it impossible for \TeX\ to find a +satisfactory set of line breaks. Should that happen, \TeX\ will +set one or more underfull or overfull boxes and complain about it. +^^{underfull boxes} ^^{overfull boxes} +The hbox method has a further disadvantage: because \TeX\ sets an hbox +as a single unit without considering its context, the interword space +within the hbox may not be consistent with the interword space in the rest of +the line. +\eix^^{line breaks//bad} + + +\section Correcting overfull or underfull boxes + +\null +\bix^^{overfull boxes} +\bix^^{underfull boxes} +\bix^^{boxes//overfull} +\bix^^{boxes//underfull} +If \TeX\ complains about an overfull box, it means you've put +more material into a box than that box has room for. +Similarly, if \TeX\ complains about an underfull box, it means you +haven't put enough material into the box. You can encounter +these complaints under many different circumstances, so let's look at the more +common ones: + +\ulist +\li An overfull hbox that's a line of a paragraph indicates that the line was +too long and that +\TeX\ couldn't rearrange the paragraph +to make the line shorter. If you set ^|\emergencystretch| +\ctsref{\emergencystretch} to some nonzero +value, that may cure the problem by allowing \TeX\ to put more space between +words. Another solution is to set |\tolerance| \ctsref{\tolerance} +to $10000$, but that's likely +to yield lines with far too much space in them. Yet another solution is to +insert a discretionary hyphen +^^{discretionary hyphens//overfull boxes, correcting with} +in a critical word that \TeX\ didn't know how to hyphenate. +If all else fails, you might try rewording the paragraph. +A solution that is rarely satisfactory is increasing ^|\hfuzz| \ctsref\hfuzz, +allowing \TeX\ to construct lines that project beyond the right margin. + +\li An underfull hbox that's a line of a paragraph indicates that the line was +too short and that \TeX\ couldn't rearrange the paragraph to +make the line longer. +\TeX\ will set such a line by stretching its interword spaces +beyond their normal +limits. Two of the cures for overfull lines mentioned above +also apply to underfull lines: +inserting discretionary hyphens and rewording the paragraph. +Underfull lines +won't trouble you if you're using ragged right formatting, which you can get +with the ^|\raggedright| command \ctsref\raggedright. + +\li The complaint: +\csdisplay +Underfull \vbox (badness 10000) has occurred + while \output is active +| +indicates that \TeX\ didn't have enough material to fill up a page. The +likely cause is that you've been using vboxes to keep material together +and \TeX\ has encountered a vbox near the bottom of a page that wouldn't fit on +that page. +It has put the vbox on the next page, but in doing so has left too much +empty space in the current page. +In this case you'll either have to insert some more space +elsewhere on the current page or break up the vbox into smaller parts. + +Another possible cause of this complaint is having a long paragraph +that occupies an entire page without a break. +Since \TeX\ won't ordinarily vary the spacing between lines, +it may be unable to fill a gap at the bottom of the page +amounting to a fraction of the line spacing. +This can happen if |\vsize| \ctsref{\vsize}, the page length, +is not an even multiple of |\baselineskip| \ctsref{\baselineskip}, +the space between consecutive +baselines. + +Yet another cause of this complaint, +similar to the previous one, is setting ^|\parskip| \ctsref{\parskip}, +the interparagraph glue, to a value that doesn't have any +stretch or shrink. You can fix these last two problems by increasing ^|\vfuzz| +\ctsref\vfuzz. + +\li The complaint +\csdisplay +Overfull \vbox (296.30745pt too high) has occurred + while \output is active +| +indicates that you constructed a vbox that was longer than the page. You'll +just have to make it shorter. + +\li +\bix^^|\hbox//overfull box from| +\bix^^|\vbox//overfull box from| +The only cures for an overfull hbox or vbox that you've constructed +with the |\hbox| or |\vbox| commands +(\pp\xrefn\hbox, \xrefn\vbox) +are to take something out of the box, to insert some negative glue +with ^|\hss| or ^|\vss| (\xref\hss), or to increase the size +of the box. + +\li If you encounter an underfull hbox or vbox that you've constructed +with |\hbox| or |\vbox|, +you're usually best off to fill out the box with ^|\hfil| +or ^|\vfil| (\xref\hfil). +\eix^^|\hbox//overfull box from| +\eix^^|\vbox//overfull box from| + +\endulist +\eix^^{boxes//overfull} +\eix^^{boxes//underfull} +\eix^^{overfull boxes} +\eix^^{underfull boxes} + + +\section Recovering lost interword spaces + +\null +^^{space//lost} +^^{words run together} +If you find that \TeX\ has run two words together, the likely cause is a +control sequence that's absorbed the spaces after it. +Put a ^{control space} (|\!visiblespace|) after the control +sequence. + + +\section Avoiding unwanted interword spaces + +\null +\bix^^{space//unwanted}\xrdef{unwantedspace} +If you get a space in your document where you don't want and don't +expect one, the most likely cause, in our experience, +is an end of line or a space following a brace. +^^{braces//space after} +(If you're doing fancy things with category codes, +^^{category codes//cause of unwanted spaces} +you've introduced lots of other likely causes.) +\TeX\ ordinarily translates an end-of-line into a space, +and it considers a space after a right or left brace to be significant. + +If the unwanted space is caused by a space after a brace within +an input line, then remove that space. +If the unwanted space is caused by a brace at the end of an input line, +put a `|%|' immediately after the brace. +{\recat!ttidxref[%//to eliminate unwanted spaces]] +The `|%|' starts a comment, but this comment needn't +have any text. + +A macro definition can also +introduce unwanted spaces if you haven't written it +carefully. If you're getting unwanted spaces when you call a macro, check +its definition to be sure that you don't have an unintended space after a +brace and that you haven't ended a line of the definition immediately +after a brace. +People often end lines of macro definitions after braces in order to make +the definitions more readable. +To be safe, put a `|%|' after any brace that ends a line of a macro +definition. +It may not be needed, but it won't do any harm.\footnote{ +Admittedly there are rare cases where you really do want an end of line +after a brace.} + +When you're having trouble locating the source of an unwanted space, +try setting |\tracingcommands| \ctsref{\tracingcommands} to $2$. +You'll get a |{blank space}| command in the log file for each space +that \TeX\ sees. + +It helps to know \TeX's rules for spaces: + +\olist +\li Spaces are ignored at the beginnings of input lines. +\li Spaces at the ends of input lines are ignored under \emph{all} +circumstances, although the end of line itself is treated like a space. +(A completely blank line, however, generates a |\par| token.) +\li Multiple spaces are treated like a single space, but +only if they appear together in your input. +Thus a space following the arguments of a macro call is not combined +with a final space produced by the macro call. Instead, you get two spaces. +\li Spaces are ignored after control words. +\li Spaces are in effect ignored after numbers, dimensions, +and the `|plus|' and `|minus|' in glue specifications.% +\footnote{Actually, \TeX\ ignores only a +single space in these places. +Since multiple spaces ordinarily reduce to a single space, however, the +effect is that of ignoring any number of spaces.} +\endolist +\noindent If you've changed the category code of the space or the end-of-line +character, all bets are off. +\eix^^{space//unwanted} + + +\section Avoiding excess space around a display + +\null +^^{math display} +If you're getting too much space above a math display, it may be because +you've left a blank line in your input above the display. +The blank line starts a new paragraph and puts \TeX\ into +vertical mode. When +\TeX\ sees a `|$|' in vertical mode, it switches back to horizontal mode +and inserts the interparagraph glue (|\parskip|) followed by +the interline glue (|\baselineskip|). +Then, when it starts the display itself, +it inserts \emph{more} glue (either ^|\abovedisplayskip| +or ^|\abovedisplayshortskip|, depending on the length of the preceding +line). +This last glue is the only glue that you want. +To avoid getting the interparagraph glue as well, don't leave a blank line above a +math display or otherwise +end a paragraph (with |\par|, say) just before a math display. + +Similarly, +if you're getting too much space below a math display, it may be because +you've left a blank line in your input below the display. +Just remove it. + + +\section Avoiding excess space after a paragraph + +If you get too much vertical space after a paragraph that was produced by a +macro, you may be getting the interparagraph glue produced by the macro, +an empty paragraph, and then more interparagraph glue. +You can get rid of the second paragraph skip by inserting: +\csdisplay +\vskip -\parskip +\vskip -\baselineskip +| +just after the macro call. +If you always get this problem with a certain macro, you can put these +lines at the end of the macro definition instead. +You may also be able to cure the problem by never leaving a blank line +after the macro call---if you want a blank line just to make your input +more readable, start it with a `|%|'. + + +\section Changing the paragraph shape + +\null +\bix^^{paragraphs//shaping} +Several \TeX\ parameters---^|\hangindent|, ^|\leftskip|, etc.---% +affect the way that \TeX\ shapes paragraphs and breaks them into lines. +^^{line breaking} +These parameters are used indirectly in \plainTeX{} commands such as +^|\narrower| and ^|\hang|; you can also assign to them directly. +If you've used one of these commands (or changed one of these parameters), +but the command or parameter change +does not seem to be having any effect on a paragraph, +the problem may be that you've ended a group before you've ended the +paragraph. For example: +\csdisplay +{\narrower She very soon came to an open field, with +a wood on the other side of it: it looked much darker +than the last wood, and Alice felt a little timid +about going into it.} +| +This paragraph won't be set narrower because the right brace at the end +terminates the |\narrower| group before \TeX\ has had a chance to +break the paragraph into lines. Instead, put a |\par| before the +right brace; then you'll get the effect you want. +^^|\par//when changing paragraph shape| +\eix^^{paragraphs//shaping} + + +\section Putting paragraphs into a box + +Suppose you have a few paragraphs of text that you want to put in a +particular place on the page. The obvious way to do it is to enclose +the paragraphs in an hbox of an appropriate size, and then place the hbox +where you want it to be. Alas, the obvious way doesn't work because +\TeX\ won't do line breaking in restricted horizontal mode. +^^{restricted mode//horizontal} +If you try it, +you'll get a misleading error message that suggests you're +missing the end of a group. +The way around this restriction is to write: +\csdisplay +\vbox{\hsize = ! !dots ! !dots} +| +where \ is the line length that you want for the paragraphs. +This is what you need to do, in particular, when you want to enclose some +paragraphs in a box (a box enclosed in ruled lines, not a \TeX\ box). + +\section Drawing lines + +\null +\bix^^{rules} +You can use the ^|\hrule| and ^|\vrule| commands (\xref\hrule) +to draw lines, i.e., rules. You'll need to +know (a)~where you can use each command and +(b)~how \TeX\ determines the lengths of rules when +you haven't given the lengths explicitly. +\ulist +\li You can only use |\hrule| when \TeX\ is in a vertical mode and |\vrule| +when \TeX\ is in a horizontal mode. +This requirement means that +you can't put a horizontal rule into an hbox or a vertical rule +into a vbox. +You can, however, construct a horizontal rule that looks vertical by +specifying all three dimensions and making it tall and skinny. +Similarly, you can construct a vertical rule that looks horizontal +by making it short and fat. + +\li A horizontal rule inside a vbox +has the same width as does the vbox if you haven't +given the width of the rule explicitly. +Vertical rules +inside hboxes behave analogously. +If your rules are coming out too long or too short, +check the dimensions of the enclosing box. +\endulist + +As an example, suppose we want to produce: +\display{% +\hbox{\vrule + \vbox{\hrule\vskip 3pt + \hbox{\hskip 3pt + \vbox{\hsize .7in\raggedright + \noindent Help! Let me out of here!}% + \hskip 3pt} + \vskip 3pt\hrule}% +\vrule}} +The following input will do it: +\csdisplay +\hbox{\vrule + \vbox{\hrule \vskip 3pt + \hbox{\hskip 3pt + \vbox{\hsize = .7in \raggedright + \noindent Help!! Let me out of here!!}% + \hskip 3pt}% + \vskip 3pt \hrule}% +\vrule} +| +We need to put the text into a vbox in order to get \TeX\ to process it +as a paragraph. +The four levels of boxing are really +necessary---if you doubt it, try to run this example with fewer levels. +\eix^^{rules} + + +\section Creating multiline headers or footers + +\null +\xrdef{bighead} +\bix^^{headers//multiple-line} +\bix^^{footers//multiple-line} +You can use +the ^|\headline| and ^|\footline| commands +(\xref\footline) to produce headers and footers, but they don't work properly +for headers and footers having more than one line. However, you can get +multiline headers and footers by redefining some of the subsidiary +macros in \TeX's output routine. + +For a multiline header, you need to do three things: +\olist\compact +\li Redefine the ^|\makeheadline| macro that's called from \TeX's +output routine. +\li Increase ^|\voffset| by the amount of vertical space consumed by the +extra lines. +\li Decrease ^|\vsize| by the same amount. +\endolist +\noindent The following example shows how you might do this: +\csdisplay +\advance\voffset by 2\baselineskip +\advance\vsize by -2\baselineskip +\def\makeheadline{\vbox to 0pt{\vss\noindent + Header line 1\hfil Page \folio\break + Header line 2\hfil\break + Header line 3\hfil}% + \vskip\baselineskip} +| +You can usually follow the pattern of this definition quite closely, just +substituting your own header lines and choosing an appropriate multiple +of |\baselineskip| (one less than the number of lines in the header). + +For a multiline footer, the method is similar: +\olist +\li Redefine the ^|\makefootline| macro that's called from \TeX's +output routine. +\li Decrease ^|\vsize| by the amount of vertical space consumed by the +extra lines. +\endolist +\noindent The following example shows how you might do this: +\csdisplay +\advance\vsize by -2\baselineskip +\def\makefootline{% + \lineskip = 24pt + \vbox{\raggedright\noindent + Footer line 1\hfil\break + Footer line 2\hfil\break + Footer line 3\hfil}} +| +Again, you can usually follow the pattern of this definition quite closely. +The value of |\lineskip| determines the amount of space between the +baseline of the last line +of the main text on the page and the baseline of the first line of the footer. +\eix^^{headers//multiple-line} +\eix^^{footers//multiple-line} + + +\section Finding mismatched braces + +\bix^^{braces//mismatched} +\xrdef{mismatched} +Most times when your \TeX\ input suffers from mismatched braces, you'll +get a diagnostic from \TeX\ fairly near the place where you actually +made the mistake. +But one of the most frustrating errors you can get from a \TeX\ run, +just before \TeX\ quits, is +the following: +\csdisplay +(\end occurred inside a group at level 1) +| +This indicates that there is an extra left brace +or a missing right brace somewhere +in your document, but it gives you no hint at all +about where the problem might be. So how can you find it? + +A debugging trick we've found useful +is to insert the following line or its equivalent +at five or six places equally spaced within the document (and not within +a known group): +\csdisplay +}% a fake ending +| +Let's assume the problem is an extra left brace. +If the extra left brace +is, say, between the third and fourth fake ending, +you'll get error messages from the first three fake endings but not from +the fourth one. The reason is that \TeX\ will ignore the first three +fake endings after complaining about them, +but the fourth fake ending will match +the extra left brace. +Thus you know that the extra left brace +is somewhere between the third and fourth +fake ending. +If the region of the error +is still too large for you to find it, +just remove the original set of fake endings and +repeat the process within that region. +If the problem is a missing right brace rather than an extra left brace, +you should be able to track it down once you've found its mate. + +This method doesn't work under all circumstances. In particular, it doesn't +work if your document consists of several really large groups. But often +you can find some variation on this method that will lead you to that +elusive brace. + +If all else fails, try shortening your input by removing +the last half of the file +(after stashing away the original version first!) or inserting a +|\bye| command in the middle. +If the error persists, you know it's in the first half; if it goes away, +you know it's in the second half. +By repeating this process you'll eventually find the error. +\eix^^{braces//mismatched} + + +\section Setting dimensions + +\null +\bix^^{\} +The simplest way to set a dimension is to specify it directly, e.g.: +\csdisplay +\hsize = 6in +| +You can also specify a dimension in terms of other dimensions or as a mixture +of different units, but it's a little more work. There are two ways +to construct a dimension as such a combination: +\olist\compact +\li You can add a dimension to a dimension parameter or to a dimension +register. +For example: +\csdisplay +\hsize = 6in \advance\hsize by 3pc % 6in + 3pc +| +\li You can indicate a dimension as a multiple of a dimension +or glue parameter or register. +In this case, \TeX\ converts glue to a dimension by throwing away +the stretch and shrink. For example: +\csdisplay +\parindent = .15\hsize +\advance\vsize by -2\parskip +| +\endolist +\eix^^{\} + + +\section Creating composite fonts + +\null +\bix^^{fonts//composite} +It's sometimes useful to create a ``composite font'', +named by a control sequence $\cal F$, in which all the characters +are taken from a font $f_1$ except for a few that are +borrowed from another font $f_2$. +You can then set text in the composite font by using $\cal F$ just as +you'd use any other font identifier. + +You can create such a composite font by defining $\cal F$ as a macro. +In the definition of $\cal F$, you first select font $f_1$ and then +define control sequences that produce the borrowed characters, +set in $f_2$. +For example, suppose that you want to +create a composite font |\britrm| which has all the characters of |cmr10| +except for the dollar sign, for which you want to borrow +the pound sterling symbol +from font |cmti10|. +The pound sterling symbol in |cmti10| happens to be in the same font position +as the dollar sign in |cmr10|. +Here's how to do it: +\csdisplay +\def\britrm{% + \tenrm % \tenrm names the cmr10 font + \def\${{\tenit\char `\$}}% \tenit names the cmti10 font. +} +| +Now whenever you start the font named |\britrm|, +|\$| will produce a pound sterling symbol. + +You can also get the same effect by changing the category codes +of the characters in question to make those characters active and then +providing a definition for the character. For example: +\csdisplay +\catcode `* = \active +\def*{{\tentt \char `\*}} +| +In this case the asterisk will be taken from the |\tentt| font. +If you then type the input line: +\csdisplay +Debbie was the * of the show. +| +it will be set as: +{\font\tentt=cmtt10% +\catcode `* = \active +\def*{{\tentt \char `\*}}% +\display{Debbie was the * of the show.}} +\noindent + +\eix^^{fonts//composite} + + +\section Reproducing text verbatim + +\null +^^{verbatim text}\xrdef{verbatim} +Verbatim text is text that is reproduced in a typeset +document just as it appeared in the input. +The most common use of verbatim text is in typesetting +computer input, +including both computer programs and input to \TeX\ itself. +^^{computer programs, typesetting} +Computer input is not easy to produce verbatim for two reasons: +\olist\compact +\li Some characters (control symbols, escape characters, braces, +etc.) have +special meanings to \TeX. +\li Ends of line and multiple spaces are translated to single spaces. +\endolist +\noindent +In order to produce verbatim text, you have to cancel the special meanings +and disable the translation. This is best done with macros. + +To cancel the special meanings, you need to change the category codes +of those characters that have special meanings. +^^{category codes//for verbatim text} +The following macro illustrates how you might do it: +\csdisplay +\chardef \other = 12 +\def\deactivate{% + \catcode`\\ = \other \catcode`\{ = \other + \catcode`\} = \other \catcode`\$ = \other + \catcode`\& = \other \catcode`\# = \other + \catcode`\% = \other \catcode`\~ = \other + \catcode`\^ = \other \catcode`\_ = \other +} +| +But beware! Once you've changed the category codes in this way, you've lost +the ability to use control sequences since there's no longer an escape +character. You need some way of getting back to the normal mode of +operation. We'll explain how to do that in a moment, after considering +the other problem: disabling the translation of spaces and ends of line. + +\PlainTeX\ has two commands that together nearly solve the problem: +^|\obeyspaces| \ctsref{\obeyspaces} and ^|\obeylines| \ctsref{\obeylines}. +The two things that they don't do are to preserve spaces at the start of +a line +and to preserve blank lines. +For that you need stronger measures---which are provided by +the ^|\obeywhitespace| macro that we are about to define. + +\TeX\ normally insists on collecting lines into paragraphs. One way to +convince it to take line boundaries literally is to turn individual lines +into paragraphs.\footnote{% +Another way is to turn the end of line character into a |\break| +command and provide infinite glue at the end of each line. +^^|\break//end of line as| +} +You can do this by redefining the end of line character to produce +the |\par| control sequence. The following three macro definitions +show how: + +^^{whitespace, preserving} +\xrdef{\obeywhitespace} +\csdisplay +\def\makeactive#1{\catcode`#1 = \active \ignorespaces} +{% The group delimits the text over which ^^M is active. + \makeactive\^^M % + \gdef\obeywhitespace{% + % Use \gdef so the definition survives the group. + \makeactive\^^M % + \let^^M = \newline % + \aftergroup\removebox % Kill extra paragraph at end. + \obeyspaces % + }% +} +\def\newline{\par\indent} +\def\removebox{\setbox0=\lastbox} + +| +A subtle point about the definition of |\obeywhitespace| is that +|^^M| must be made active both +when |\obeywhitespace| is being \emph{defined} and when +it is being \emph{used}. + +In order to be able to get back to normal operation after verbatim text, +you need to choose a character that +appears rarely if at all in the verbatim text. This character serves as +a temporary escape character. +The vertical bar (|!||) is sometimes a good choice. +With this choice, the macros: +\csdisplay +\def\verbatim{\par\begingroup\deactivate\obeywhitespace + \catcode `\!| = 0 % Make !| the new escape character. +} + +\def\endverbatim{\endgroup\endpar} + +\def\!|{!|} +| +will do the trick. Within the verbatim text, you can use a double +vertical bar (|!|!||) to denote a single one, and you end the verbatim text +with |!|endverbatim|. + +There are many variations on this technique: +\ulist +\li If a programming language has keywords, you can turn +each keyword into a command that typesets +that keyword in boldface. Each keyword in the input should then be +preceded by the temporary escape character. +\li If you have a character (again, let's assume it's the vertical bar) +that +\emph{never} appears in the verbatim text, you can make it active and +cause it to end the verbatim text. The macro definitions then go like +this: +\csdisplay +{\catcode `\!| = \active +\gdef\verbatim{% + \par\begingroup\deactivate\obeywhitespace + \catcode `!| = \active + \def !|{\endgroup\par}% +}} +| +\endulist + +The ideas presented here provide only a simple approach to typesetting +computer programs. +Verbatim reproduction is often not as revealing or easy to read as a version +that uses typographical conventions to reflect the syntax +and even the semantics of the program. +If you'd like to pursue this subject further, we recommend the following book: + +\smallskip{\narrower\noindent +Baecker, Ronald M., and Marcus, Aaron, {\sl Human Factors +and Typography for More Readable Programs}. Reading, Mass.: +Addison-Wesley, 1990.\par} + + +\section Using outer macros + +\null +^^{forbidden control sequence}^^{incomplete conditional} +If \TeX\ complains about a ``forbidden control sequence'', +you've probably used an outer macro in a non-outer context +\seeconcept{outer}. +^^{macros//outer} +An outer macro is one whose definition is +preceded by ^|\outer|. +An outer macro can't be used in a macro argument, in a macro definition, +in the preamble of an alignment, or in conditional +text, i.e., text that will be expanded only when a conditional test +has a particular outcome. +^^{alignments//outer control sequence in} +Certain macros have been defined as outer because they aren't +intended to be used in these contexts and such a use is probably an error. +The only ways around this problem are to redefine the +macro or to move its use to an acceptable context. + +Using an outer macro in an improper context can also cause +\TeX\ to complain about a runaway situation or an incomplete conditional. +The problem can be hard to diagnose because the error message +gives no hint as to what it is. +If you get such an error message, look around for a call on an outer macro. +You may not always know that a particular macro is outer, but the +command `^|\show||\a|' \ctsref{\show} +will show you the definition of |\a| and also tell you +if |\a| is outer. + + +\section Changing category codes + +\null +\bix^^{category codes//changing} +Sometimes it's useful to make local changes to the category code of a +character in some part of your document. For instance, you might be +typesetting a computer program +^^{computer programs, typesetting} +or something else that uses normally active +characters for special purposes. You'd then want to deactivate those +characters so that \TeX\ will treat them as being like any other character. + +If you make such a local change to the category code of a character, +you may sometimes be dismayed to find that +\TeX\ seems to be paying no attention whatsoever to your change. +Two aspects of \TeX's behavior are likely causes: +\olist +\li \TeX\ determines the category code of an input character +^^{input characters} +and attaches it to the character when it reads in the character. +Let's say you read in a tilde (|~|) and later +change the category code of tildes, +but make the change +before \TeX's stomach has actually processed that \emph{particular\/} +tilde \seeconcept{\anatomy}. +\TeX\ will still respond to that +tilde using the category code as it was before the change. +This difficulty typically arises +when the tilde is part of an argument to a macro +and the macro itself changes the category code of tilde. + +\li When \TeX\ is matching a call of a macro to the definition of that macro, +it matches not just the characters in the parameter pattern but also their +category codes. +^^{macros//arguments of} +^^{macros//parameters of} +If the category code of a pattern character isn't equal to +the category code of the same character in the call, \TeX\ won't consider +the characters as matching. +This effect can produce mysterious results because it +\emph{looks} as though the pattern should match. +For example, if you've defined a macro: +\csdisplay +\def\eurodate#1/#2/#3{#2.#1.#3} +| +then the slash character must have the same category code when you +call |\eurodate| as it had when you defined |\eurodate|. +\endolist +If the problem arises because the troublesome character is an argument to +a macro, then +the usual cure is to redefine the macro as a pair +of macros |\mstart| and |\mfinish|, where +|\mstart| is to be called before the argument text +and |\mfinish| is to be called after it. +|\mstart| then sets up the category codes and |\mfinish| undoes the change, +perhaps just by ending a group. +\eix^^{category codes//changing} + + +\section Making macro files more readable + +\null +\bix^^{macros//making readable} +You can make a file of macros more readable by +setting the category codes of space to $9$ (ignored +character) and ^|\endlinechar| \ctsref{\endlinechar} to $-1$ +at the beginning of the file. +Then you can use spaces and ends of line freely in the +macro definitions without getting +unwanted spaces when you call the macros. +The ignored characters won't generate spaces, but they'll still +act as terminators for control sequences. +If you really do want a space, you can still get it with the ^|\space| +command \ctsref\space. + +Of course you'll need to restore the category codes of space and end of line +to their normal values ($10$ and $5$, respectively) at the end of the file. +You can do this either by enclosing the entire file in a group or by +restoring the values explicitly. If you choose to enclose the file in a group, +then you should also set ^|\globaldefs| to $1$ so that +all the macro definitions will be global and thus visible outside of the group. + +A miniature example of a macro file of this form is: + +\csdisplay +\catcode `\ = 9 \endlinechar = -1 + +\def \makeblankbox #1 #2 { + \hbox{\lower \dp0 \vbox{\hidehrule {#1} {#2} + \kern -#1 % overlap rules + \hbox to \wd0{\hidevrule {#1} {#2}% + \raise \ht0 \vbox to #1{} % vrule height + \lower \dp0 \vtop to #1{} % vrule depth + \hfil \hidevrule {#2} {#1} } + \kern -#1 \hidehrule {#2} {#1} } } + +\def\hidehrule #1 #2 { + \kern -#1 \hrule height#1 depth#2 \kern -#2 } +\def\hidevrule #1 #2 { + \kern -#1 {\dimen0 = #1 \advance \dimen0 by #2 + \vrule width \dimen0 } \kern -#2 } + +\catcode `\ = 10 \endlinechar = `\^^M +| +\noindent +Without the changed category codes, +these macros would have to be written much more compactly, using fewer +spaces and more `|%|'s at the ends of lines. +\eix^^{macros//making readable} + +\endchapter\byebye -- cgit v1.2.3