+#!/usr/bin/python
+#
+# curses_check_for_keypress - loop until user presses a key.
+#
+# Copyright (C) 2008-2009 William Trevor King
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# The author may be contacted at <wking@drexel.edu> on the Internet, or
+# write to Trevor King, Drexel University, Physics Dept., 3141 Chestnut St.,
+# Philadelphia PA 19104, USA.
+
+
+import curses, curses.ascii
+import time
+import sys
+import StringIO
+# http://www.amk.ca/python/howto/curses/curses.html
+
+VERSION = "0.1"
+
+def quiet_sleep() :
+ time.sleep(.1)
+
+def test_sleep() :
+ time.sleep(.5)
+
+class check_for_keypress :
+ def __init__(self, prompt="Press any key to continue",
+ timeout_ms=0, test_mode=False) :
+ self.test_mode = test_mode
+ self.last = None # last byte number read
+ self.lasta = None # last as an ASCII character
+ if test_mode == True :
+ print prompt
+ self.i = 0
+ return None
+ # redirect stderr to a file, because exiting curses mode clears
+ # any error messages that had been printed to the screen
+ sys.stderr = StringIO.StringIO()
+ # initialize raw curses mode
+ self.stdscr = curses.initscr()
+ curses.noecho()
+ curses.cbreak()
+ self.stdscr.scrollok(1)
+ try :
+ self.stdscr.addstr(0,0,prompt+"\n")
+ if timeout_ms <= 0 :
+ self.stdscr.nodelay(True)
+ else :
+ self.stdscr.halfdelay(timeout_ms)
+ except :
+ self.close()
+ def __del__(self) :
+ self.close()
+ def close(self) :
+ if self.test_mode == True :
+ return None
+ # return to standard terminal
+ while self.input() != None : # eat up the buffer
+ pass
+ self.stdscr.scrollok(0)
+ curses.nocbreak()
+ curses.echo()
+ curses.endwin()
+ # print any errors and restore stderr
+ contents = sys.stderr.getvalue()
+ sys.stderr = sys.__stderr__
+ if len(contents) > 0 :
+ print contents
+ def input(self) :
+ if self.test_mode == True :
+ if self.i < 10 :
+ self.i += 1
+ return None
+ else :
+ return "a"
+ c = self.stdscr.getch()
+ if c == curses.ERR :
+ return None
+ else :
+ self.last = c
+ self.lasta = curses.ascii.unctrl(c)
+ return c
+ def inputa(self) :
+ c = self.input()
+ if c == None :
+ return None
+ else :
+ return self.lasta
+ def _output(self, string) :
+ if self.test_mode == True :
+ print string,
+ return None
+ #y,x = self.stdscr.getyx()
+ self.stdscr.addstr(string)
+ def _flush(self) :
+ if self.test_mode == True :
+ return None
+ self.stdscr.refresh()
+ def output(self, string) :
+ self._output(string)
+ self._flush()
+
+def _test_usual_usage() :
+ c=check_for_keypress('testing usual usage, press any key to stop loop...')
+ i = 0
+ while c.input() == None :
+ test_sleep()
+ c.output('sleeping\n')
+ if i > 1000:
+ raise Exception, "you didn't press a key!"
+ i += 1
+ del(c)
+
+def _test_error_catching() :
+ c=check_for_keypress('testing error catching, wait for the error...')
+ i = 0
+ class _testException (Exception):
+ pass
+ try:
+ while c.input() == None :
+ if i > 4 :
+ print >> sys.stderr, "testing error output"
+ raise _testException, "testing error exception"
+ test_sleep()
+ c.output('sleeping\n')
+ i += 1
+ raise Exception, "_test_error_catching() failed!"
+ except _testException, e:
+ assert len(sys.stderr.getvalue()) > 0, "No error message!"
+ del(c)
+
+def test() :
+ _test_usual_usage()
+ _test_error_catching()
+
+if __name__ == "__main__" :
+ test()