Show More
@@ -1,198 +1,199 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """Word completion for GNU readline 2.0. |
|
3 | 3 | |
|
4 | 4 | --------------------------------------------------------------------------- |
|
5 | 5 | NOTE: This version is a re-implementation of rlcompleter with selectable |
|
6 | 6 | namespace. |
|
7 | 7 | |
|
8 | 8 | The problem with rlcompleter is that it's hardwired to work with |
|
9 | 9 | __main__.__dict__, and in some cases one may have 'sandboxed' namespaces. So |
|
10 | 10 | this class is a ripoff of rlcompleter, with the namespace to work in as an |
|
11 | 11 | optional parameter. |
|
12 | 12 | |
|
13 | 13 | This class can be used just like rlcompleter, but the Completer class now has |
|
14 | 14 | a constructor with the optional 'namespace' parameter. |
|
15 | 15 | |
|
16 | 16 | A patch has been submitted to Python@sourceforge for these changes to go in |
|
17 | 17 | the standard Python distribution. |
|
18 | 18 | |
|
19 | 19 | The patch went in for Python 2.3. Once IPython drops support for Python 2.2, |
|
20 | 20 | this file can be significantly reduced. |
|
21 | 21 | --------------------------------------------------------------------------- |
|
22 | 22 | |
|
23 | 23 | Original rlcompleter documentation: |
|
24 | 24 | |
|
25 | 25 | This requires the latest extension to the readline module (the |
|
26 | 26 | completes keywords, built-ins and globals in __main__; when completing |
|
27 | 27 | NAME.NAME..., it evaluates (!) the expression up to the last dot and |
|
28 | 28 | completes its attributes. |
|
29 | 29 | |
|
30 | 30 | It's very cool to do "import string" type "string.", hit the |
|
31 | 31 | completion key (twice), and see the list of names defined by the |
|
32 | 32 | string module! |
|
33 | 33 | |
|
34 | 34 | Tip: to use the tab key as the completion key, call |
|
35 | 35 | |
|
36 | 36 | readline.parse_and_bind("tab: complete") |
|
37 | 37 | |
|
38 | 38 | Notes: |
|
39 | 39 | |
|
40 | 40 | - Exceptions raised by the completer function are *ignored* (and |
|
41 | 41 | generally cause the completion to fail). This is a feature -- since |
|
42 | 42 | readline sets the tty device in raw (or cbreak) mode, printing a |
|
43 | 43 | traceback wouldn't work well without some complicated hoopla to save, |
|
44 | 44 | reset and restore the tty state. |
|
45 | 45 | |
|
46 | 46 | - The evaluation of the NAME.NAME... form may cause arbitrary |
|
47 | 47 | application defined code to be executed if an object with a |
|
48 | 48 | __getattr__ hook is found. Since it is the responsibility of the |
|
49 | 49 | application (or the user) to enable this feature, I consider this an |
|
50 | 50 | acceptable risk. More complicated expressions (e.g. function calls or |
|
51 | 51 | indexing operations) are *not* evaluated. |
|
52 | 52 | |
|
53 | 53 | - GNU readline is also used by the built-in functions input() and |
|
54 | 54 | raw_input(), and thus these also benefit/suffer from the completer |
|
55 | 55 | features. Clearly an interactive application can benefit by |
|
56 | 56 | specifying its own completer function and using raw_input() for all |
|
57 | 57 | its input. |
|
58 | 58 | |
|
59 | 59 | - When the original stdin is not a tty device, GNU readline is never |
|
60 | 60 | used, and this module (and the readline module) are silently inactive. |
|
61 | 61 | |
|
62 | 62 | """ |
|
63 | 63 | |
|
64 | 64 | #***************************************************************************** |
|
65 | 65 | # |
|
66 | 66 | # Since this file is essentially a minimally modified copy of the rlcompleter |
|
67 | 67 | # module which is part of the standard Python distribution, I assume that the |
|
68 | 68 | # proper procedure is to maintain its copyright as belonging to the Python |
|
69 | 69 | # Software Foundation: |
|
70 | 70 | # |
|
71 | 71 | # Copyright (C) 2001 Python Software Foundation, www.python.org |
|
72 | 72 | # |
|
73 | 73 | # Distributed under the terms of the Python Software Foundation license. |
|
74 | 74 | # |
|
75 | 75 | # Full text available at: |
|
76 | 76 | # |
|
77 | 77 | # http://www.python.org/2.1/license.html |
|
78 | 78 | # |
|
79 | 79 | #***************************************************************************** |
|
80 | 80 | |
|
81 | 81 | import readline |
|
82 | 82 | import __builtin__ |
|
83 | 83 | import __main__ |
|
84 | 84 | |
|
85 | 85 | __all__ = ["Completer"] |
|
86 | 86 | |
|
87 | # declares Python 2.2 compatibility symbols: | |
|
88 | try: | |
|
89 | basestring | |
|
90 | except NameError: | |
|
91 | import types | |
|
92 | basestring = (types.StringType, types.UnicodeType) | |
|
93 | ||
|
87 | 94 | class Completer: |
|
88 | 95 | def __init__(self, namespace = None): |
|
89 | 96 | """Create a new completer for the command line. |
|
90 | 97 | |
|
91 | 98 | Completer([namespace]) -> completer instance. |
|
92 | 99 | |
|
93 | 100 | If unspecified, the default namespace where completions are performed |
|
94 | 101 | is __main__ (technically, __main__.__dict__). Namespaces should be |
|
95 | 102 | given as dictionaries. |
|
96 | 103 | |
|
97 | 104 | Completer instances should be used as the completion mechanism of |
|
98 | 105 | readline via the set_completer() call: |
|
99 | 106 | |
|
100 | 107 | readline.set_completer(Completer(my_namespace).complete) |
|
101 | 108 | """ |
|
102 | 109 | |
|
103 | 110 | if namespace and type(namespace) != type({}): |
|
104 | 111 | raise TypeError,'namespace must be a dictionary' |
|
105 | 112 | |
|
106 | 113 | # Don't bind to namespace quite yet, but flag whether the user wants a |
|
107 | 114 | # specific namespace or to use __main__.__dict__. This will allow us |
|
108 | 115 | # to bind to __main__.__dict__ at completion time, not now. |
|
109 | 116 | if namespace is None: |
|
110 | 117 | self.use_main_ns = 1 |
|
111 | 118 | else: |
|
112 | 119 | self.use_main_ns = 0 |
|
113 | 120 | self.namespace = namespace |
|
114 | 121 | |
|
115 | 122 | def complete(self, text, state): |
|
116 | 123 | """Return the next possible completion for 'text'. |
|
117 | 124 | |
|
118 | 125 | This is called successively with state == 0, 1, 2, ... until it |
|
119 | 126 | returns None. The completion should begin with 'text'. |
|
120 | 127 | |
|
121 | 128 | """ |
|
122 | 129 | if self.use_main_ns: |
|
123 | 130 | self.namespace = __main__.__dict__ |
|
124 | 131 | |
|
125 | 132 | if state == 0: |
|
126 | 133 | if "." in text: |
|
127 | 134 | self.matches = self.attr_matches(text) |
|
128 | 135 | else: |
|
129 | 136 | self.matches = self.global_matches(text) |
|
130 | 137 | try: |
|
131 | 138 | return self.matches[state] |
|
132 | 139 | except IndexError: |
|
133 | 140 | return None |
|
134 | 141 | |
|
135 | 142 | def global_matches(self, text): |
|
136 | 143 | """Compute matches when text is a simple name. |
|
137 | 144 | |
|
138 | 145 | Return a list of all keywords, built-in functions and names currently |
|
139 | 146 | defined in self.namespace that match. |
|
140 | 147 | |
|
141 | 148 | """ |
|
142 | 149 | import keyword |
|
143 | 150 | matches = [] |
|
144 | 151 | n = len(text) |
|
145 | 152 | for list in [keyword.kwlist, |
|
146 | 153 | __builtin__.__dict__.keys(), |
|
147 | 154 | self.namespace.keys()]: |
|
148 | 155 | for word in list: |
|
149 | 156 | if word[:n] == text and word != "__builtins__": |
|
150 | 157 | matches.append(word) |
|
151 | 158 | return matches |
|
152 | 159 | |
|
153 | 160 | def attr_matches(self, text): |
|
154 | 161 | """Compute matches when text contains a dot. |
|
155 | 162 | |
|
156 | 163 | Assuming the text is of the form NAME.NAME....[NAME], and is |
|
157 | 164 | evaluatable in self.namespace, it will be evaluated and its attributes |
|
158 | 165 | (as revealed by dir()) are used as possible completions. (For class |
|
159 | 166 | instances, class members are are also considered.) |
|
160 | 167 | |
|
161 | 168 | WARNING: this can still invoke arbitrary C code, if an object |
|
162 | 169 | with a __getattr__ hook is evaluated. |
|
163 | 170 | |
|
164 | 171 | """ |
|
165 | 172 | import re |
|
166 | 173 | |
|
167 | 174 | # Another option, seems to work great. Catches things like ''.<tab> |
|
168 | 175 | m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) |
|
169 | 176 | |
|
170 | 177 | if not m: |
|
171 | 178 | return [] |
|
172 | 179 | expr, attr = m.group(1, 3) |
|
173 | 180 | object = eval(expr, self.namespace) |
|
174 | words = dir(object) | |
|
181 | words = [w for w in dir(object) if isinstance(w, basestring)] | |
|
175 | 182 | if hasattr(object,'__class__'): |
|
176 | 183 | words.append('__class__') |
|
177 | 184 | words.extend(get_class_members(object.__class__)) |
|
178 | 185 | n = len(attr) |
|
179 | 186 | matches = [] |
|
180 | 187 | for word in words: |
|
181 | try: | |
|
182 | if word[:n] == attr and word != "__builtins__": | |
|
183 | matches.append("%s.%s" % (expr, word)) | |
|
184 | except: | |
|
185 | # some badly behaved objects pollute dir() with non-strings, | |
|
186 | # which cause the completion to fail. This way we skip the | |
|
187 | # bad entries and can still continue processing the others. | |
|
188 | pass | |
|
188 | if word[:n] == attr and word != "__builtins__": | |
|
189 | matches.append("%s.%s" % (expr, word)) | |
|
189 | 190 | return matches |
|
190 | 191 | |
|
191 | 192 | def get_class_members(klass): |
|
192 | 193 | ret = dir(klass) |
|
193 | 194 | if hasattr(klass,'__bases__'): |
|
194 | 195 | for base in klass.__bases__: |
|
195 | 196 | ret.extend(get_class_members(base)) |
|
196 | 197 | return ret |
|
197 | 198 | |
|
198 | 199 | readline.set_completer(Completer().complete) |
General Comments 0
You need to be logged in to leave comments.
Login now