python readline模块文件夹名称完成

时间:2015-10-08 14:14:11

标签: python linux python-2.7 cygwin readline

我正在尝试为我的某个程序实现文件夹名称完成,并且我正在使用readline模块。我写了一个Completer类(文件autocompletion.py):

import os.path
import readline


class Completer(object):

    def _match_path(self, text):
        text = readline.get_line_buffer()
        return DirectoryPathCompleter(text).completions()

    def complete(self, text, state):
        matches = self._match_path(text)
        try:
            return matches[state]
        except IndexError:
            return None


class DirectoryPathCompleter(object):

    def __init__(self, text):
        self.text = text

    def completions(self):
        path, rest = os.path.split(self.text)
        if rest == '.' or rest == '..':
            result = [rest + '/']
        else:
            result = [i + '/' for i in get_dirs_under(path) if i.startswith(rest)]
        return result


def get_dirs_under(path):
    if not path:
        path = '.'
    dirpath, dirnames, filenames = os.walk(path).next()
    return dirnames

在这里尝试这个是一个小脚本try_readline.py

#!/usr/bin/env python
from autocompletion import Completer
import readline

readline.parse_and_bind('tab: complete')
readline.set_completer(Completer().complete)
raw_input('Test it! > ')

我可以看到,只要我不尝试完成可以部分完成的dirnames,它就能很好地工作。当我创建一个具有以下结构的目录并通过shell运行程序时:

$ mkdir -p test/bla-foo test/bla-bar test/bla-baz test/something test/else
$ cp autocompletion.py try_readline.py test
$ cd test; tree
.
├── autocompletion.py
├── bla-bar
├── bla-baz
├── bla-foo
├── else
├── something
└── try_readline.py

5 directories, 2 files

$ python try_readline.py

我尝试通过TAB完成bla-,因此我得到bla-bla-。我希望完成时坚持使用bla-并显示可以完成的替代方案。

我怎样才能做到这一点?

修改

好的,我不知道为什么会发生这种情况。如果我将try_readline.py脚本更改为如下所示:

#!/usr/bin/env python
import readline

readline.parse_and_bind('tab: complete')
raw_input('Test it! > ')

所以我没有使用自己的Completer并且我在上面显示的相同文件夹结构上运行它,我可以看到类似的行为:

Test it! > bla-b<TAB>
Test it! > bla-bla-

我希望:

Test it! > bla-b<TAB>
Test it! > bla-ba<TAB><TAB>
bla-bar/ bla-baz/

EDIT2

好的我现在有另一种方法,花了这么长时间,因为readline文档非常稀疏..我仍然无法确切地知道为什么我必须这样做,但它的工作原理。

如果我查看readline正在使用的分隔符,我得到:

In [1]: readline.get_completer_delims()
Out[1]: ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'

特别是\\部分对我来说很奇怪,所以我确实在try_readline.py

中设置了新的分隔符
#!/usr/bin/env python
import readline
from autocompletion import Completer

readline.parse_and_bind('tab: complete')
readline.set_completer_delims(' \t\n')
raw_input('Test it! > ')

我现在正在使用标准的readline完成,因为我不知道如何编写正确的Completer ...我想重用标准的readline完成函数,只是过滤掉任何非目录但是我不知道如何从模块中提取它。

0 个答案:

没有答案