chiark / gitweb /
Keystroke handling infrastructure
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Tue, 26 May 2009 01:56:14 +0000 (02:56 +0100)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Tue, 26 May 2009 01:56:14 +0000 (02:56 +0100)
yoweb-scrape

index b62ce00..b4f99c5 100755 (executable)
@@ -14,6 +14,7 @@ import sys
 import re as regexp
 import random
 import curses
+import termios
 from optparse import OptionParser
 
 from BeautifulSoup import BeautifulSoup
@@ -41,9 +42,12 @@ def debug(m):
        if opts.debug > 0:
                print >>opts.debug_file, m
 
-def sleep(seconds):
+def debug_flush():
        if opts.debug > 0:
-               opts.debug_file.flush()
+               opts.debug_file.flush() 
+
+def sleep(seconds):
+       debug_flush()
        time.sleep(seconds)
 
 def format_time_interval(ti):
@@ -989,16 +993,23 @@ def do_ship_aid(args, bu):
        if opts.ship_duty is None: opts.ship_duty = True
 
        displayer = globals()['Display_'+opts.display]()
-       rotate_nya = '/-\\'
 
        (myself, track) = prep_chat_log(args, bu, progress=displayer)
 
-       def timeevent(t,e):
-               if t is None: return ' ' * 22
-               return " %-4s %-16s" % (format_time_interval(now - t),e)
-
        displayer.realstart()
 
+       if os.isatty(0): kr_create = KeystrokeReader
+       else: kr_create = DummyKeystrokeReader
+
+       try:
+               kreader = kr_create(0, 10)
+               ship_aid_core(myself, track, displayer, kreader)
+       finally:
+               kreader.stop()
+               print '\n'
+
+def ship_aid_core(myself, track, displayer, kreader):
+
        def find_vessel():
                vn = track.vesselname()
                if vn: return (vn, " on board the %s" % vn)
@@ -1006,15 +1017,23 @@ def do_ship_aid(args, bu):
                if vn: return (vn, " ashore from the %s" % vn)
                return (None, " not on a vessel")
 
+       def timeevent(t,e):
+               if t is None: return ' ' * 22
+               return " %-4s %-16s" % (format_time_interval(now - t),e)
+
        displayer.show(track.myname() + find_vessel()[1] + '...')
 
+       rotate_nya = '/-\\'
+
        while True:
                track.catchup()
                now = time.time()
 
                (vn, s) = find_vessel()
                s = track.myname() + s
-               s += " at %s\n" % time.strftime("%Y-%m-%d %H:%M:%S")
+               s += " at %s" % time.strftime("%Y-%m-%d %H:%M:%S")
+               s += kreader.info()
+               s += '\n'
 
                tbl = StandingsTable()
                tbl.headings()
@@ -1036,10 +1055,43 @@ def do_ship_aid(args, bu):
                                tbl.pirate(pi, xs)
 
                s += tbl.results()
-
                displayer.show(s)
-               sleep(1)
-               rotate_nya = rotate_nya[1:3] + rotate_nya[0]
+
+               k = kreader.getch()
+               if k is None:
+                       rotate_nya = rotate_nya[1:3] + rotate_nya[0]
+                       continue
+
+               if k == 'q':
+                       break
+
+#---------- individual keystroke input ----------
+
+class DummyKeystrokeReader:
+       def __init__(self,fd,timeout_dummy): pass
+       def stop(self): pass
+       def getch(self): sleep(1); return None
+       def info(self): return ' [noninteractive]'
+
+class KeystrokeReader(DummyKeystrokeReader):
+       def __init__(self, fd, timeout_decisec=0):
+               self._fd = fd
+               self._saved = termios.tcgetattr(fd)
+               a = termios.tcgetattr(fd)
+               a[3] &= ~(termios.ECHO | termios.ECHONL |
+                         termios.ICANON | termios.IEXTEN)
+               a[6][termios.VMIN] = 0
+               a[6][termios.VTIME] = timeout_decisec
+               termios.tcsetattr(fd, termios.TCSANOW, a)
+       def stop(self):
+               termios.tcsetattr(self._fd, termios.TCSANOW, self._saved)
+       def getch(self):
+               debug_flush()
+               byte = os.read(self._fd, 1)
+               if not len(byte): return None
+               return byte
+       def info(self):
+               return ''
 
 #---------- main program ----------