Python 如何使用 GNU readline 库停止自动完成并使用正常选项卡

How to stop autocomplete and have normal tab with GNU readline library in Python

现在,我 运行 Python 2.7 中的以下代码:

import readline as rl
rl.parse_and_bind('set editing-mode vi') #allow for arrow keys to be used
rl.set_completer()
raw_input()

根据 thisrl.set_completer() 应该删除 completer 函数,我认为这会使选项卡正常工作。但是,Tab 键根本不起作用。

我也尝试过编写自己的函数并将其作为完成函数传递进来,但这也没有用。 (如果有人能找到一种方法使制表键正常工作,那也足够了。)

如何才能在 raw_input 中使用方向键,同时又能使用普通的制表符?

您可以使用

#allow for arrow keys to be used for raw_input.
readline.parse_and_bind('set editing-mode vi') 

#set the tab key to make 4 spaces
readline.parse_and_bind("TAB: '    '")

出于某种原因,使用 readline.parse_and_bind("TAB: '\t'") 导致 Python 使用了过多的 CPU 并且只会冻结屏幕,所以我不得不将其切换为使用空格。

rl.set_completer()

删除完成函数,但不删除 TAB 绑定。所以标签被吃掉了,但是当标签被传递给 "None function".

时什么也没做
readline.parse_and_bind("TAB: '\t'")

导致对底层完成函数的无限调用。

Read TAB -> Return TAB -> Read TAB …

最简单的方法,至少在这里测试时,是使用默认的 emacs 模式。如果只导入 readline 而未设置任何内容,则 read_raw 适用于方向键,而 TAB 导致 TAB。

如果这不是一个选项,请设置自定义完成函数。 (对 Python 3 的作用相同)。这也是很可能更安全的选择。

如果按 TAB 键调用完成函数。对于 one TAB 键,按 state 参数从 0 开始,每次调用函数时递增。当我们 return TAB 时,重要的是我们检查状态是 0否则会被调用一遍又一遍

我们还必须 return 文本,如果有的话,它会被 readline 吃掉。

简单示例:

#!/usr/bin/env python2.7

import readline

def rl_tab_expander():
    def completer(txt, state):
        if state == 0:
            return txt + '\t'

    return completer

readline.set_completer(rl_tab_expander())
readline.parse_and_bind('set editing-mode vi')

while 1:
    inp = raw_input("$ ")
    if inp.strip() in ('exit', 'q', 'quit'):
        break

检查原始测试

您可以使用日志文件。在这里,我们看看如果我们 return TAB 或者如果我们不按照上面的例子检查 state 在完成函数中会发生什么。我们将 state 的限制设置为 25,否则它会一直持续下去。

在一个控制台

运行 脚本 window 并在另一个控制台执行 tail -f /tmp/test-readline.log

#!/usr/bin/env python2.7

import readline
import logging

logging.basicConfig(filename = '/tmp/test-readline.log', level = logging.DEBUG)

def rl_tab_expander():
    def completer(txt, state):
        logging.debug("STATE: %2d TXT: %s", state, repr(txt))
        if state > 24:
            return None
        return txt + '\t'

    return completer

readline.set_completer(rl_tab_expander())
readline.parse_and_bind('set editing-mode vi')

while 1:
    inp = raw_input("$ ")
    if inp.strip() in ('exit', 'q', 'quit'):
        break

结果

DEBUG:root:STATE:         0 TXT: ''
DEBUG:root:STATE:         1 TXT: ''
DEBUG:root:STATE:         2 TXT: ''
...
DEBUG:root:STATE:        24 TXT: ''
DEBUG:root:STATE:        25 TXT: ''

如果不限制 state 级别,这将一直持续到程序被终止或者如果我们按 Ctrl+C 幸运的话。