Added modular directory structure.
[hooke.git] / hooke / libinput.py
1 '''
2 Input check routines.
3
4 Copyright (C) 2008 Alberto Gomez-Casado (University of Twente).
5
6 This program is released under the GNU General Public License version 2.
7
8 This is just a collection of wrappers for raw_input(), I noticed using
9 hooke that unexpected answers from the user often triggered a nasty
10 crash, so what they do is provide some basic check of inputs to avoid
11 'voids', letters where numbers are expected, etc
12
13 The basic call there is safeinput(message,[list])
14 Message is a string that is shown to the user ('Enter filename:')
15 [list] can be present or not.
16   - If not present safeinput is just a raw_input shielded against void
17 inputs (it will keep asking until it gets some answer)
18   - If a list of only one element is provided, it is interpreted as a
19 default value (in case a void input that value will be returned)
20   - If a list of two or more 'string' elements is provided, user input
21 must match one of them to be valid
22   - If a list of two integer elements [a, b] is provided, user input
23 is required to be in the interval [a,b]
24
25 More info about the underlying calls can be found in the code. However
26 I am still not very satisfied with them, That's why I made safeinput()
27 to wrap all so I can improve them without further fiddling with other
28 module's code.
29 '''
30
31 from types import *
32
33
34 def safeinput (message, valid=[]):
35     '''
36     friendlier frontend for alphainput and numinput
37     valid should be a list of 0...n values
38     '''
39
40     #if possible values are not listed we just ask for any non-null input
41     if len(valid)==0:
42         return alphainput(message, '',1,[])
43
44
45     if len(valid)>0:
46         #if valid values are string we use alphainput, if it is only one we take as default
47         if type(valid[0]) is StringType:
48             if len(valid)==1:
49                 return alphainput(message, valid[0], 0,[])
50             else:
51                 return alphainput(message,'', 1,valid)
52
53         #if valid values are numbers we use numinput
54         if type(valid[0]) is IntType:
55             if len(valid)==1:
56                 return numinput(message,valid[0],1,[])
57             else:
58                 return numinput(message,'',1,valid)
59
60
61 def alphainput (message, default, repeat, valid):
62     '''
63     message: prompt for the user
64     default: return value if user input was not correct (and repeat=0)
65     repeat: keeps asking user till it gets a valid input
66     valid: list of allowed answers, empty list for "anything"
67     '''
68     if default and not repeat:
69         print 'Press [enter] for default: ('+str(default)+')'
70     reply=raw_input(message)
71     if len(valid)>0:
72         if reply in valid:
73             return reply
74         else:
75             if repeat==1:
76                 while reply not in valid:
77                     reply=raw_input('You should enter any of these: '+ str(valid) +'\n'+ message)
78                 return reply
79             else:
80                 return default
81     else:
82         if len(reply)>0:
83             return reply
84         else:
85             if not repeat:
86                 return default
87             else:
88                 while len(reply)==0:
89                     print 'Try again'
90                     reply=raw_input(message)
91                 return reply
92
93
94 def checkalphainput (test, default, valid):
95     #useful when input was taken form command args
96     if len(valid)>0:
97         if test in valid:
98             return test
99         else:
100             return default
101     else:
102         #TODO: raise exception?
103         if len(test)>0:
104             return test
105         else:
106             return default
107
108
109 def numinput(message, default, repeat, limits):
110     '''
111     message: prompt for the user
112     default: return value if user input was not correct (and repeat=0)
113     repeat: keeps asking user till it gets a valid input
114     limits: pair of values, input is checked to be between them, empty list for "any number"
115     '''
116     if default and not repeat:
117         print 'Press [enter] for default: '+str(default)
118
119     reply=raw_input(message)
120
121     try:
122         intreply=int(reply)
123     except:
124         intreply=None
125
126     if len(limits)==2:
127         high=int(limits.pop())
128         low=int(limits.pop())
129         if intreply>=low and intreply <= high:
130             return intreply
131         else:
132             if repeat==1:
133                 while intreply<low or intreply>high :
134                     reply=raw_input('You should enter values between: '+ str(low)+' and '+str(high) +'\n'+ message)
135                     try:
136                         intreply=int(reply)
137                     except:
138                         intreply=None
139                 return intreply
140             else:
141                 return default
142     else:
143         if intreply!=None:
144             return intreply
145         else:
146             if not repeat:
147                 return default
148             else:
149                 while intreply==None:
150                     print 'Try again'
151                     reply=raw_input(message)
152                     try:
153                         intreply=int(reply)
154                     except:
155                         intreply=None
156                 return intreply
157
158
159 def checknuminput(test,default,limits):
160     #useful when input was taken from command args
161     if len(limits)==2:
162         high=int(limits.pop())
163         low=int(limits.pop())
164         if test>=low and test <= high:
165             return int(test)
166         else:
167             return default
168     else:
169         if len(test)>0:
170             return int(test)
171         else:
172             return default