blob: bca4a7bc5218a90d7ad145ae1d57e9eb489daeda [file] [log] [blame]
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001"""Word completion for GNU readline.
2
3The completer completes keywords, built-ins and globals in a selectable
4namespace (which defaults to __main__); when completing NAME.NAME..., it
5evaluates (!) the expression up to the last dot and completes its attributes.
6
7It's very cool to do "import sys" type "sys.", hit the completion key (twice),
8and see the list of names defined by the sys module!
9
10Tip: to use the tab key as the completion key, call
11
12 readline.parse_and_bind("tab: complete")
13
14Notes:
15
16- Exceptions raised by the completer function are *ignored* (and generally cause
17 the completion to fail). This is a feature -- since readline sets the tty
18 device in raw (or cbreak) mode, printing a traceback wouldn't work well
19 without some complicated hoopla to save, reset and restore the tty state.
20
21- The evaluation of the NAME.NAME... form may cause arbitrary application
22 defined code to be executed if an object with a __getattr__ hook is found.
23 Since it is the responsibility of the application (or the user) to enable this
24 feature, I consider this an acceptable risk. More complicated expressions
25 (e.g. function calls or indexing operations) are *not* evaluated.
26
27- When the original stdin is not a tty device, GNU readline is never
28 used, and this module (and the readline module) are silently inactive.
29
30"""
31
32import atexit
33import builtins
34import __main__
35
36__all__ = ["Completer"]
37
38class Completer:
39 def __init__(self, namespace = None):
40 """Create a new completer for the command line.
41
42 Completer([namespace]) -> completer instance.
43
44 If unspecified, the default namespace where completions are performed
45 is __main__ (technically, __main__.__dict__). Namespaces should be
46 given as dictionaries.
47
48 Completer instances should be used as the completion mechanism of
49 readline via the set_completer() call:
50
51 readline.set_completer(Completer(my_namespace).complete)
52 """
53
54 if namespace and not isinstance(namespace, dict):
55 raise TypeError('namespace must be a dictionary')
56
57 # Don't bind to namespace quite yet, but flag whether the user wants a
58 # specific namespace or to use __main__.__dict__. This will allow us
59 # to bind to __main__.__dict__ at completion time, not now.
60 if namespace is None:
61 self.use_main_ns = 1
62 else:
63 self.use_main_ns = 0
64 self.namespace = namespace
65
66 def complete(self, text, state):
67 """Return the next possible completion for 'text'.
68
69 This is called successively with state == 0, 1, 2, ... until it
70 returns None. The completion should begin with 'text'.
71
72 """
73 if self.use_main_ns:
74 self.namespace = __main__.__dict__
75
76 if not text.strip():
77 if state == 0:
78 if _readline_available:
79 readline.insert_text('\t')
80 readline.redisplay()
81 return ''
82 else:
83 return '\t'
84 else:
85 return None
86
87 if state == 0:
88 if "." in text:
89 self.matches = self.attr_matches(text)
90 else:
91 self.matches = self.global_matches(text)
92 try:
93 return self.matches[state]
94 except IndexError:
95 return None
96
97 def _callable_postfix(self, val, word):
98 if callable(val):
99 word = word + "("
100 return word
101
102 def global_matches(self, text):
103 """Compute matches when text is a simple name.
104
105 Return a list of all keywords, built-in functions and names currently
106 defined in self.namespace that match.
107
108 """
109 import keyword
110 matches = []
111 seen = {"__builtins__"}
112 n = len(text)
113 for word in keyword.kwlist:
114 if word[:n] == text:
115 seen.add(word)
116 if word in {'finally', 'try'}:
117 word = word + ':'
118 elif word not in {'False', 'None', 'True',
119 'break', 'continue', 'pass',
120 'else'}:
121 word = word + ' '
122 matches.append(word)
123 for nspace in [self.namespace, builtins.__dict__]:
124 for word, val in nspace.items():
125 if word[:n] == text and word not in seen:
126 seen.add(word)
127 matches.append(self._callable_postfix(val, word))
128 return matches
129
130 def attr_matches(self, text):
131 """Compute matches when text contains a dot.
132
133 Assuming the text is of the form NAME.NAME....[NAME], and is
134 evaluable in self.namespace, it will be evaluated and its attributes
135 (as revealed by dir()) are used as possible completions. (For class
136 instances, class members are also considered.)
137
138 WARNING: this can still invoke arbitrary C code, if an object
139 with a __getattr__ hook is evaluated.
140
141 """
142 import re
143 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
144 if not m:
145 return []
146 expr, attr = m.group(1, 3)
147 try:
148 thisobject = eval(expr, self.namespace)
149 except Exception:
150 return []
151
152 # get the content of the object, except __builtins__
153 words = set(dir(thisobject))
154 words.discard("__builtins__")
155
156 if hasattr(thisobject, '__class__'):
157 words.add('__class__')
158 words.update(get_class_members(thisobject.__class__))
159 matches = []
160 n = len(attr)
161 if attr == '':
162 noprefix = '_'
163 elif attr == '_':
164 noprefix = '__'
165 else:
166 noprefix = None
167 while True:
168 for word in words:
169 if (word[:n] == attr and
170 not (noprefix and word[:n+1] == noprefix)):
171 match = "%s.%s" % (expr, word)
172 try:
173 val = getattr(thisobject, word)
174 except Exception:
175 pass # Include even if attribute not set
176 else:
177 match = self._callable_postfix(val, match)
178 matches.append(match)
179 if matches or not noprefix:
180 break
181 if noprefix == '_':
182 noprefix = '__'
183 else:
184 noprefix = None
185 matches.sort()
186 return matches
187
188def get_class_members(klass):
189 ret = dir(klass)
190 if hasattr(klass,'__bases__'):
191 for base in klass.__bases__:
192 ret = ret + get_class_members(base)
193 return ret
194
195try:
196 import readline
197except ImportError:
198 _readline_available = False
199else:
200 readline.set_completer(Completer().complete)
201 # Release references early at shutdown (the readline module's
202 # contents are quasi-immortal, and the completer function holds a
203 # reference to globals).
204 atexit.register(lambda: readline.set_completer(None))
205 _readline_available = True