如何编写代码实现自动补全单词和句子?

46 投票
6 回答
84966 浏览
提问于 2025-04-17 04:37

我想写一段代码,让Linux终端能够自动补全输入的内容。这个代码应该这样工作。

它有一个字符串列表,比如“hello”,“hi”,“how are you”,“goodbye”,“great”等等。

在终端中,用户开始输入时,如果有可能匹配的内容,就会显示出可能的字符串提示,用户可以从中选择(就像在vim编辑器谷歌增量搜索中那样)。

例如,用户开始输入“h”,然后就会看到这样的提示:

h"ello"

_ "i"

_"ow are you"

更棒的是,如果它能从字符串的任意部分进行补全,而不仅仅是从开头开始,那就更好了。

6 个回答

9

你可能想看看这个叫做 fast-autocomplete 的工具:https://github.com/seperman/fast-autocomplete

它有一个演示模式,你可以在上面输入内容,系统会实时给你结果:https://zepworks.com/posts/you-autocomplete-me/#part-6-demo

使用起来非常简单:

>>> from fast_autocomplete import AutoComplete
>>> words = {'book': {}, 'burrito': {}, 'pizza': {}, 'pasta':{}}
>>> autocomplete = AutoComplete(words=words)
>>> autocomplete.search(word='b', max_cost=3, size=3)
[['book'], ['burrito']]
>>> autocomplete.search(word='bu', max_cost=3, size=3)
[['burrito']]
>>> autocomplete.search(word='barrito', max_cost=3, size=3)  # mis-spelling
[['burrito']]

免责声明:我是 fast-autocomplete 的作者。

9

要在Python命令行中启用自动补全功能,可以输入以下内容:

import rlcompleter, readline
readline.parse_and_bind('tab:complete')

(感谢 http://blog.e-shell.org/221

58

(我知道这不是你问的确切内容,但)如果你对在 TAB 键上出现的自动补全/建议感到满意(这在很多命令行中都很常见),那么你可以通过使用 readline 模块快速上手。

这里有一个简单的例子,基于 Doug Hellmann 关于 readline 的文章

import readline

class MyCompleter(object):  # Custom completer

    def __init__(self, options):
        self.options = sorted(options)

    def complete(self, text, state):
        if state == 0:  # on first trigger, build possible matches
            if text:  # cache matches (entries that start with entered text)
                self.matches = [s for s in self.options 
                                    if s and s.startswith(text)]
            else:  # no text entered, all matches possible
                self.matches = self.options[:]

        # return match indexed by state
        try: 
            return self.matches[state]
        except IndexError:
            return None

completer = MyCompleter(["hello", "hi", "how are you", "goodbye", "great"])
readline.set_completer(completer.complete)
readline.parse_and_bind('tab: complete')

input = raw_input("Input: ")
print "You entered", input

这会产生以下效果(<TAB> 表示按下了 Tab 键):

Input: <TAB><TAB>
goodbye      great        hello        hi           how are you

Input: h<TAB><TAB>
hello        hi           how are you

Input: ho<TAB>ow are you

在最后一行(输入了 HOTAB),只有一个可能的匹配项,整个句子 "how are you" 被自动补全了。

想了解更多关于 readline 的信息,可以查看链接的文章。


“更好的效果是能够从字符串的任意部分完成单词,而不仅仅是从开头...”

这可以通过简单地修改补全函数中的匹配条件来实现,也就是说,从:

self.matches = [s for s in self.options 
                   if s and s.startswith(text)]

改成类似这样的:

self.matches = [s for s in self.options 
                   if text in s]

这样会产生以下效果:

Input: <TAB><TAB>
goodbye      great        hello        hi           how are you

Input: o<TAB><TAB>
goodbye      hello        how are you

更新:使用历史缓冲区(如评论中提到的)

创建一个伪菜单来滚动/搜索的简单方法是将关键词加载到历史缓冲区中。这样你就可以使用上下箭头键滚动浏览条目,还可以使用 Ctrl+R 进行反向搜索。

要尝试这个,可以做以下更改:

keywords = ["hello", "hi", "how are you", "goodbye", "great"]
completer = MyCompleter(keywords)
readline.set_completer(completer.complete)
readline.parse_and_bind('tab: complete')
for kw in keywords:
    readline.add_history(kw)

input = raw_input("Input: ")
print "You entered", input

运行脚本时,尝试先按 Ctrl+r 然后输入 a。这会返回第一个包含 "a" 的匹配项。再按一次 Ctrl+r 会得到下一个匹配项。要选择一个条目,按 ENTER

还可以尝试使用上下键来浏览关键词。

撰写回答