python -m 模块的命令行自动补全

问题描述 投票:0回答:2

是否可以获取

python -m package.subpackage.module
的命令行自动补全?

这类似于,但不一样,

python ./package/subpackage/module.py
,它会自动完成目录和文件路径。然而,使用
-m
,Python 将库的模块作为具有适当命名空间和导入路径的脚本运行。

我希望能够执行

python -m package.s[TAB]
并自动完成
subpackage

此功能是否内置于某处,或者我该如何设置?

python bash autocomplete bash-completion
2个回答
2
投票

正如评论部分所说,您需要扩展 bash-completion 工具。然后,您将创建一个脚本来处理您需要的情况(即:当最后一个参数为

-m
时)。

下面的这个小示例显示了自定义完成脚本的开始。让我们将其命名为

python_completion.sh

_python_target() {
    local cur prev opts

    # Retrieving the current typed argument
    cur="${COMP_WORDS[COMP_CWORD]}"

    # Retrieving the previous typed argument ("-m" for example)
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Preparing an array to store available list for completions
    # COMREPLY will be checked to suggest the list
    COMPREPLY=()

    # Here, we'll only handle the case of "-m"
    # Hence, the classic autocompletion is disabled
    # (ie COMREPLY stays an empty array)
    if [[ "$prev" != "-m" ]]
    then
        return 0
    fi

    # Retrieving paths and converts their separators into dots
    # (if packages doesn't exist, same thing, empty array)
    if [[ ! -e "./package" ]]
    then
       return 0
    fi

    # Otherwise, we retrieve first the paths starting with "./package"
    # and converts their separators into dots
    opts="$(find ./package -type d | sed -e 's+/+.+g' -e 's/^\.//' | head)"

    # We store the whole list by invoking "compgen" and filling
    # COMREPLY with its output content.
    COMPREPLY=($(compgen -W "$opts" -- "$cur"))

}

complete -F _python_target python

(警告。此脚本有一个缺陷,它不适用于包含空格的文件名)。要测试它,请在当前环境中运行它:

. ./python_completion.sh

并测试一下:

python -m packag[TAB]

这里是一个以这种方式继续的教程。


0
投票

寻找这个确切的东西,@Amessihel 的答案是一个非常有用的开始。

我发布了基于它的解决方案,因为我相信它可以帮助其他人,特别是如果您愿意的话:

  • 无论您当前的路径如何,都会自动完成包(对我来说这是使用 -m 的优点之一)
  • 保留标准Python自动完成功能
# man page for "complete": https://manpages.ubuntu.com/manpages/noble/en/man7/bash-builtins.7.html
_python_target() {
    local cur prev opts

    # Retrieving the current typed argument
    cur="${COMP_WORDS[COMP_CWORD]}"
    # Retrieving the previous typed argument ("-m" for example)
    prev="${COMP_WORDS[COMP_CWORD - 1]}"

    # Preparing an array to store available list for completions
    # COMREPLY will be checked to suggest the list
    COMPREPLY=()

    # Here, we only handle the case of "-m"
    # we want to leave the autocomplete of the standard usage to the default,
    # so COMREPLY stays an empty array and we fallback through "-o default"
    if [[ "$prev" != "-m" ]]; then
        return 0
    fi

    # Ensure package exists
    PACKAGE_PATH=replace_this_by_your_package_path
    if [[ ! -e "$PACKAGE_PATH" ]]; then
        echo "$PACKAGE_PATH does not exist on your computer ?"
        return 0
    fi

    # Otherwise, first we retrieve all paths of folder and .py files inside the <your_package> package,
    # we keep only the package related section, remove the .py extension and convert their separators into dots
    opts="$(find $PACKAGE_PATH/your_package -type d -o -regex ".*py" | sed "s|$PACKAGE_PATH||" | sed "s|\.py||" | sed -e 's+/+.+g' -e 's/^\.//')"

    # Then we store the whole list by invoking "compgen" and filling COMREPLY with its output content.
    # To mimick standard bash autocompletions we truncate autocomplete to the next folder (identified by dots)
    COMPREPLY=($(compgen -W "$opts" -- "$cur" | sed "s|\($cur.[^.]*\).*|\1|" | uniq))
}

complete -F _python_target -o nospace -o bashdefault -o default python
# nospace disables printing of a space at the end of autocomplete,
# it allows to chain the autocomplete but:
# - removes the indication on end of chain that only one match was found.
# - removes the addition of the trailing / for standard python completion on folders
© www.soinside.com 2019 - 2024. All rights reserved.