1. Henning Schröder
  2. ttgui

Source

ttgui / console.py

# -*_ coding: utf-8 -*-
# http://gnosis.cx/publish/programming/charming_python_6.html
# TODO: implement ConsoleLib-API with ncurses: http://effbot.org/zone/console-handbook.htm
import sys
import curses

from keymap import keymap


def debug(*args):
    s = " ".join(str(a) for a in args)
    open("/tmp/debug.log", "a").write("%s\n" % s)

    

class Console(object):
    instance = None
    
    def __init__(self):
        if Console.instance:
            raise RuntimeError("Only one console instance allowed")
        Console.instance = self
        sys.excepthook = self.excepthook
        self.window = curses.initscr()
        if curses.has_colors():
            curses.start_color()
        curses.noecho()
        #curses.cbreak()    
        curses.raw() # intercept everything
        # In keypad mode, escape sequences for special keys
        # (like the cursor keys) will be interpreted and
        # a special value like curses.KEY_LEFT will be returned
        self.window.keypad(1)

        
        # Frame the interface area at fixed VT100 size
        self.width = 80
        self.height= 25
        self.screen = self.window.subwin(self.height, self.width, 0, 0)
        #self.screen.box()
        #self.screen.hline(2, 1, curses.ACS_HLINE, 77)
        self.screen.refresh()
    

        
    def excepthook(self, *args):
        self.close()
        sys.__excepthook__(*args)
        sys.exit(1)


    def __del__(self):
        self.close()
        

    def close(self):
        if self.window:
            self.window.keypad(0)
        curses.echo()
        #curses.nocbreak()
        curses.endwin()


    def getchar(self, wait=False):
        if not wait:
            self.screen.nodelay(1)
            while 1:
                try:
                    curses.cbreak()
                    break
                except _curses.error:
                    pass
        return self.screen.getch()
    
    
    def readkeys(self):
        l = []
        while True:
            key = self.getchar()
            if key == -1:
                break
            l.append(chr(key))
        return "".join(l)

        
    def xreadkeys(self):
        umlauts = {
            '\xc3\xa4': u'ä',
            '\xc3\x84': u'Ä',
            '\xc3\xb6': u'ö',
            '\xc3\x96': u'Ö',
            '\xc3\xbc': u'ü',
            '\xc3\x9c': u'Ü',
            '\xc3\x9f': u'ß',
            }

        keys = self.readkeys()
        
        if keys in umlauts:
            return False, umlauts[keys]

        if keys.startswith(chr(27)):
            xkeys = keymap.get(keys[1:], None)
            if xkeys:
                return True, xkeys
            elif len(keys) == 2:
                return True, "meta %s" % keys[1]
        elif len(keys) ==  1:
            code = ord(keys[0]) 
            if code < 32 and code not in (9,10):
                return True, "ctrl %s" % chr(ord('A') + code - 1) + str(code)
        return False, keys
        

    def refresh(self):
        self.screen.refresh()
    
    
    def text(self, column, line, string, style=curses.A_NORMAL):
        self.screen.addstr(line, column, string, style)


    def page(self):
        self.window.erase()
        

    def gotoxy(self, x, y):
        self.window.move(x, y)
        self.text(x,y, "")

        
    def show_cursor(self):
        curses.curs_set(2)


    def hide_cursor(self):
        curses.curs_set(0)



if __name__=='__main__':
    c = Console()
    c.text(1,1, "hello, world!")
    i = 0
    while True:
        keys = c.readkeys()
        if keys:
            if keys in keymap:
                keys = keymap[keys]
            i += 1
            c.text(i%23, 1, "%r  " % keys)
    c.close()