Andrew M. Kuchling | d0939fa | 2000-06-10 23:06:53 +0000 | [diff] [blame] | 1 | """curses |
| 2 | |
| 3 | The main package for curses support for Python. Normally used by importing |
| 4 | the package, and perhaps a particular module inside it. |
| 5 | |
| 6 | import curses |
| 7 | from curses import textpad |
Andrew Svetlov | bac04e5 | 2012-12-29 23:07:50 +0200 | [diff] [blame] | 8 | curses.initscr() |
Andrew M. Kuchling | d0939fa | 2000-06-10 23:06:53 +0000 | [diff] [blame] | 9 | ... |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 10 | |
Andrew M. Kuchling | d0939fa | 2000-06-10 23:06:53 +0000 | [diff] [blame] | 11 | """ |
| 12 | |
Andrew M. Kuchling | d0939fa | 2000-06-10 23:06:53 +0000 | [diff] [blame] | 13 | from _curses import * |
Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 14 | import os as _os |
Christian Heimes | 836baa5 | 2008-02-26 08:18:30 +0000 | [diff] [blame] | 15 | import sys as _sys |
Andrew M. Kuchling | d0939fa | 2000-06-10 23:06:53 +0000 | [diff] [blame] | 16 | |
Andrew M. Kuchling | 289d9d4 | 2000-06-26 23:54:03 +0000 | [diff] [blame] | 17 | # Some constants, most notably the ACS_* ones, are only added to the C |
| 18 | # _curses module's dictionary after initscr() is called. (Some |
| 19 | # versions of SGI's curses don't define values for those constants |
| 20 | # until initscr() has been called.) This wrapper function calls the |
| 21 | # underlying C initscr(), and then copies the constants from the |
| 22 | # _curses module to the curses package's dictionary. Don't do 'from |
| 23 | # curses import *' if you'll be needing the ACS_* constants. |
| 24 | |
| 25 | def initscr(): |
| 26 | import _curses, curses |
Christian Heimes | 8640e74 | 2008-02-23 16:23:06 +0000 | [diff] [blame] | 27 | # we call setupterm() here because it raises an error |
| 28 | # instead of calling exit() in error cases. |
Christian Heimes | 836baa5 | 2008-02-26 08:18:30 +0000 | [diff] [blame] | 29 | setupterm(term=_os.environ.get("TERM", "unknown"), |
| 30 | fd=_sys.__stdout__.fileno()) |
Andrew M. Kuchling | 289d9d4 | 2000-06-26 23:54:03 +0000 | [diff] [blame] | 31 | stdscr = _curses.initscr() |
| 32 | for key, value in _curses.__dict__.items(): |
| 33 | if key[0:4] == 'ACS_' or key in ('LINES', 'COLS'): |
| 34 | setattr(curses, key, value) |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 35 | |
Andrew M. Kuchling | 289d9d4 | 2000-06-26 23:54:03 +0000 | [diff] [blame] | 36 | return stdscr |
Andrew M. Kuchling | d0939fa | 2000-06-10 23:06:53 +0000 | [diff] [blame] | 37 | |
Andrew M. Kuchling | 37f0263 | 2001-04-05 16:08:41 +0000 | [diff] [blame] | 38 | # This is a similar wrapper for start_color(), which adds the COLORS and |
| 39 | # COLOR_PAIRS variables which are only available after start_color() is |
| 40 | # called. |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 41 | |
Andrew M. Kuchling | 37f0263 | 2001-04-05 16:08:41 +0000 | [diff] [blame] | 42 | def start_color(): |
| 43 | import _curses, curses |
| 44 | retval = _curses.start_color() |
| 45 | if hasattr(_curses, 'COLORS'): |
| 46 | curses.COLORS = _curses.COLORS |
| 47 | if hasattr(_curses, 'COLOR_PAIRS'): |
| 48 | curses.COLOR_PAIRS = _curses.COLOR_PAIRS |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 49 | return retval |
Andrew M. Kuchling | 37f0263 | 2001-04-05 16:08:41 +0000 | [diff] [blame] | 50 | |
Andrew M. Kuchling | b45bd32 | 2000-08-01 01:21:11 +0000 | [diff] [blame] | 51 | # Import Python has_key() implementation if _curses doesn't contain has_key() |
| 52 | |
| 53 | try: |
| 54 | has_key |
| 55 | except NameError: |
Victor Stinner | b9bb1f4 | 2011-11-29 00:03:50 +0100 | [diff] [blame] | 56 | from .has_key import has_key |
R David Murray | afc9a5e | 2011-06-18 20:21:09 -0400 | [diff] [blame] | 57 | |
| 58 | # Wrapper for the entire curses-based application. Runs a function which |
| 59 | # should be the rest of your curses-based application. If the application |
| 60 | # raises an exception, wrapper() will restore the terminal to a sane state so |
| 61 | # you can read the resulting traceback. |
| 62 | |
| 63 | def wrapper(func, *args, **kwds): |
| 64 | """Wrapper function that initializes curses and calls another function, |
| 65 | restoring normal keyboard/screen behavior on error. |
| 66 | The callable object 'func' is then passed the main window 'stdscr' |
| 67 | as its first argument, followed by any other arguments passed to |
| 68 | wrapper(). |
| 69 | """ |
| 70 | |
| 71 | try: |
| 72 | # Initialize curses |
| 73 | stdscr = initscr() |
| 74 | |
| 75 | # Turn off echoing of keys, and enter cbreak mode, |
| 76 | # where no buffering is performed on keyboard input |
| 77 | noecho() |
| 78 | cbreak() |
| 79 | |
| 80 | # In keypad mode, escape sequences for special keys |
| 81 | # (like the cursor keys) will be interpreted and |
| 82 | # a special value like curses.KEY_LEFT will be returned |
| 83 | stdscr.keypad(1) |
| 84 | |
| 85 | # Start color, too. Harmless if the terminal doesn't have |
| 86 | # color; user can test with has_color() later on. The try/catch |
| 87 | # works around a minor bit of over-conscientiousness in the curses |
| 88 | # module -- the error return from C start_color() is ignorable. |
| 89 | try: |
| 90 | start_color() |
| 91 | except: |
| 92 | pass |
| 93 | |
| 94 | return func(stdscr, *args, **kwds) |
| 95 | finally: |
| 96 | # Set everything back to normal |
| 97 | if 'stdscr' in locals(): |
| 98 | stdscr.keypad(0) |
| 99 | echo() |
| 100 | nocbreak() |
| 101 | endwin() |