【问题标题】:How to write code to autocomplete words and sentences?如何编写代码来自动完成单词和句子?
【发布时间】:2011-12-10 22:07:59
【问题描述】:

我想编写在 Linux 终端中自动完成的代码。代码应该如下工作。

它有一个字符串列表(例如“hello”、“hi”、“how are you”、“goodbye”、“great”...)。

在终端中,用户将开始输入,当有匹配的可能性时,他会得到可能的字符串的提示,他可以从中选择(类似于vim editorgoogle incremental search)。

例如他开始输入“h”,然后他得到了提示

你好“你好”

_“我”

_“你好吗”

如果它不仅可以从开头完成单词,而且可以从字符串的任意部分完成单词,那就更好了。

【问题讨论】:

  • 上下文是什么?您是否在接收用户输入的终端中运行 Python 应用程序?我不明白...
  • @FelixKling 是的,完全正确

标签: python autocomplete


【解决方案1】:

您可能想要结帐快速自动完成: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']]

免责声明:我编写了快速自动完成功能。

【讨论】:

  • 这个其实很方便。谢谢楼主!
  • 当然!很高兴听到您发现它很方便!
  • @coderina 我还没有机会优化它。如果有人有时间通过​​ Cython 对其进行优化,那就太好了。我在创建时的用例不需要庞大的字典。您可以在底部阅读更多内容:github.com/seperman/fast-autocomplete/issues/10
  • @Seperman 好的,非常感谢您的澄清!
  • 哦,对了,我忽略了这一点。谢谢!
【解决方案2】:

对于那些(像我一样)最终在解释器中搜索自动完成功能的人:

https://web.archive.org/web/20140214003802/http://conjurecode.com/enable-auto-complete-in-python-interpreter/

这涉及创建一个文件.pythonrc,修改.bashrc 和一个import sys,每次启动 Python 解释器时都必须导入。

我想知道后者是否可以自动化以获得更大的胜利。

【讨论】:

    【解决方案3】:

    步骤:

    1. 通过以下命令在主目录中创建一个文件 .pythonrc: vi .pythonrc

    2. 输入此内容:

      import rlcompleter, readline  
      readline.parse_and_bind('tab:complete') 
      
    3. 关闭文件

    4. 现在运行

      echo "export PYTHONSTARTUP=~/.pythonrc" >> ~/.bashrc

    5. 重启终端

    【讨论】:

      【解决方案4】:

      要在 Python shell 中启用自动完成功能,请输入:

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

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

      【讨论】:

        【解决方案5】:

        (我知道这并不完全符合您的要求,但是)如果您对出现在 TAB 上的自动完成/建议感到满意(在许多 shell 中使用),然后您可以使用readline 模块快速启动并运行。

        这是一个基于Doug Hellmann's PyMOTW writeup on 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输入),只有一个可能的匹配和整个句子“你好吗”自动完成。

        查看链接文章以获取有关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
        

        更新:使用历史缓冲区(如 cmets 中所述)

        创建用于滚动/搜索的伪菜单的一种简单方法是将关键字加载到历史缓冲区中。然后,您将能够使用向上/向下箭头键滚动条目以及使用 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

        还可以尝试使用向上/向下键滚动浏览关键字。

        【讨论】:

        • 谢谢,我测试了代码。它只缺少一些我想要的功能。 automatic autocomplation while typing, without the need to press tab keyarbitrary part of the strings 完成的可能性,choosing between matches with rows, or other keyboard shortcuts 的可能性。
        • 我忘了这个功能在google里,所以可以尝试用google搜索一下。
        • AFAIK 没有罐装的解决方案来做你想做的事。控制台应用程序中的这种级别的交互性需要更多的工作。正如@jro 在另一个答案中评论的那样,curses 将是一个好的开始。我只是指出基于 cmd-line 的自动完成的更常见方法,即使用 readline。抱歉没有提供更多帮助。祝你的应用好运。
        • “我忘了这个功能在谷歌里”...嗯?你想写什么应用之王?
        • 只是普通的应用程序,可以节省我的打字时间。我希望有一些图书馆可以轻松做到这一点。您的回答是可以接受的,但如果可以改进,我会等待一段时间。谢谢
        【解决方案6】:

        我猜你需要让用户按下一个键。

        你可以用这样的方法来实现它(不按回车键):

        import termios, os, sys
        
        def getkey():
            fd = sys.stdin.fileno()
            old = termios.tcgetattr(fd)
            new = termios.tcgetattr(fd)
            new[3] = new[3] & ~termios.ICANON & ~termios.ECHO
            new[6][termios.VMIN] = 1
            new[6][termios.VTIME] = 0
            termios.tcsetattr(fd, termios.TCSANOW, new)
            c = None
            try:
                c = os.read(fd, 1)
            finally:
                termios.tcsetattr(fd, termios.TCSAFLUSH, old)
            return c
        

        然后,如果这个键是一个 tab 键(例如,这是你需要实现的东西),那么向用户显示所有可能性。如果这是任何其他键,请将其打印在标准输出上。

        哦,当然你需要在一段时间内让 getkey() 循环,只要用户按下回车键。您还可以获得一个类似 raw_input 的方法,当您点击一个选项卡时,它将逐个符号地获取整个单词,或显示所有可能性。

        至少那是项目,你可以开始。如果您遇到任何其他问题,请不要写下来。

        编辑 1:

        get_word 方法可能如下所示:

        def get_word():
            s = ""
            while True:
                a = getkey()
                if a == "\n":
                    break
                elif a == "\t":
                    print "all possibilities"
                else:
                    s += a
        
            return s
        
        word = get_word()
        print word
        

        我现在遇到的问题是显示标志的方式,您刚刚输入时没有任何输入和空格,print aprint a, 都是这样做的。

        【讨论】:

        • 要显示建议,您可以使用curses 模块来模仿vi 显示建议的方式。
        • 哦,以前没听说过这个。看起来很有趣,谢谢:)
        • @Gandi 谢谢。只缺少核心部分incremental matchingshowing hints while typing
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-22
        相关资源
        最近更新 更多