"""Word completion for GNU readline 2.0.

This requires the latest extension to the readline module (the
set_completer() function).  When completing a simple identifier, it
completes keywords, built-ins and globals in __main__; when completing
NAME.NAME..., it evaluates (!) the expression up to the last dot and
completes its attributes.

It's very cool to do "import string" type "string.", hit the
completion key (twice), and see the list of names defined by the
string module!

Tip: to use the tab key as the completion key, call

    readline.parse_and_bind("tab: complete")

Notes:

- Exceptions raised by the completer function are *ignored* (and
generally cause the completion to fail).  This is a feature -- since
readline sets the tty device in raw (or cbreak) mode, printing a
traceback wouldn't work well without some complicated hoopla to save,
reset and restore the tty state.

- The evaluation of the NAME.NAME... form may cause arbitrary
application defined code to be executed if an object with a
__getattr__ hook is found.  Since it is the responsibility of the
application (or the user) to enable this feature, I consider this an
acceptable risk.  More complicated expressions (e.g. function calls or
indexing operations) are *not* evaluated.

- GNU readline is also used by the built-in functions input() and
raw_input(), and thus these also benefit/suffer from the completer
features.  Clearly an interactive application can benefit by
specifying its own completer function and using raw_input() for all
its input.

- When the original stdin is not a tty device, GNU readline is never
used, and this module (and the readline module) are silently inactive.

"""

import readline
import keyword
import __builtin__
import __main__
import string
import re
import traceback

class Completer:

    def complete(self, text, state):
	"""Return the next possible completion for 'text'.

	This is called successively with state == 0, 1, 2, ... until it
	returns None.  The completion should begin with 'text'.

	"""
	if state == 0:
	    if "." in text:
		self.matches = self.attr_matches(text)
	    else:
		self.matches = self.global_matches(text)
	return self.matches[state]

    def global_matches(self, text):
	"""Compute matches when text is a simple name.

	Return a list of all keywords, built-in functions and names
	currently defines in __main__ that match.

	"""
	matches = []
	n = len(text)
	for list in [keyword.kwlist,
		     __builtin__.__dict__.keys(),
		     __main__.__dict__.keys()]:
	    for word in list:
		if word[:n] == text:
		    matches.append(word)
	return matches

    def attr_matches(self, text):
	"""Compute matches when text contains a dot.

	Assuming the text is of the form NAME.NAME....[NAME], and is
	evaluabable in the globals of __main__, it will be evaluated
	and its attributes (as revealed by dir()) are used as possible
	completions.

	WARNING: this can still invoke arbitrary C code, if an object
	with a __getattr__ hook is evaluated.

	"""
	m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
	if not m:
	    return
	expr, attr = m.group(1, 3)
	words = dir(eval(expr, __main__.__dict__))
	matches = []
	n = len(attr)
	for word in words:
	    if word[:n] == attr:
		matches.append("%s.%s" % (expr, word))
	return matches

readline.set_completer(Completer().complete)
