summaryrefslogtreecommitdiff
path: root/info/challenges/aro-bend/answer.017
blob: c0d5be7d4ef23677b877d9853e90bdf961270b4f (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
[The TUGboat article mentioned below appeared as [info not yet
available--18-Aug-1994]]

Date: 17 Mar 1994 13:04:36 -0500 (EST)
From: Michael Downes <MJD@MATH.AMS.ORG>
Subject: Around the Bend #17, answers
To: info-tex@shsu.edu
X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>

Exercise 17 (posted January 14) asked for an error recovery file to
provide better recovery from file input errors: When TeX cannot find an
input file, it prompts for an alternative file name and refuses to
continue until a valid file name is entered or the user presses some
(system-dependent) abort key. This can be rather unfriendly, especially
for novice users.

At the request of Barbara Beeton (TUGboat's editor) I wrote up the
results of this exercise as an article for publication in TUGboat, so
this posting will be largely redundant with that article.

-------------------------------------
DON'T BOTHER, REDEFINE \input INSTEAD

Interestingly, both of the answers I received (from Victor Eijkhout and
Donald Arseneau) recommended redefining input instead of trying to
make an input error recovery file. Donald summed it up thus:

> Since verbatim file input is an important mainstream application,
> the task is hopeless.
> 
> The right approach is to redefine \input and check for the file's
> existence at the macro level.

I.e., consider the way a typical \verbfile commands works: first, start
a group; next, deactivate all special characters such as \ { } # % by
changing their catcodes; then input the desired file; and finally close
the group to restore normal catcodes. If the desired file is not found
and an input error recovery file is read instead, the IERF will not be
able to do anything because of the deactivation of \ { } etc.

----------------------------------------------
DIFFICULTIES ASSOCIATED WITH REDEFINING \input

Generally speaking I am in favor of redefining input (for instance,
to make up for the deficiency in TeX that the current input file name
is not accessible like \jobname or \inputlineno), but there are
some practical problems:

---In order to serve all users, the redefinition of \input would
have to go into plain TeX, LaTeX, and any other major macro
packages that are not layered on top of plain TeX or LaTeX.

---The most commonly used approach to test for the existence of an input
file is \openin N=file.name \ifeof N ..., but for
some TeX implementations \openin will only open a file in the
current directory, and not search through the entire `TeX inputs'
path. I believe that this restriction is canonical in TeX.web
therefore only overridden by the system-dependent changes of each TeX
implementation according to the judgment of the individual implementor.

---The details of how to redefine \input are nontrivial. If you
redefine \input to take an argument delimited by a space, for
example, there is some risk of bombing on existing files with
statements like

  \input x.y\relax

It becomes especially nontrivial if you want to use some method other
than simple \openin ... \ifeof to test for file existence, so that
the method will be reliable across all systems.

It is worth noting that in LaTeX2e the \input command has
been dramatically overhauled so that it solves, among other things,
some of the problems mentioned here. Anyone doubting the claim that
the work is nontrivial is invited to look at the LaTeX2e definitions.

---Redefining \input will (generally speaking) not help for the
jobname file itself. When the file name is given on the command line, or
following a ** prompt, the input operation is done directly by
TeX instead of through invoking the control sequence \input.

---When a non-existing file is called for by a verb-file command,
TeX will prompt the user for a file name, and then if a .tex recovery
file exists, pressing <return> will typeset the contents of that file;
but this is at least as good as inputting a null file, in that you are
not stuck at the prompt with no obvious way to quit.

----------------------------------------------------------
SOMEBODY ALREADY PUBLISHED SOME INPUT ERROR RECOVERY FILES

Coincidentally, reading through one of my books a few days after posting
Around the Bend #17, I found that someone had already written and
published a suite of input error recovery files: Frank Mittelbach, The
LaTeX Companion, section 14-4.

------------------------------------------------------
BUT WHAT THE HECK, HERE ARE MY SLIGHTLY DIFFERENT ONES

The basic idea is to create a file named h.tex that will produce an
\errmessage{...} statement. Copies (or links) of this file will be made
under several different names corresponding to the typical user
responses to an input file error, to the extent that the operating
system permits.

So a first attempt would be something like this:

  \errmessage{Enter x to exit or ? to see other options}

Suppose we test this with a simple test file:

  %   This is line 1
  %   This is line 2
  \input fzrg \relax % This is line 3
  %   This is line 4
  \end

The on-screen result looks like this:

  ! I can't find file `fzrg.tex'.
  l.3 \input fzrg 
                  \relax % This is line 3
  Please type another input file name: h
  (h.tex
  ! Enter x to exit or ? to see other options.
  l.1 ... to exit or ? to see other options}

  ?

Then if the user enters ? they will see

  Type <return> to proceed,
  S to scroll future error messages,
  R to run without stopping,
  Q to run quietly,
  I to insert something,
  E to edit your file,
  1 or ... or 9 to ignore the next 1 to 9 tokens of input,
  H for help, X to quit.
  ? x

Now let's examine this solution a little more closely, to ask what are
the potential problems, and what assumptions can be done away with?

One problem is the possibility of an unusual catcode for space, question
mark, left brace, right brace, backslash, or \endlinechar. For the
backslash (and the letters) we don't have much choice; if they don't
have normal catcodes, h.tex cannot issue an \errmessage command, or even
try to fix up the catcodes. (This is why the problem of verbatim file
input is insoluble, if primitive \input is used.) Note that for users of
a macro package such as texinfo, which has @ for the escape character
instead of backslash, a different IERF would be required.

The \endlinechar problem can be solved by adding a percent sign at the
end of the line:

  \errmessage{...}%

but at the cost of a new assumption: percent must have catcode 14. This
and some of the other catcode assumptions can be removed with a bit of
extra work:

  \begingroup\chardef\%37\catcode\%14\chardef\ 32\catcode\ 10\relax%
  \catcode123 1\catcode125 2\catcode63 12 %
  \errmessage{%
  Enter x to exit or ? to see other options}%
  \endgroup\endinput%

This enforces the desired catcodes for space, %, {, }, and ?; and
putting % at the end of each line makes \endlinechar harmless, no matter
what its prevailing value and catcode might happen to be. The
\begingroup ... \endgroup pair of course keep the catcode changes local,
just in case (though I expect that the user will normally choose to exit
anyway). I write

  \chardef\%37\catcode\%14

in preference to the alternatives

  \catcode37 14
  \catcode37=14
  \catcode37'16
  \catcode37"E
  \catcode`\%14

which require assuming a usable catcode for one extra character (space
or = or ' or ...). Even using \string, as in

  \catcode37\string"E

would fail if " had catcode 5, 9, 10, 11, 14, or 15.

Here now is the screen output produced by the above IERF:

  ! I can't find file `fzrg'.
  l.3 \input fzrg 
                  \relax % This is line 3
  Please type another input file name: h
  (h.tex
  ! Enter x to exit or ? to see other options.
  l.5  Enter x to exit or ? to see other options}
                                                 %
  ? x

------------------
BEST FINAL VERSION

There is one fairly obvious drawback of the above IERF: the error
message is repeated twice on screen, once by \errmessage and once in the
error context shown for line 5. There is a little trick that can be used
to fix that: Use only the error context for showing the message text, by
putting it in a comment rather than in the argument of \errmessage!
[Cf.the comment after \patterns in the original TeX hyphenation patterns
file hyphen.tex.]

  \begingroup\chardef\%37\catcode\%14\chardef\?63\catcode\?12\relax%
  \chardef\{123\catcode\{1\chardef\ 32\catcode\ 2\relax%
  \errmessage{Input\string canceled\string ..%
   % Enter x to exit or ? to see other options %
  \endgroup\endinput%

I have thrown in some extra cleverness with the catcode of space to
clean up the screen output a tiny bit more. The result looks like this:

  ! I can't find file `fzrg'.
  l.3 \input fzrg 
                  \relax % This is line 3
  Please type another input file name: h
  (h.tex
  ! Input canceled ...
  l.4  
       % Enter x to exit or ? to see other options %
  ? x

Frank Mittelbach's IERF solution differs from mine by providing a set of
files that attempt to mimic standard TeX error recovery according to
their name: The file s.tex, for example, arranges to switch into
\scrollmode and continue processing, as would happen if you entered `s'
at a normal error message prompt. And there are files named e.tex,
x.tex, q.tex that mimic the corresponding error message actions. His
IERFs also don't bother to worry about possible odd catcodes for {,
space, }, etc.---an approach whose simplicity perhaps outweighs the
minor added robustness of my version.

-----------
CONCLUSIONS

It seems that it would be a worthy service to their users if the authors
of all TeX implementations took a second look at how input file errors
are handled and added suitable actions depending on the operating
system. For example, under DOS it is difficult to create a file named
.tex, so perhaps emTeX, PCTeX, TurboTeX, etc., should check for the case
when the user presses the <return> key at the prompt, and automatically
exit instead of trying to input a highly improbable file! Similar
arguments would hold for an input file name of ? or ?.tex for operating
systems where ? is an OS wild-card character.

And another part of improving the input error handling might be to add
to their standard distributions a set of IERFs in the TeX inputs area,
to help users who are using some macro package *other* than LaTeX2e.
(Or, even for LaTeX2e users, to help in the case when it is the jobname
file itself that was not input-able.) I recommend of course my IERF
given above; my feelings would not be deeply wounded, however, if
Frank's version gets used instead. Installing either version would be
much better for end users than none at all.

Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~