summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/eplain/base/progdef.texi
blob: 4169f15173037753c2fcb71f4deaf0e5eff8339f (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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
@c This is part of the Eplain manual.  Public domain.

@node Programming definitions
@chapter Programming definitions

The definitions in this section are only likely to be useful when you
are writing nontrivial macros, not when writing a document.

@menu
* Category codes::              Changing category codes.
* Allocation macros::           Non-outer versions of \newcount et al.
* Iteration::                   Doing `for' loops in TeX.
* Macro arguments::             Reading and ignoring them.
* Converting to characters::    Normalizing control sequences and spaces.
* Expansion::                   Controlling expansion.
* Obeying spaces::              Making whitespace count anywhere.
* Writing out numbers::         Making `1' into `one'.
* Mode-specific penalties::     
* Auxiliary files::             Testing for their existence.
* User-defined environments::   User-defined environments.
* Page list and page range parsers::
@end menu


@node Category codes
@section Category codes

@cindex category codes

Plain @TeX{} defines @code{\active} (as the number 13) for use in
changing category codes.  Although the author of @cite{The @TeX{}book}
@cindex Knuth, Donald Ervin
has ``intentionally kept the category codes numeric'', two other
categories are commonly used: letters (category code 11) and others
(12).  Therefore, Eplain defines @code{\letter} and
@code{\other}.
@findex letter
@findex other

Sometimes it is cleaner to make a character active without actually
@cindex active characters
writing a @code{\catcode} command.  The @code{\makeactive} command takes
@findex catcode
@findex makeactive
a character as an argument to make active (and ignores following
spaces).  For example, here are two commands which both make @kbd{\}
active:
@cindex backslash character

@example
\makeactive`\\   \makeactive92
@end example

@cindex user-inaccessible macros
@cindex inaccessible macros
Sometimes you might want to temporarily change the category code of
the `@@' character to @code{\letter}, so that you can use or define
macros which are normally inaccessible to the user.  For such
situations, Eplain provides the @code{\makeatletter}
@findex makeatletter
command.  It sets the category code of `@@' to @code{\letter} (11) and
defines
@code{\resetatcatcode}
@findex resetatcatcode
to restore the category code to whatever it was before the call to
@code{\makeatletter}.  For example:

@example
\makeatletter
\def\@@hidden@@macro@{This macro cannot normally be
                   called / redefined by the user@}
\resetatcatcode
@end example

@noindent There is also @code{\makeatother}
@findex makeatother
which works similarly but sets the category code of `@@' to
@code{\other} (12).

Usually, when you give a definition to an active character, you have
to do so inside a group where you temporarily make the character active,
and then give it a global definition (cf.@: the definition of
@code{\obeyspaces} in @cite{The @TeX{}book}).
@cindex definitions, global
This is inconvenient if you are writing a long macro, or if the
character already has a global definition you do not wish to transcend. 
Eplain provides @code{\letreturn}, which defines the usual end-of-line
@findex letreturn
@cindex return character
character to be the argument.  For example:

@example
\def\mymacro@{@dots{} \letreturn\myreturn @dots{} @}
\mymacro hello
there
@end example

@noindent The end-of-line between @samp{hello} and @samp{there} causes
@code{\myreturn} to be expanded.

@cite{The @TeX{}book} describes @code{\uncatcodespecials},
@findex uncatcodespecials
which makes all characters which are normally ``special'' into ``other''
characters, but the definition never made it into plain @TeX{}. 
Eplain therefore defines it.

Finally, @code{\percentchar}
@findex percentchar
expands into a literal `%' character.  This is useful when you
@code{\write} @TeX{} output to a file, and want to avoid spurious
spaces.  For example, Eplain writes a @code{\percentchar} after the
definition of cross-references.  The macros @code{\lbracechar}
@findex lbracechar
and @code{\rbracechar}
@findex rbracechar
expand similarly.


@node Allocation macros
@section Allocation macros

@cindex allocation macros
@cindex register allocation

Plain @TeX{} provides macros that allocate registers of each primitive
type in @TeX{}, to prevent different sets of macros from using the same
register for two different things.  The macros are all named starting
with @samp{new},
@findex new@dots{}
e.g., @code{\newcount} allocates a new ``count''
(integer) register.  Such allocations are usually needed only at the top
level of some macro definition file; therefore, plain @TeX{} makes the
allocation registers @code{\outer},
@findex outer
to help find errors.  (The error this helps to find is a missing right
brace in some macro definition.)

Sometimes, however, it is useful to allocate a register as part of
some macro.  An outer control sequence cannot be used as part of a macro
definition (or in a few other contexts: the parameter text of a
definition, an argument to a definition, the preamble of an alignment,
or in conditional text that is being skipped).  Therefore, Eplain
defines ``inner'' versions of all the allocation macros, named with the
prefix @samp{inner}:
@code{\innernewbox},
@findex innernewbox
@code{\innernewcount},
@findex innernewcount
@code{\innernewdimen},
@findex innernewdimen
@code{\innernewfam},
@findex innernewfam
@code{\innernewhelp},
@findex innernewhelp
@code{\innernewif},
@findex innernewif
@code{\innernewinsert},
@findex innernewinsert
@code{\innernewlanguage},
@findex innernewlanguage
@code{\innernewread},@*
@findex innernewread
@code{\innernewskip},
@findex innernewskip
@code{\innernewtoks},
@findex innernewtoks
@code{\innernewwrite}.
@findex innernewwrite

You can also define non-outer versions of other macros in the same way
that Eplain defines the above.  The basic macro is called
@code{\innerdef}:
@findex innerdef

@example
\innerdef @var{\innername} @{@var{outername}@}
@end example

The first argument (@var{\innername}) to @code{\innerdef} is the
control sequence that you want to define.  Any previous definition of
@var{\innername} is replaced.  The second argument
(@var{outername}) is the @emph{characters} in the name of the outer
control sequence.  (You can't use the actual control sequence name,
since it's outer!)

If the outer control sequence is named @var{\cs}, and you want to
define @code{inner@var{cs}} as the inner one, you can use
@code{\innerinnerdef},
@findex innerinnerdef
which is just an abbreviation for a call to @code{\innerdef}.  For
example, these two calls are equivalent:

@example
\innerdef\innerproclaim@{proclaim@}
\innerinnerdef@{proclaim@}
@end example


@node Iteration
@section Iteration

@cindex iteration
@cindex for loops

You can iterate through a comma-separated list of items with
@code{\for}.
@findex for
Here is an example:

@example
\for\name:=karl,kathy\do@{%
   \message@{\name@}%
@}%
@end example

This writes @samp{karl} and @samp{kathy} to the terminal.  Spaces
before or after the commas in the list, or after the @code{:=}, are
@emph{not} ignored.

@code{\for} expands the iterated values fully (with @code{\edef}), so
this is equivalent to the above:

@example
\def\namelist@{karl,kathy@}%
\for\name:=\namelist\do @dots{}
@end example


@node Macro arguments
@section Macro arguments

@cindex arguments, ignoring
@cindex ignoring arguments
@cindex gobbling arguments
It is occasionally useful to redefine a macro that takes arguments to
do nothing.  Eplain defines @code{\gobble},
@findex gobble
@code{\gobbletwo},
@findex gobbletwo
and @code{\gobblethree} to swallow one, two, and three arguments,
respectively.

For example, if you want to produce a ``short'' table of
@cindex table of contents, short
contents---one that includes only chapters, say---the easiest thing to
do is read the entire @code{.toc} file (@pxref{Contents}), and just
ignore the commands that produce section or subsection entries.  To be
specific:

@example
\let\tocchapterentry = \shorttocchapter
\let\tocsectionentry = \gobbletwo
\let\tocsubsectionentry = \gobbletwo
\readtocfile
@end example
@noindent (Of course, this assumes you only have chapters, sections, and
subsections in your document.)

In addition, Eplain defines @code{\eattoken}
@findex eattoken
to swallow the single following token, using @code{\let}.  Thus,
@code{\gobble} followed by @samp{@{@dots{}@}} ignores the entire
brace-enclosed text.  @code{\eattoken} followed by the same ignores only
the opening left brace.

Eplain defines a macro @code{\identity}
@findex identity
which takes one argument and expands to that argument.  This may be
useful if you want to provide a function for the user to redefine, but
don't need to do anything by default.  (For example, the default
definition of @code{\eqconstruct} (@pxref{Formatting equation
references}) is @code{\identity}.)

You may also want to read an optional argument.  The established
convention is that optional arguments are put in square brackets, so
that is the syntax Eplain recognizes.  Eplain ignores space tokens
before an optional argument, via @code{\futurenonspacelet}.

You test for an optional argument by using @code{\@@getoptionalarg}.
@c this confuses texinfo.tex: findex @@getoptionalarg
It takes one argument, a control sequence to expand after reading the
argument, if present.  If an optional argument is present, the control
sequence @code{\@@optionalarg} expands to it; otherwise,
@code{\@@optionalarg} is @code{\empty}.  You must therefore have the
category code of @kbd{@@} set to 11 (letter).  Here is an example:

@example
\catcode`@@=\letter
\def\cmd@{\@@getoptionalarg\finishcmd@}
\def\finishcmd@{%
  \ifx\@@optionalarg\empty
    % @r{No optional argument present.}
  \else
    % @r{One was present.}
  \fi
@}
@end example

If an optional argument contains another optional argument, the inner
one will need to be enclosed in braces, so @TeX{} does not mistake the
end of the first for the end of the second.


@node Converting to characters
@section Converting to characters

@cindex characters, converting to
Eplain defines  @code{\xrlabel}
@findex xrlabel
to produce control sequence names for cross-reference labels, et al.
This macro expands to its argument with an @samp{_} appended.  (It does
this because the usual use of @code{\xrlabel} is to generate a control
sequence name, and we naturally want to avoid conflicts between control
sequence names.)

Because @code{\xrlabel} is fully expandable, to make a control
sequence name out of the result you need only do
@example
@code{\csname \xrlabel@{@var{label}@}\endcsname}
@end example

@noindent The @code{\csname} primitive makes a control sequence name out
of any sequence of character tokens, regardless of category code.
Labels can therefore include any characters except for @samp{\},
@samp{@{}, @samp{@}}, and @samp{#}, all of which are used in macro
definitions themselves.

@findex sanitize
@code{\sanitize} takes a control sequence as an argument and converts
the expansion of the control sequence into a list of character tokens.
This is the behavior you want when writing information like chapter
titles to an output file.  For example, here is part of the definition
of @code{\writenumberedtocentry}; @code{#2} is the title that the user
has given.

@example
@dots{}
\def\temp@{#2@}%
@dots{}
  \write\tocfile@{%
    @dots{}
    \sanitize\temp
    @dots{}
  @}%
@end example


@node Expansion
@section Expansion

This section describes some miscellanous macros for expansion, etc.

@menu
* \csn and \ece::               Abbreviations for \csname expansions.
* \edefappend::                 
* Hooks::                       Manipulating and executing named actions.
* Properties::                  Associating information with a csname.
* \expandonce::                 
* \ifundefined::                
* \futurenonspacelet::          
@end menu


@node \csn and \ece
@subsection @code{\csn} and @code{\ece}

@findex csn
@code{\csn}@{@var{name}@} simply abbreviates @code{\csname} @var{name}
@code{\endcsname}, thus saving some typing.  The extra level of expansion
does take some time, though, so I don't recommend it for an inner loop.

@findex ece
@code{\ece}@{@var{token}@}@{@var{name}@} abbreviates

@example
\expandafter @var{token} \csname @var{name} \endcsname
@end example

@noindent For example,

@example
\def\fontabbrevdef#1#2@{\ece\def@{@@#1font@}@{#2@}@}
\fontabbrevdef@{normal@}@{ptmr@}
@end example

@noindent defines a control sequence @code{\@@normalfont} to expand to
@code{ptmr}.


@node \edefappend
@subsection @code{\edefappend}

@findex edefappend
@code{\edefappend} is a way of adding on to an existing definition.  It
takes two arguments: the first is the control sequence name, the second
the new tokens to append to the definition.  The second argument is
fully expanded (in the @code{\edef} that redefines the control sequence).

For example:

@example
\def\foo@{abc@}
\def\bar@{xyz@}
\edefappend\foo@{\bar karl@}
@end example

@noindent results in @code{\foo} being defined as @samp{abcxyzkarl}.


@node Hooks
@subsection Hooks

@cindex hooks
A @dfn{hook} is simply a name for a group of actions which is executed
in certain places---presumably when it is most useful to allow
customization or modification.  @TeX{} already provides many builtin
hooks; for example, the @code{\every @dots{}} token lists are all
examples of hooks.

Eplain provides several macros for adding actions to hooks.  They all
take two arguments: the name of the hook and the new actions.

@table @code

@findex hookaction
@itemx hookaction @var{name} @var{actions}
@findex hookappend
@itemx hookappend @var{name} @var{actions}
@findex hookprepend
@item hookprepend @var{name} @var{actions}
Each of these adds @var{actions} to the hook @var{name}.  (Any
previously-defined actions are retained.)  @var{name} is not a control
sequence, but rather the characters of the name.

@findex hookactiononce
@item hookactiononce @var{name} @code{\@var{cs}}
@code{\hookactiononce} adds @var{cs} to @var{name}, like the macros
above, but first it adds

@example
\global\let @var{\cs} \relax
@end example

@noindent to the definition of @var{\cs}.  (This implies @var{\cs} must
be a true expandable macro, not a control sequence @code{\let} to a
primitive or some other such thing.)  Thus, @var{\cs} is expanded the
next time the hook @var{name} is run, but it will disappear after that.

The @code{\global} is useful because @code{\hookactiononce} is most
useful when the grouping structure of the @TeX{} code could be anything.
Neither this nor the other hook macros do global assignments to the hook
variable itself, so @TeX{}'s usual grouping rules apply.
@end table

@findex hookrun
The companion macro to defining hook actions is @code{\hookrun}, for
running them.  This takes a single argument, the name of the hook.  If
no actions for the hook are defined, no error ensues.

Here is a skeleton of general @code{\begin} and @code{\end} macros that
run hooks, and a couple of calls to define actions.  The use of
@code{\hookprepend} for the begin action and @code{\hookappend} for the
end action ensures that the actions are executed in proper sequence with
other actions (as long as the other actions use @code{\hookprepend} and
@code{\hookappend} also).

@example
\def\begin#1@{ @dots{} \hookrun@{begin@} @dots{} @}
\def\end#1@{ @dots{} \hookrun@{end@} @dots{} @}
\hookprepend@{begin@}\start_underline
\hookappend@{end@}\finish_underline
@end example


@node Properties
@subsection Properties

@cindex properties
@cindex atom
A @dfn{property} is a name/value pair associated with another symbol,
traditionally called an @dfn{atom}.  Both atom and property names are
control sequence names.

Eplain provides two macros for dealing with property lists:
@code{\setproperty} and @code{\getproperty}.

@table @code

@findex setproperty
@item \setproperty @var{atom} @var{propname} @var{value}
@code{\setproperty} defines the property @var{property} on the atom
@var{atom} to be @var{value}.  @var{atom} and @var{propname} can be
anything acceptable to @code{\csname}.  @var{value} can be anything.

@findex getproperty
@item \getproperty @var{atom} @var{propname}
@code{\getproperty} expands to the value stored for @var{propname} on
@var{atom}.  If @var{propname} is undefined, it expands to nothing
(i.e., @code{\empty}).

@end table

The idea of properties originated in Lisp (I believe).  There, the
implementation truly does associate properties with atoms.  In @TeX{},
where we have no builtin support for properties, the association is only
conceptual.

The following example typesets @samp{xyz}.

@example
\setproperty@{a@}@{pr@}@{xyz@}
\getproperty@{a@}@{pr@}
@end example


@node \expandonce
@subsection @code{\expandonce}

@cindex expansion, one-level 
@findex expandonce
@code{\expandonce} is defined as @code{\expandafter\noexpand}.  Thus, 
@code{\expandonce @var{token}} expands @var{token} once, instead of to
@TeX{} primitives.  This is most useful in an @code{\edef}.  

For example, the following defines @code{\temp} to be @code{\foo}, not
@samp{abc}.

@example
\def\foo@{abc@}
\def\bar@{\foo@}
\edef\temp@{\expandonce\bar@}
@end example


@node \ifundefined
@subsection @code{\ifundefined}

@findex ifundefined
@code{\ifundefined@{@var{cs}@} @var{t} \else @var{f} \fi} expands the
@var{t} text if the control sequence @code{\@var{cs}} is undefined or
has been @code{\let} to @code{\relax}, and the @var{f} text otherwise.

@cindex skipping tokens
@cindex undefined control sequence, checking for
Since @code{\ifundefined} is not a primitive conditional, it cannot be
used in places where @TeX{} might skip tokens ``at high speed'', e.g.,
within another conditional---@TeX{} can't match up the @code{\if}'s and
@code{\fi}'s.

This macro was taken directly from @cite{The @TeX{}book}, page 308.


@node \futurenonspacelet
@subsection @code{\futurenonspacelet}

@cindex lookahead without spaces
@cindex spaces, ignoring
@findex futurenonspacelet
The @code{\futurelet} primitive allows you to look at the next token
from the input.  Sometimes, though, you want to look ahead ignoring any
spaces.  This is what @code{\futurenonspacelet} does.  It is otherwise
the same as @code{\futurelet}: you give it two control sequences as
arguments, and it assigns the next nonspace token to the first, and then
expands the second.  For example:

@example
\futurenonspacelet\temp\finishup
\def\finishup@{\ifx\temp @dots{}@}
@end example


@node Obeying spaces
@section Obeying spaces

@cindex whitespace
@cindex spaces, obeying
@cindex newlines, obeying
@findex obeywhitespace

@code{\obeywhitespace} makes both end-of-lines and space characters in
the input be respected in the output.  Unlike plain @TeX{}'s
@code{\obeyspaces}, even spaces at the beginnings of lines turn into
blank space.

By default, the size of the space that is produced by a space
character is the natural space of the current font, i.e.,
what @code{\ } produces.

Ordinarily, a blank line in the input produces as much blank vertical
space as a line of text would occupy.  You can adjust this by assigning
to the parameter @code{\blanklineskipamount}:
@findex blanklineskipamount @r{in obeyed text}
if you set this negative, the space produced by a blank line will be
smaller; if positive, larger.

Tabs are not affected by this routine.  In particular, if tabs occur
at the beginning of a line, they will disappear.  (If you are trying to
make @TeX{} do the ``right thing'' with tabs, don't.  Use a utility
program like @i{expand} instead.)
@cindex tabs


@node Writing out numbers
@section Writing out numbers

@cindex numbers, written form of
   @code{\numbername}
@findex numbername
produces the written-out form of its argument, i.e., `zero' through
`ten' for the numbers 0--10, and numerals for all others.


@node Mode-specific penalties
@section Mode-specific penalties

@TeX{}'s built-in @code{\penalty} command simply appends to the
current list, no matter what kind of list it is.  You might intend a
particular penalty to always be a ``vertical'' penalty, however, i.e.,
appended to a vertical list.  Therefore, Eplain provides
@code{\vpenalty}
@findex vpenalty
and @code{\hpenalty}
which first leave the other mode and then do @code{\penalty}.

More precisely, @code{\vpenalty} inserts @code{\par} if the current
mode is horizontal, and @code{\hpenalty} inserts @code{\leavevmode} if
the current mode is vertical.  (Thus, @code{\vpenalty} cannot be used in
math mode.)


@node Auxiliary files
@section Auxiliary files

@cindex axuiliary files, existence of
It is common to write some information out to a file to be used on a
subsequent run.  But when it is time to read the file again, you only
want to do so if the file actually exists.  @code{\testfileexistence}
@findex testfileexistence
is given an argument which is appended to @code{\jobname},
@findex jobname
and sets the conditional @code{\iffileexists}
@findex iffileexists
@findex fileexists @r{(conditional)}
appropriately.  For example:

@example
\testfileexistence@{toc@}%
\iffileexists
   \input \jobname.toc
\fi
@end example

@code{\testfileexistence} takes an optional parameter; when
given, it will override @code{\jobname} for the root part of the file
name.  For example, if you want to test for the file
@file{answers.aux}, you can do this with the following:

@example
\testfileexistence[answers]@{aux@}%
\iffileexists
   \input answers.aux
\fi
@end example


@node User-defined environments
@section User-defined environments

@cindex environments, user-defined 
Plain @TeX{} does not provide ``named'' block structures, only the anonymous 
@code{\begingroup} and @code{\endgroup} pair. The disadvantage of this
is that when there are several such groups and one is mismatched, it can
be difficult to find the error. Eplain provides a named block structure
so that if you forget an @code{\environment} or an
@code{\endenvironment}, you will (probably) get an error message about
it.

For example:

@example
\def\itpar@{
  \environment@{@@italicpar@}
  \it\par
@}
\def\enditpar@{
  \par
  \endenvironment@{@@italicpar@}%
@}
@end example
@noindent which could then be used to set italicized paragraphs: 
@example
\itpar
If I reprehend anything in this world, it is the use of my oracular
tongue, and a nice derangement of epitaphs! 
\enditpar
@end example

The above sort of environment allows nesting.  But environments
shouldn't always be allowed to nest.  Put the control sequence 
@code{\checkenv} at the beginning of a macro that is going to define an
environment that should not be nested. 


@node Page list and page range parsers
@section Page list and page range parsers

@findex idxparselist
@findex idxparserange
@findex idxpagei
@findex idxpageii
The macros which Eplain uses to parse the page lists and ranges in the
index, @code{\idxparselist} and @code{\idxparserange} (@pxref{Page
destinations for index terms}), are sometimes useful when defining page
number encapsulators.  They take one argument, text to parse.  When a
page list (range) is not present, they set @code{\idxpagei} to be
@code{\empty}; when a list (range) is detected, they set
@code{\idxpagei} and @code{\idxpageii} to the first and the second page
numbers, respectively.

@findex setidxpagelistdelimiter
@findex setidxpagerangedelimiter
Eplain's defaults for the page list and page range delimiters are the
same as those in MakeIndex, a comma followed by a space (@samp{, }) and
two dashes (@samp{--}), respectively.  If you customize MakeIndex to use
different delimiters, you must not forget to let Eplain know about them
with the commands

@example
\setidxpagelistdelimiter@{@var{list-delim}@}
\setidxpagerangedelimiter@{@var{page-delim}@}
@end example

@noindent These commands save the @var{list-delim} and
@var{page-delim} delimiters in
@findex idxpagelistdelimiter
@findex idxpagerangedelimiter
@code{\idxpagelistdelimiter} and @code{\idxpagerangedelimiter},
respectively.

@cindex underlining page numbers in index
@cindex index, underlining page numbers
@findex ituline
For example, you may want to define a page number markup command which
italicizes and properly underlines page ranges by underlining only the
page numbers and not the delimiter:

@findex idxpagerangedelimiter
@example
\def\ituline#1@{%
  @{\it
  \idxparserange@{#1@}%
  \ifx\idxpagei\empty
    % The argument is a single page number.
    \underbar@{#1@}%
  \else
    % The argument is a page range.
    \underbar@{\idxpagei@}\idxpagerangedelimiter\underbar@{\idxpageii@}%
  \fi@}%
@}
@end example

@noindent Note that the @code{\ituline} macro is not aware of page
lists.  This is not needed if you use hyperlinks in the index, because
@code{\hlidx} and @code{\hlidxpage} will break up the page lists before
calling the user's page encapsulator (@pxref{Page destinations for index
terms}), so @code{\ituline} will never see the lists.  If, however, you
need to design a macro which also takes care of the lists, you can
extend @code{\ituline} with an additional call to @code{\idxparselist}.