10.8 Richer-Text I/O

The tools we have covered so far support the minimal subset of text I/O functionality that all platforms supply. Most platforms also offer richer-text I/O capabilities, such as responding to single keypresses (not just to entire lines of text) and showing text in any spot of the terminal (not just sequentially).

Python extensions and core Python modules let you access platform-specific functionality. Unfortunately, various platforms expose this functionality in different ways. To develop cross-platform Python programs with rich-text I/O functionality, you may need to wrap different modules uniformly, importing platform-specific modules conditionally (usually with the try/except idiom covered in Chapter 6).

10.8.1 The readline Module

The readline module wraps the GNU Readline Library. Readline lets the user edit text lines during interactive input, and also recall previous lines for further editing and re-entry. GNU Readline is widely installed on Unix-like platforms, and is available at http://cnswww.cns.cwru.edu/~chet/readline/rltop.html. A Windows port (http://starship.python.net/crew/kernr/) is available, but not widely deployed. Chris Gonnerman's module, Alternative Readline for Windows, implements a subset of Python's standard readline module (using a small dedicated .pyd file instead of GNU Readline) and can be freely downloaded from http://newcenturycomputers.net/projects/readline.html.

When either readline module is loaded, Python uses Readline for all line-oriented input, such as raw_input. The interactive Python interpreter always tries loading readline to enable line editing and recall for interactive sessions. You can call functions supplied by module readline to control advanced functionality, particularly the history functionality for recalling lines entered in previous sessions, and the completion functionality for context-sensitive completion of the word being entered. See http://cnswww.cns.cwru.edu/~chet/readline/rltop.html#Documentation for GNU Readline documentation, with details on configuration commands. Alternative Readline also supports history, but the completion-related functions it supplies are dummy ones: these functions don't perform any operation, and exist only for compatibility with GNU Readline.

get_history_length

get_history_length(  )

Returns the number of lines of history that are saved to the history file. When the returned value is less than 0, all lines in the history are saved.

parse_and_bind

parse_and_bind(readline_cmd)

Gives Readline a configuration command. To let the user hit Tab to request completion, call parse_and_bind('tab: complete'). See the GNU Readline documentation for other useful values of readline_cmd.

read_history_file

read_history_file(filename='~/.history')

Loads history lines from the text file whose name or path is filename.

read_init_file

read_init_file(filename=None)

Makes Readline load a text file, where each line is a configuration command. When filename is None, Readline loads the same file as last time.

set_completer

set_completer(f=None)

Sets the completion function. When f is None, Readline disables completion. Otherwise, when the user enters a partial word start and then hits Tab, Readline calls f(start,i), where i is an int, initially 0. f returns the ith possible word that begins with start, or None when there are no more. Readline calls f repeatedly, with i set to 0, 1, 2, ..., until f returns None.

set_history_length

set_history_length(x)

Sets the number of lines of history that are saved to the history file. When x is less than 0, all lines in the history are saved.

write_history_file

write_history_file(filename='~/.history')

Saves history lines to the text file whose name or path is filename.

An example of a completion function is in module rlcompleter. In an interactive interpreter session (or, more practically, in the startup file that the interpreter runs at the start of each interactive session, as covered in Chapter 3), you can enter:

import readline, rlcompleter
readline.parse_and_bind('tab: complete')

Now, for the rest of this interactive session, you can hit Tab during line editing and get completion for global names and object attributes.

10.8.2 Console I/O

