📄 rlcomple.py
字号:
"""Word completion for GNU readline 2.0.This requires the latest extension to the readline module (theset_completer() function). When completing a simple identifier, itcompletes keywords, built-ins and globals in __main__; when completingNAME.NAME..., it evaluates (!) the expression up to the last dot andcompletes its attributes.It's very cool to do "import string" type "string.", hit thecompletion key (twice), and see the list of names defined by thestring module!Tip: to use the tab key as the completion key, call readline.parse_and_bind("tab: complete")Notes:- Exceptions raised by the completer function are *ignored* (andgenerally cause the completion to fail). This is a feature -- sincereadline sets the tty device in raw (or cbreak) mode, printing atraceback wouldn't work well without some complicated hoopla to save,reset and restore the tty state.- The evaluation of the NAME.NAME... form may cause arbitraryapplication defined code to be executed if an object with a__getattr__ hook is found. Since it is the responsibility of theapplication (or the user) to enable this feature, I consider this anacceptable risk. More complicated expressions (e.g. function calls orindexing operations) are *not* evaluated.- GNU readline is also used by the built-in functions input() andraw_input(), and thus these also benefit/suffer from the completerfeatures. Clearly an interactive application can benefit byspecifying its own completer function and using raw_input() for allits input.- When the original stdin is not a tty device, GNU readline is neverused, and this module (and the readline module) are silently inactive."""import readlineimport __builtin__import __main__class Completer: def complete(self, text, state): """Return the next possible completion for 'text'. This is called successively with state == 0, 1, 2, ... until it returns None. The completion should begin with 'text'. """ if state == 0: if "." in text: self.matches = self.attr_matches(text) else: self.matches = self.global_matches(text) try: return self.matches[state] except IndexError: return None def global_matches(self, text): """Compute matches when text is a simple name. Return a list of all keywords, built-in functions and names currently defines in __main__ that match. """ import keyword matches = [] n = len(text) for list in [keyword.kwlist, __builtin__.__dict__.keys(), __main__.__dict__.keys()]: for word in list: if word[:n] == text: matches.append(word) return matches def attr_matches(self, text): """Compute matches when text contains a dot. Assuming the text is of the form NAME.NAME....[NAME], and is evaluabable in the globals of __main__, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. WARNING: this can still invoke arbitrary C code, if an object with a __getattr__ hook is evaluated. """ import re m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) if not m: return expr, attr = m.group(1, 3) words = dir(eval(expr, __main__.__dict__)) matches = [] n = len(attr) for word in words: if word[:n] == attr: matches.append("%s.%s" % (expr, word)) return matchesreadline.set_completer(Completer().complete)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -