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
|
% Removed parts marked by ellipsis dots (mjd)
. . .
UKTeX Digest Friday, 4 Jan 1991
Volume 91 : Issue 1
Today's Topics:
RE: Testing for numeric-only input
RE: Help with TeX fonts
re: Footnotes without the number
metafont bombs out on cmbase.mf
. . .
------------------------------------------------------------
Date: Tue, 13 Nov 90 19:35:05 +0000
From: TEX@UK.AC.CRANFIELD.RMCS
Subject: RE: Testing for numeric-only input
In message 84 of Tue, 13 Nov 90 11:20:22,
C20249@UK.AC.POLY-SOUTH-WEST.PRIME-A wrote:
> Back in March, I wrote to you asking for help with a TeX/LaTeX
> query. I have still not had any acknowledgment or reply. Can you
> please help? Here is my query:
I'm sorry, but there appears to be no record of your submission to
UKTeX ever having arrived. Perhaps it came in when Aston were
experiencing some difficulty in forwarding Janet mail to the UKTeX
editor, and you missed the ``bounce''.
> I am writing a LaTeX "program" and need your help. I am using
> \typein to prompt the user to enter a "number" via the terminal.
> Then I set a counter to the value of the "number" read in.
>
> \typein[\mynumber]{Please type a number}
> \setcounter{mycounter}{\mynumber}
>
> What I would like to do is to insert some TeX logic (before
> setting the counter) to check the validity of the "number"
> entered (it should consist of a sequence of digits 0-9 only) and
> to prompt the user again if it contains anything else.
>
> I have scoured the TeXbook looking for anything that might appear
> to be useful or relevant, but I'm not a TeXpert and my search was
> fruitless.
Having had a slightly similar requirement when writing my
crossword.sty option, and eventually being pointed towards
\afterassignment by Frank Mittelbach, I can sympathize.
I've just knocked together (and tested!) the following style option,
which fills the bill, I think.
Enjoy!!
Brian {Hamilton Kelly}
. . .
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[Start of attached file CHECKNUM.STY]
% CHECKNUM.STY
%
% A style file providing the macro \getnumber.
%
% Usage: \getnumber{A prompt string}{countername}
% or: \getnumber{A prompt string}[default]{countername}
%
% Outputs the specified prompt and accepts input interactively.
%
% If the input forms a valid number, it will be assigned to the
% LaTeX counter `countername'. Invalid input causes repetition
% of the prompt until a valid response is given.
%
% The second form, with the optional parameter, will assign the
% value `default' (which must be a valid number) to countername
% if the user types return by itself.
%
% Caveat: Input commencing with leading zeros will be spuriously
% rejected.
%
%
% Author: Brian {Hamilton Kelly}
% Address: Royal Military College of Science,
% Shrivenham, SWINDON, SN6~8LA, United Kingdom
% Tel: ++44 793 785252
% e-mail: <TeX@Uk.Ac.Cranfield.RMCS>
% Date: 13th November 1990
%
% This macro reads and consumes all following text, up to and
% including the special marker \@nil
\def\special@gobble #1\@nil{}
% This if allows us to decide whether a valid number was entered
\newif\ifg@rbage
%
% Here is the macro to be invoked by the user
%
\def\getnumber#1{\@ifnextchar[{\g@tnumber#1}{\g@tnumber#1[]}}
%
% This is the macro that does the work!
%
\def\g@tnumber#1[#2]#3{%
\loop
% Doing things this way allows us to get the prompt and the
% response onto the same line; the alternative course of using
% \typein would have separated these items, and the prompt line
% itself would have read as
% ``\@tempa=''.
\typeout{}% Ensure we start on a newline;
% prompt & response then together
% If the optional default value is provided, include it in the
% prompt
\ifx #2 \@empty
\message{#1: }%
\else
\message{#1 [#2]: }%
\fi
% Read the user's response
\read\m@ne to\@tempa
% If the user types just a return, \@tempa will be set to `\par ';
% convert this into just a space by itself. When we later perform
% the assignment to \@tempcnta, the latter will assume the value
% zero, so the expansion of \@tempa will NOT equate to that of
% \@tempb, and the input of a return by itself will thus be
% rejected. (NB \@defpar is defined by LaTeX.TeX)
\ifx \@tempa\@defpar \xdef\@tempa{#2\space}\fi
% We'll now assign to \@tempcnta whatever part of the beginning of
% the content of \@tempa (read from the input) that constitutes a
% legal number; any remaining characters (including the terminating
% space) will then be discarded by the call of \special@gobble, but
% this macro only takes effect AFTER the assignment to the counter
% has taken place
\afterassignment \special@gobble \@tempcnta=0\@tempa \@nil
% We define \@tempb to expand to whatever legal number was input,
% with a trailing space.
\xdef\@tempb{\the\@tempcnta\space}%
% therefore, iff \@tempa contained only digits then its first-level
% expansion will be identical to that of \@tempb
\ifx\@tempb\@tempa
\g@rbagefalse
\else
% But if the `number' input contained non-digit characters, then
% \@tempb will contain something different!
\g@rbagetrue
\fi
% If we didn't get a valid number, then tell the punter; the
% \repeat will then return us to the \loop above, and re-prompt for
% input.
\ifg@rbage
\typeout{Your response contained non-digit characters; try again!}%
\repeat
% Finally, we can set the user-provided LaTeX counter and return
\setcounter{#3}{\the\@tempcnta}%
}
------------------------------
. . .
|