Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | """Word completion for GNU readline 2.0. |
2 | ||
3 | This requires the latest extension to the readline module. The completer | |
4 | completes keywords, built-ins and globals in a selectable namespace (which | |
5 | defaults to __main__); when completing NAME.NAME..., it evaluates (!) the | |
6 | expression up to the last dot and completes its attributes. | |
7 | ||
8 | It's very cool to do "import sys" type "sys.", hit the | |
9 | completion key (twice), and see the list of names defined by the | |
10 | sys module! | |
11 | ||
12 | Tip: to use the tab key as the completion key, call | |
13 | ||
14 | readline.parse_and_bind("tab: complete") | |
15 | ||
16 | Notes: | |
17 | ||
18 | - Exceptions raised by the completer function are *ignored* (and | |
19 | generally cause the completion to fail). This is a feature -- since | |
20 | readline sets the tty device in raw (or cbreak) mode, printing a | |
21 | traceback wouldn't work well without some complicated hoopla to save, | |
22 | reset and restore the tty state. | |
23 | ||
24 | - The evaluation of the NAME.NAME... form may cause arbitrary | |
25 | application defined code to be executed if an object with a | |
26 | __getattr__ hook is found. Since it is the responsibility of the | |
27 | application (or the user) to enable this feature, I consider this an | |
28 | acceptable risk. More complicated expressions (e.g. function calls or | |
29 | indexing operations) are *not* evaluated. | |
30 | ||
31 | - GNU readline is also used by the built-in functions input() and | |
32 | raw_input(), and thus these also benefit/suffer from the completer | |
33 | features. Clearly an interactive application can benefit by | |
34 | specifying its own completer function and using raw_input() for all | |
35 | its input. | |
36 | ||
37 | - When the original stdin is not a tty device, GNU readline is never | |
38 | used, and this module (and the readline module) are silently inactive. | |
39 | ||
40 | """ | |
41 | ||
42 | import readline | |
43 | import __builtin__ | |
44 | import __main__ | |
45 | ||
46 | __all__ = ["Completer"] | |
47 | ||
48 | class Completer: | |
49 | def __init__(self, namespace = None): | |
50 | """Create a new completer for the command line. | |
51 | ||
52 | Completer([namespace]) -> completer instance. | |
53 | ||
54 | If unspecified, the default namespace where completions are performed | |
55 | is __main__ (technically, __main__.__dict__). Namespaces should be | |
56 | given as dictionaries. | |
57 | ||
58 | Completer instances should be used as the completion mechanism of | |
59 | readline via the set_completer() call: | |
60 | ||
61 | readline.set_completer(Completer(my_namespace).complete) | |
62 | """ | |
63 | ||
64 | if namespace and not isinstance(namespace, dict): | |
65 | raise TypeError,'namespace must be a dictionary' | |
66 | ||
67 | # Don't bind to namespace quite yet, but flag whether the user wants a | |
68 | # specific namespace or to use __main__.__dict__. This will allow us | |
69 | # to bind to __main__.__dict__ at completion time, not now. | |
70 | if namespace is None: | |
71 | self.use_main_ns = 1 | |
72 | else: | |
73 | self.use_main_ns = 0 | |
74 | self.namespace = namespace | |
75 | ||
76 | def complete(self, text, state): | |
77 | """Return the next possible completion for 'text'. | |
78 | ||
79 | This is called successively with state == 0, 1, 2, ... until it | |
80 | returns None. The completion should begin with 'text'. | |
81 | ||
82 | """ | |
83 | if self.use_main_ns: | |
84 | self.namespace = __main__.__dict__ | |
85 | ||
86 | if state == 0: | |
87 | if "." in text: | |
88 | self.matches = self.attr_matches(text) | |
89 | else: | |
90 | self.matches = self.global_matches(text) | |
91 | try: | |
92 | return self.matches[state] | |
93 | except IndexError: | |
94 | return None | |
95 | ||
96 | def global_matches(self, text): | |
97 | """Compute matches when text is a simple name. | |
98 | ||
99 | Return a list of all keywords, built-in functions and names currently | |
100 | defined in self.namespace that match. | |
101 | ||
102 | """ | |
103 | import keyword | |
104 | matches = [] | |
105 | n = len(text) | |
106 | for list in [keyword.kwlist, | |
107 | __builtin__.__dict__, | |
108 | self.namespace]: | |
109 | for word in list: | |
110 | if word[:n] == text and word != "__builtins__": | |
111 | matches.append(word) | |
112 | return matches | |
113 | ||
114 | def attr_matches(self, text): | |
115 | """Compute matches when text contains a dot. | |
116 | ||
117 | Assuming the text is of the form NAME.NAME....[NAME], and is | |
118 | evaluatable in self.namespace, it will be evaluated and its attributes | |
119 | (as revealed by dir()) are used as possible completions. (For class | |
120 | instances, class members are also considered.) | |
121 | ||
122 | WARNING: this can still invoke arbitrary C code, if an object | |
123 | with a __getattr__ hook is evaluated. | |
124 | ||
125 | """ | |
126 | import re | |
127 | m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) | |
128 | if not m: | |
129 | return | |
130 | expr, attr = m.group(1, 3) | |
131 | object = eval(expr, self.namespace) | |
132 | words = dir(object) | |
133 | if hasattr(object,'__class__'): | |
134 | words.append('__class__') | |
135 | words = words + get_class_members(object.__class__) | |
136 | matches = [] | |
137 | n = len(attr) | |
138 | for word in words: | |
139 | if word[:n] == attr and word != "__builtins__": | |
140 | matches.append("%s.%s" % (expr, word)) | |
141 | return matches | |
142 | ||
143 | def get_class_members(klass): | |
144 | ret = dir(klass) | |
145 | if hasattr(klass,'__bases__'): | |
146 | for base in klass.__bases__: | |
147 | ret = ret + get_class_members(base) | |
148 | return ret | |
149 | ||
150 | readline.set_completer(Completer().complete) |