|
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 __builtin__ |
|
43 import __main__ |
|
44 |
|
45 __all__ = ["Completer"] |
|
46 |
|
47 class Completer: |
|
48 def __init__(self, namespace = None): |
|
49 """Create a new completer for the command line. |
|
50 |
|
51 Completer([namespace]) -> completer instance. |
|
52 |
|
53 If unspecified, the default namespace where completions are performed |
|
54 is __main__ (technically, __main__.__dict__). Namespaces should be |
|
55 given as dictionaries. |
|
56 |
|
57 Completer instances should be used as the completion mechanism of |
|
58 readline via the set_completer() call: |
|
59 |
|
60 readline.set_completer(Completer(my_namespace).complete) |
|
61 """ |
|
62 |
|
63 if namespace and not isinstance(namespace, dict): |
|
64 raise TypeError,'namespace must be a dictionary' |
|
65 |
|
66 # Don't bind to namespace quite yet, but flag whether the user wants a |
|
67 # specific namespace or to use __main__.__dict__. This will allow us |
|
68 # to bind to __main__.__dict__ at completion time, not now. |
|
69 if namespace is None: |
|
70 self.use_main_ns = 1 |
|
71 else: |
|
72 self.use_main_ns = 0 |
|
73 self.namespace = namespace |
|
74 |
|
75 def complete(self, text, state): |
|
76 """Return the next possible completion for 'text'. |
|
77 |
|
78 This is called successively with state == 0, 1, 2, ... until it |
|
79 returns None. The completion should begin with 'text'. |
|
80 |
|
81 """ |
|
82 if self.use_main_ns: |
|
83 self.namespace = __main__.__dict__ |
|
84 |
|
85 if state == 0: |
|
86 if "." in text: |
|
87 self.matches = self.attr_matches(text) |
|
88 else: |
|
89 self.matches = self.global_matches(text) |
|
90 try: |
|
91 return self.matches[state] |
|
92 except IndexError: |
|
93 return None |
|
94 |
|
95 def _callable_postfix(self, val, word): |
|
96 if hasattr(val, '__call__'): |
|
97 word = word + "(" |
|
98 return word |
|
99 |
|
100 def global_matches(self, text): |
|
101 """Compute matches when text is a simple name. |
|
102 |
|
103 Return a list of all keywords, built-in functions and names currently |
|
104 defined in self.namespace that match. |
|
105 |
|
106 """ |
|
107 import keyword |
|
108 matches = [] |
|
109 n = len(text) |
|
110 for word in keyword.kwlist: |
|
111 if word[:n] == text: |
|
112 matches.append(word) |
|
113 for nspace in [__builtin__.__dict__, self.namespace]: |
|
114 for word, val in nspace.items(): |
|
115 if word[:n] == text and word != "__builtins__": |
|
116 matches.append(self._callable_postfix(val, word)) |
|
117 return matches |
|
118 |
|
119 def attr_matches(self, text): |
|
120 """Compute matches when text contains a dot. |
|
121 |
|
122 Assuming the text is of the form NAME.NAME....[NAME], and is |
|
123 evaluatable in self.namespace, it will be evaluated and its attributes |
|
124 (as revealed by dir()) are used as possible completions. (For class |
|
125 instances, class members are also considered.) |
|
126 |
|
127 WARNING: this can still invoke arbitrary C code, if an object |
|
128 with a __getattr__ hook is evaluated. |
|
129 |
|
130 """ |
|
131 import re |
|
132 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) |
|
133 if not m: |
|
134 return [] |
|
135 expr, attr = m.group(1, 3) |
|
136 try: |
|
137 thisobject = eval(expr, self.namespace) |
|
138 except Exception: |
|
139 return [] |
|
140 |
|
141 # get the content of the object, except __builtins__ |
|
142 words = dir(thisobject) |
|
143 if "__builtins__" in words: |
|
144 words.remove("__builtins__") |
|
145 |
|
146 if hasattr(thisobject, '__class__'): |
|
147 words.append('__class__') |
|
148 words.extend(get_class_members(thisobject.__class__)) |
|
149 matches = [] |
|
150 n = len(attr) |
|
151 for word in words: |
|
152 if word[:n] == attr and hasattr(thisobject, word): |
|
153 val = getattr(thisobject, word) |
|
154 word = self._callable_postfix(val, "%s.%s" % (expr, word)) |
|
155 matches.append(word) |
|
156 return matches |
|
157 |
|
158 def get_class_members(klass): |
|
159 ret = dir(klass) |
|
160 if hasattr(klass,'__bases__'): |
|
161 for base in klass.__bases__: |
|
162 ret = ret + get_class_members(base) |
|
163 return ret |
|
164 |
|
165 try: |
|
166 import readline |
|
167 except ImportError: |
|
168 pass |
|
169 else: |
|
170 readline.set_completer(Completer().complete) |