Linux 如何使 python 命令行程序自动完成任意事物而不是解释器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/187621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:34:52  来源:igfitidea点击:

How to make a python, command-line program autocomplete arbitrary things NOT interpreter

pythonlinuxunixcommand-lineautocomplete

提问by Paul D. Eden

I am aware of how to setup autocompletion of python objects in the python interpreter (on unix).

我知道如何在 python 解释器(在 unix 上)中设置 python 对象的自动完成。

  • Google shows many hits for explanations on how to do this.
  • Unfortunately, there are so many references to that it is difficult to find what I need to do, which is slightly different.
  • 谷歌显示了许多关于如何做到这一点的解释。
  • 不幸的是,引用太多了,很难找到我需要做的事情,这略有不同。

I need to know how to enable, tab/auto completion of arbitrary items in a command-line program written in python.

我需要知道如何在用 python 编写的命令行程序中启用、选项卡/自动完成任意项目。

My specific use case is a command-line python program that needs to send emails. I want to be able to autocomplete email addresses (I have the addresses on disk) when the user types part of it (and optionally presses the TAB key).

我的具体用例是一个需要发送电子邮件的命令行 python 程序。我希望能够在用户键入部分电子邮件地址(并可选择按下 TAB 键)时自动完成电子邮件地址(我在磁盘上有地址)。

I do not need it to work on windows or mac, just linux.

我不需要它在 windows 或 mac 上工作,只需要在 linux 上工作。

采纳答案by ephemient

Use Python's readlinebindings. For example,

使用 Python 的readline绑定。例如,

import readline

def completer(text, state):
    options = [i for i in commands if i.startswith(text)]
    if state < len(options):
        return options[state]
    else:
        return None

readline.parse_and_bind("tab: complete")
readline.set_completer(completer)

The official module docsaren't much more detailed, see the readline docsfor more info.

官方模块文档并没有更详细,请参阅readline 文档以获取更多信息。

回答by Florian B?sch

Follow the cmd documentationand you'll be fine

按照cmd 文档,你会没事的

import cmd

addresses = [
    '[email protected]',
    '[email protected]',
    '[email protected]',
]

class MyCmd(cmd.Cmd):
    def do_send(self, line):
        pass

    def complete_send(self, text, line, start_index, end_index):
        if text:
            return [
                address for address in addresses
                if address.startswith(text)
            ]
        else:
            return addresses


if __name__ == '__main__':
    my_cmd = MyCmd()
    my_cmd.cmdloop()

Output for tab -> tab -> send -> tab -> tab -> f -> tab

选项卡的输出 -> 选项卡 -> 发送 -> 选项卡 -> 选项卡 -> f -> 选项卡

(Cmd)
help  send
(Cmd) send
[email protected]            [email protected]         [email protected]
(Cmd) send [email protected]
(Cmd)

回答by Owen

Since you say "NOT interpreter" in your question, I guess you don't want answers involving python readline and suchlike. (edit: in hindsight, that's obviously not the case. Ho hum. I think this info is interesting anyway, so I'll leave it here.)

