您好的编码人员和勇敢的GNU-readline用户,
几个月前,我开始对我编写的类似shell的应用程序使用Python的(2.7.1)readline模块。该应用程序与文件和文件系统无关-它是专有管理软件的量身定制的解决方案。

昨天,我发现特定文本会导致意外的自动完成行为,并且尚未在documentation中找到解决此问题的方法。我很想在这里寻求您的帮助。我将从一个示例开始,然后跟随一个可重现不需要的行为的代码段。

提供自动完成的值是:

aaa0   aaa1   aaa2   bbb_0  bbb_1  bbb_2
ccc-0  ccc-1  ccc-2  ddd?0  ddd?1  ddd?2

...然后,异常行为如下(每个 Action 之后是结果输出,并且管道|符号代表光标):
  • 键入“b”。Input> b|
  • 按TAB键(在我的配置中,该键绑定(bind)到自动完成操作)。Input> bbb_|
  • 再次按TAB键。您的文本将保持不变,但是您会收到以下提示:bbb_0 bbb_1 bbb_2
    Input> bbb_|
  • 键入“0”,然后按TAB键。bbb_0 bbb_1 bbb_2
    Input> bbb_0 |
    注意“0”字符和光标之间的空格(下面的代码片段将对此进行解释)。
    到目前为止,一切都很好,并尝试使用“a”将导致类似的输出,只是没有下划线(aaa0,aaa1,aaa2)。
  • 重新开始,然后输入“c”。Input> c
  • 按TAB键。Input> ccc-
  • 再次按TAB键。aaa0 aaa1 aaa2 bbb_0 bbb_1 bbb_2 ccc-0 ccc-1 ccc-2 ddd?0 ddd?1 ddd?2
    Input> ccc-|
    这是我问题的上半部分。显示所有值,而不是仅显示以“ccc-”开头的值。
  • 键入“0”,然后按TAB键。aaa0 aaa1 aaa2 bbb_0 bbb_1 bbb_2 ccc-0 ccc-1 ccc-2 ddd?0 ddd?1 ddd?2
    Input> ccc-0|
    这是我问题的后半部分,您会看到,'0'字符和光标之间没有空格(同样,下面的代码段将解释为什么要在其中留有空格)。实际上,按TAB既不会更改文本,也不会显示提示,并且进一步按TAB的行为相同。

  • 实际上,在步骤7中发生的事情是一种误解。如果您尝试自动填充“ddd?”,则Readline会将“-”字符连字符错误(如果问号“?”字符也是如此),其他常见的单词分隔符例如:空格,制表符,“=”)。因此,由于当前的行缓冲区以单词分隔符结尾,所以是时候输入一个新单词了,对吧?因此,在第7步(即我们所在的位置)中,按TAB键将显示所有值。

    在步骤8中,一旦该行看起来像“Input> ccc-0|”,则按TAB键无效,因为破折号是一个单词分隔符,将行分隔为两个单词:“ccc”和“0”。因此,要完成的单词为'0',但是可惜的是,所有可能的值都不以'0'开头,因此无效。

    现在,可悲的是,这里没有对与错。例如,在我的应用程序中,等号'='实际上是单词分隔符,而连字符'-'不是。 我想这一定是配置问题,但是我还没有找到配置哪个字符分隔单词的方法。这就是我需要的帮助。

    我是我忠实的人,所以这是我 promise 的代码段:
    import readline
    values = ['aaa0',  'aaa1',  'aaa2',  'bbb_0', 'bbb_1', 'bbb_2',
              'ccc-0', 'ccc-1', 'ccc-2', 'ddd?0', 'ddd?1', 'ddd?2']
    def complete(text, state):
        matches = [v for v in values if v.startswith(text)]
        if len(matches) == 1 and matches[0] == text:
            # Add space if the current text is the same as the only match
            return "{} ".format(matches[0]) if state == 0 else None
        if state >= len(matches):
            return None
        return matches[state]
    readline.set_completer(complete)
    for line in ("tab: complete", "set show-all-if-unmodified on"):
        readline.parse_and_bind(line)
    raw_input("Input> ")
    

    男孩和女孩,请-帮助!我保证会非常感激,甚至返回您的青睐。 :)

    首先十分感谢,
    嫩农G

    最佳答案

    仅查看dir(readline)的输出,函数get_completer_delims()set_completer_delims()看起来可能有用。实际上,readline模块的文档包括:

    set_completer_delims(...)
        set_completer_delims(string) -> None
        set the readline word delimiters for tab-completion
    

    我认为这正是您想要的。这是在Python 2.6.7上;如果您运行的是早期版本,则可能无法使用此功能。

    关于Python + readline +自动完成(标签): why are dashes and question-marks treated as word-separators?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7518743/

    10-11 08:45