MacOS上Python REPL的Tab补全
在升级到Lion之前,我在终端的Python环境中可以使用Tab键自动补全。按照这些步骤,我成功地让Tab键补全功能正常工作。
但是自从升级到Lion后,我在Python的终端会话中就无法使用Tab键补全了。我完全按照之前的步骤操作,但还是不行。
我在想,Lion中的readline模块是不是有什么不同?现在连接到'tab:complete'选项似乎不再有效。我在想,是终端忽略了readline,还是Python本身的问题。
Python版本:2.7.1
编辑:
这里说的Tab键补全,意思是我可以像下面这样操作:
# django
import MyModel
MyModel.objects.a[TAB] # will complete to all()
2 个回答
由于它使用了libedit/editline,所以启用自动补全的语法有点不同。
你可以先通过输入以下命令来强制使用emacs的按键绑定(如果我没记错的话,这和readline是一样的):
readline.parse_and_bind("bind -e")
接着,你可以把TAB键设置为自动补全的功能(可以查看editrc的手册):
readline.parse_and_bind("bind '\t' rl_complete")
如果你想支持缩进并且有历史记录(这个可以在网上找到),它应该看起来像这样(除非我搞错了):
import readline,rlcompleter
### Indenting
class TabCompleter(rlcompleter.Completer):
"""Completer that supports indenting"""
def complete(self, text, state):
if not text:
return (' ', None)[state]
else:
return rlcompleter.Completer.complete(self, text, state)
readline.set_completer(TabCompleter().complete)
### Add autocompletion
if 'libedit' in readline.__doc__:
readline.parse_and_bind("bind -e")
readline.parse_and_bind("bind '\t' rl_complete")
else:
readline.parse_and_bind("tab: complete")
### Add history
import os
histfile = os.path.join(os.environ["HOME"], ".pyhist")
try:
readline.read_history_file(histfile)
except IOError:
pass
import atexit
atexit.register(readline.write_history_file, histfile)
del histfile
苹果的操作系统 OS X 并没有自带 GNU 的 readline
。不过,它提供了一个叫做 BSD libedit 的工具,这个工具有一个和 readline
兼容的接口。苹果自带的 Python 版本,以及从 python.org 下载的 64 位和 32 位 Python,都是用 libedit
构建的。问题在于,libedit
支持的命令和 readline
的命令完全不一样(你可以在这里查看相关讨论 这里)。传统的 32 位 python.org 安装包使用的是 GNU readline
,还有一些其他的第三方 Python 版本,比如 MacPorts,也使用这个工具。你可能之前用的就是这样的 Python,而不是最近的苹果版本。除了修改 Django,你还有几个选择:可以安装一个第三方的替代模块 readline;或者使用一个自带 GNU readline 的 Python。不过,建议你不要在 10.7 上使用 python.org 的 32 位版本,因为不幸的是,10.7 上的 Xcode 4 不再包含 gcc-4.0
和这些 Python 需要的 OS X 10.4u SDK,这些都是用来构建和安装带有 C 扩展模块的包的。
在 Python 启动文件中加入以下内容,可以为 libedit 接口和常规的 readline 模块启用 Tab 补全功能。关于 Python 启动文件的更多信息,请查看这里
import readline
import rlcompleter
if 'libedit' in readline.__doc__:
readline.parse_and_bind("bind ^I rl_complete")
else:
readline.parse_and_bind("tab: complete")