Terminals today are most often text windows on a graphical screen. You may also use a true terminal or the console (main screen) of a personal computer in text mode. All kinds of terminals in use today support advanced text I/O functionality, but you access this functionality in platform-dependent ways. The curses package works only on Unix-like platforms (there are persistent rumors of Windows ports of it, but I've never found a working one). Modules msvcrt, WConio, and Console work only on Windows.

10.8.2.1 The curses package

The traditional Unix approach to advanced terminal I/O is named curses, for obscure historical reasons.[1] The Python package curses affords reasonably simple use, but still lets you exert detailed if control required. I cover a small subset of curses, enough to let you write programs with rich text I/O functionality. See also Eric Raymond's tutorial Curses Programming with Python, available at http://py-howto.sourceforge.net/curses/curses.html, for more information. Whenever I mention the screen in this section, I mean the screen of the terminal (for example, the text window of a terminal-emulator program).

[1] "curses" does describe well the typical utterances of programmers faced with this rich, complicated approach.

The simplest and most effective way to use curses is through the curses.wrapper module, which supplies a single function.

wrapper

wrapper(func,*args)

Performs curses initialization, calls func(stdscr,*args), performs curses finalization (setting the terminal back to normal behavior), and finally returns func's result. The first argument that wrapper passes to func is stdscr, an object of type curses.Window that represents the whole terminal screen. wrapper ensures that the terminal is set back to normal behavior, whether func terminates normally or by propagating an exception.

func should be a function that performs all the tasks in your program that may need curses functionality. In other words, func normally contains (or more commonly calls, directly or indirectly, functions containing) all of your program's functionality, save perhaps for some non-interactive initialization and/or finalization tasks.

curses models text and background colors of characters as character attributes. Colors available on the terminal are numbered from 0 to curses.COLORS. Function color_content takes a color number n as its argument, and returns a tuple (r,g,b) of integers between 0 and 1000 giving the amount of each primary color in n. Function color_pair takes a color number n as its argument, and returns an attribute code that you can pass to various methods of a curses.Window object in order to display text in that color.

curses lets you create multiple instances of type curses.Window, each corresponding to a rectangle on the screen. You can also create exotic variants, such as instances of Panel, which are polymorphic with Window but not tied to a fixed screen rectangle. You do not need such advanced functionality in simple curses programs: just use the Window object stdscr that curses.wrapper gives you. Call w.refresh( ) to ensure that changes made to any Window instance w, including stdscr, show up on screen. curses can buffer the changes until you call refresh. An instance w of Window supplies, among many others, the following frequently used methods.

addstr

w.addstr([y,x,]str[,attr])

Puts the characters in string str, with attribute attr, on w at the given coordinates (x,y), overwriting any previous contents. All curses functions and methods accept coordinate arguments in reverse order, with y (the row number) before x (the column number). If you omit y,x, addstr uses w's current cursor coordinates. If you omit attr, addstr uses w's current default attribute. In any case, addstr, when done adding the string, sets w's current cursor coordinates to the end of the string it has added.

clrtobot, clrtoeol

w.clrtobot(  )
w.clrtoeol(  )

clrtoeol writes blanks from w's current cursor coordinates to the end of the line. clrtobot, in addition, also blanks all lines lower down on the screen.

delch

w.delch([y,x])

Deletes one character from w at the given coordinates (x,y). If you omit the y,x arguments, delch uses w's current cursor coordinates. In any case, delch does not change w's current cursor coordinates. All the following characters in line y, if any, shift left by one.

deleteln

w.deleteln(  )

Deletes from w the entire line at w's current cursor coordinates, and scrolls up by one line all lines lower down on the screen.

erase

w.erase(  )

Writes spaces to the entire terminal screen.

getch

w.getch(  )

Returns an integer c corresponding to a user keystroke. c between 0 and 255 represents an ordinary character, while c greater than 255 represents a special key. curses supplies names for special keys, so you can test c for equality with such readable constants as curses.KEY_HOME (the Home special key), curses.KEY_LEFT (the left-arrow special key), and so on. The list of all curses special-key names (about 100 of them) is in Python's free documentation, specifically, in the Python Library Reference, Section 6.13.3 Constants, for current versions of Python. If you have set window w to no-delay mode by calling w.nodelay(True), w.getch raises an exception if no keystroke is ready. By default, however, w.getch waits until the user hits a key.

getyx

w.getyx(  )

Returns w's current cursor coordinates as a tuple (y,x).

insstr

w.insstr([y,x,]str[,attr])

Inserts the characters in string str, with attribute attr, on w at the given coordinates (x,y), shifting the rest of line rightwards. Any characters that shift beyond the end of line are dropped. If you omit y,x, insstr uses w's current cursor coordinates. If you omit attr, insstr uses w's current default attribute. In any case, when done inserting the string, insstr sets w's current cursor coordinates to the first character of the string it has inserted.

move

w.move(y,x)

Moves w's cursor to the given coordinates (x,y).

nodelay

w.nodelay(flag)

Sets w to no-delay mode when flag is true, resets w back to normal mode when flag is false. No-delay mode affects method w.getch.

refresh

w.refresh(  )

Updates window w on-screen with all changes the program has effected on w.

The curses.textpad module supplies the Textpad class, which lets you support advanced input.

Textpad

class Textpad(window)

Creates and returns an instance t of class Textpad that wraps the curses window instance window. Instance t has one frequently used method:

t.edit( )

Lets the user perform interactive editing on the contents of the window instance that t wraps. The editing session supports simple Emacs-like key bindings: normal characters overwrite the window's previous contents, arrow keys move the cursor, Ctrl-H deletes the character to the cursor's left. When the user hits Ctrl-G, the editing session ends, and edit returns the window's contents as a single string, with newlines as line separators.

10.8.2.2 The msvcrt module

The msvcrt module, available only on Windows, supplies functions that let Python programs access a few proprietary extras supplied by the Microsoft Visual C++'s runtime library msvcrt.dll. Some msvcrt functions let you read user input character by character, rather than reading a full line at a time.

getch, getche

getch(  )
getche(  )

Reads and returns one character from keyboard input, waiting if no character is yet available for reading. getche also echoes the character to screen (if printable), while getch doesn't. When the user presses a special key (arrows, function keys, etc.), it's seen as two characters: first a chr(0) or chr(224), then a second character that, together with the first one, defines what special key the user pressed. Here's how to find out what getch returns for any key:

import msvcrt
print "press z to exit, or any other key to see code"
while 1:
    c = msvcrt.getch(  )
    if c =  = 'z': break
    print "%d (%r)" % (c, c)
kbhit

kbhit(  )

Returns True when a character is available for reading (getch, if called, would return immediately), otherwise False (getch, if called, would wait).

ungetch

ungetch(c)

Ungets character c: the next call to getch or getche returns c. It's an error to call ungetch twice without intervening calls to getch or getche.

10.8.2.3 The WConio and Console modules

Two Windows-specific extension modules supply single-character keyboard input (like msvcrt) and the ability to paint characters in specified positions of the text screen. Chris Gonnerman's Windows Console I/O module is small, simple, and easy to use. Module WConio can be freely downloaded from http://newcenturycomputers.net/projects/wconio.html. Fredrik Lundh's Console module is very complete and functionally rich. Module Console can be freely downloaded from http://www.effbot.org/efflib/console/.



    Part III: Python Library and Extension Modules