• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""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
206