Began versioning.
[curses-check-for-keypress.git] / curses_check_for_keypress.py
1 #!/usr/bin/python
2 #
3 # curses_check_for_keypress - loop until user presses a key.
4 #
5 # Copyright (C) 2008-2009 William Trevor King
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation; either version 3 of the
10 # License, or (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 # See the GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 # 02111-1307, USA.
21 #
22 # The author may be contacted at <wking@drexel.edu> on the Internet, or
23 # write to Trevor King, Drexel University, Physics Dept., 3141 Chestnut St.,
24 # Philadelphia PA 19104, USA.
25
26
27 import curses, curses.ascii
28 import time
29 import sys
30 import StringIO
31 # http://www.amk.ca/python/howto/curses/curses.html
32
33 VERSION = "0.1"
34
35 def quiet_sleep() :
36     time.sleep(.1)
37
38 def test_sleep() :
39     time.sleep(.5)
40
41 class check_for_keypress :
42     def __init__(self, prompt="Press any key to continue",
43                  timeout_ms=0, test_mode=False) :
44         self.test_mode = test_mode
45         self.last = None  # last byte number read
46         self.lasta = None # last as an ASCII character
47         if test_mode == True :
48             print prompt
49             self.i = 0
50             return None
51         # redirect stderr to a file, because exiting curses mode clears
52         # any error messages that had been printed to the screen
53         sys.stderr = StringIO.StringIO()
54         # initialize raw curses mode
55         self.stdscr = curses.initscr()
56         curses.noecho()
57         curses.cbreak()
58         self.stdscr.scrollok(1)
59         try :
60             self.stdscr.addstr(0,0,prompt+"\n")
61             if timeout_ms <= 0 :
62                 self.stdscr.nodelay(True)
63             else :
64                 self.stdscr.halfdelay(timeout_ms)
65         except :
66             self.close()
67     def __del__(self) :
68         self.close()
69     def close(self) :
70         if self.test_mode == True :
71             return None
72         # return to standard terminal
73         while self.input() != None : # eat up the buffer
74             pass
75         self.stdscr.scrollok(0)
76         curses.nocbreak()
77         curses.echo()
78         curses.endwin()
79         # print any errors and restore stderr
80         contents = sys.stderr.getvalue()
81         sys.stderr = sys.__stderr__
82         if len(contents) > 0 :
83             print contents
84     def input(self) :
85         if self.test_mode == True :
86             if self.i < 10 :
87                 self.i += 1
88                 return None
89             else :
90                 return "a"
91         c = self.stdscr.getch()
92         if c == curses.ERR :
93             return None
94         else :
95             self.last = c
96             self.lasta = curses.ascii.unctrl(c)
97             return c
98     def inputa(self) :
99         c = self.input()
100         if c == None :
101             return None
102         else :
103             return self.lasta
104     def _output(self, string) :
105         if self.test_mode == True :
106             print string,
107             return None
108         #y,x = self.stdscr.getyx()
109         self.stdscr.addstr(string)
110     def _flush(self) :
111         if self.test_mode == True :
112             return None
113         self.stdscr.refresh()
114     def output(self, string) :
115         self._output(string)
116         self._flush()
117
118 def _test_usual_usage() :
119     c=check_for_keypress('testing usual usage, press any key to stop loop...')
120     i = 0
121     while c.input() == None :
122         test_sleep()
123         c.output('sleeping\n')
124         if i > 1000:
125             raise Exception, "you didn't press a key!"
126         i += 1
127     del(c)
128
129 def _test_error_catching() :
130     c=check_for_keypress('testing error catching, wait for the error...')
131     i = 0
132     class _testException (Exception):
133         pass
134     try:
135         while c.input() == None :
136             if i > 4 :
137                 print >> sys.stderr, "testing error output"
138                 raise _testException, "testing error exception"
139             test_sleep()
140             c.output('sleeping\n')
141             i += 1
142         raise Exception, "_test_error_catching() failed!"
143     except _testException, e:
144         assert len(sys.stderr.getvalue()) > 0, "No error message!"
145     del(c)
146
147 def test() :
148     _test_usual_usage()
149     _test_error_catching()
150
151 if __name__ == "__main__" :
152     test()