由于您在问题中说“不是解释器”,我想您不想要涉及 python readline 之类的答案。(编辑:事后看来,显然不是这样。呵呵。我觉得这个信息无论如何都很有趣,所以我会把它留在这里。

I think you might be after this.

我想你可能会在之后。

It's about adding shell-level completion to arbitrary commands, extending bash's own tab-completion.

它是关于向任意命令添加 shell 级完成,扩展 bash 自己的选项卡完成。

In a nutshell, you'll create a file containing a shell-function that will generate possible completions, save it into /etc/bash_completion.d/and register it with the command complete. Here's a snippet from the linked page:

简而言之,您将创建一个包含 shell 函数的文件,该函数将生成可能的补全,将其保存到/etc/bash_completion.d/命令中并注册complete。这是链接页面的一个片段:

_foo() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="--help --verbose --version"

    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _foo foo

In this case, the typing foo --[TAB]will give you the values in the variable opts, i.e. --help, --verboseand --version. For your purposes, you'll essentially want to customise the values that are put into opts.

在这种情况下,打字foo --[TAB]会给你的价值观在变opts,即--help--verbose--version。出于您的目的,您基本上希望自定义放入opts.

Do have a look at the example on the linked page, it's all pretty straightforward.

请查看链接页面上的示例,这一切都非常简单。

回答by Paul D. Eden

Here is a full-working version of the code that was very supplied by ephemient here(thank you).

这是 ephemient在这里非常提供的代码的完整工作版本(谢谢)。

import readline

addrs = ['[email protected]', '[email protected]', '[email protected]']

def completer(text, state):
    options = [x for x in addrs if x.startswith(text)]
    try:
        return options[state]
    except IndexError:
        return None

readline.set_completer(completer)
readline.parse_and_bind("tab: complete")

while 1:
    a = raw_input("> ")
    print "You entered", a

回答by user178047

# ~/.pythonrc
import rlcompleter, readline
readline.parse_and_bind('tab:complete')

# ~/.bashrc
export PYTHONSTARTUP=~/.pythonrc

回答by qed

I am surprised that nobody has mentioned argcomplete, here is an example from the docs:

我很惊讶没有人提到 argcomplete,这是文档中的一个例子:

from argcomplete.completers import ChoicesCompleter

parser.add_argument("--protocol", choices=('http', 'https', 'ssh', 'rsync', 'wss'))
parser.add_argument("--proto").completer=ChoicesCompleter(('http', 'https', 'ssh', 'rsync', 'wss'))

回答by Seperman

The posted answers work fine but I have open sourced an autocomplete library that I wrote at work. We have been using it for a while in production and it is fast, stable and easy to use. It even has a demo mode so you can quickly test what you would get as you type words.

发布的答案工作正常,但我已经开源了我在工作中编写的自动完成库。我们已经在生产中使用了一段时间,它快速、稳定且易于使用。它甚至还有一个演示模式,所以你可以快速测试你在输入单词时会得到什么。

To install it, simply run: pip install fast-autocomplete

要安装它,只需运行: pip install fast-autocomplete

Here is an example:

下面是一个例子:

>>> 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']]

Checkout: https://github.com/wearefair/fast-autocompletefor the source code.

结帐:https: //github.com/wearefair/fast-autocomplete获取源代码。

And here is an explanation of how it works: http://zepworks.com/posts/you-autocomplete-me/

这是它如何工作的解释:http: //zepworks.com/posts/you-autocomplete-me/

It deals with mis-spellings and optionally sorting by the weight of the word. (let's say burritois more important than book, then you give burritoa higher "count" and it will show up first before bookin the results.

它处理拼写错误,并可选择按单词的权重排序。(假设burrito比 更重要book,那么您给出burrito更高的“计数”,它会先book出现在结果中。

Words is a dictionary and each word can have a context. For example the "count", how to display the word, some other context around the word etc. In this example words didn't have any context.

单词是一本字典,每个单词都可以有上下文。例如“计数”,如何显示单词,单词周围的一些其他上下文等。在此示例中,单词没有任何上下文。

回答by Flux

You can try using the Python Prompt Toolkit, a library for building interactive command line applications in Python.

您可以尝试使用Python Prompt Toolkit,这是一个用于在 Python 中构建交互式命令行应用程序的库。

The library makes it easy to add interactive autocomplete functionality, allowing the user to use the Tabkey to visually cycle through the available choices. The library is cross-platform (Linux, OS X, FreeBSD, OpenBSD, Windows). Example:

该库可以轻松添加交互式自动完成功能,允许用户使用Tab键在可用选项之间进行可视化循环。该库是跨平台的(Linux、OS X、FreeBSD、OpenBSD、Windows)。例子:

pgcli - Python Prompt Toolkit

pgcli - Python 提示工具包

(Image source: pcgli)

(图片来源:pcgli