如何使用文件路径自动完成 bash 命令行?

2023-12-07

Context

我正在创建一个 shell 程序,它是一个命令行工具。我想为这个工具创建我自己的自动完成功能。

我想做两件不同的事情(也许我应该发布两个问题):

  • 对于选项--install and -i,我想自动完成文件路径,例如ls命令执行。
  • 对于选项--unit-test and -t,我想自动完成我可以运行的特定目录中的文件路径my_app --directory.

my_app_autocomplete file

__my_app_autocomplete()
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="--help -h --install -i --run -r --rebuild -rb --show-running-containers -ps --stop -s --remove -rm --logs -l --bash -b --sass -css --unit-tests -t"
    containers="nginx php mysql mongo node"
    sass="watch"

    # By default, autocomplete with options
    if [[ ${prev} == my_app ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
    # By default, autocomplete with options
    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
    # For --install and -i options, autocomplete with folder
    if [ ${prev} == --install ] || [ ${prev} == -i ] ; then
        COMPREPLY=( $(compgen -d -- ${cur}) )
        return 0
    fi
    # For --stop --remove --logs and --bash, autocomplete with containers
    if [ ${prev} == --stop ] || [ ${prev} == -s ] || [ ${prev} == --remove ] || [ ${prev} == -rm ] || [ ${prev} == --logs ] || [ ${prev} == -l ] || [ ${prev} == --bash ] || [ ${prev} == -b ] ; then
        COMPREPLY=( $(compgen -W "${containers}" -- ${cur}) )
        return 0
    fi
    # For --sass and -css, complete with sass options
    if [ ${prev} == --sass ] || [ ${prev} == -css ] ; then
        COMPREPLY=( $(compgen -W "${sass}" -- ${cur}) )
        return 0
    fi
    # For --unit-tests and -t, complete with relative to my_app folder paths
    if [ ${prev} == --unit-tests ] || [ ${prev} == -t ] ; then
        COMPREPLY=( $(compgen -d -- ${cur}) )
        return 0
    fi
}
complete -F __my_app_autocomplete my_app

Problem

我在一个特定的问题上遇到了困难:自动完成文件路径。

我不明白compgen选项以及如何使用它做事。也许我可以尝试运行子命令,但我不知道语法,除了以下之外我找不到任何有用的信息man of bash - 可编程完成内置函数其中没有提供太多信息compgen.

在这种情况下,当我这样做时:

user@computer:~$ my_app --install D[TAB][TAB]

我想:

user@computer:~$ my_app --install Documents/

我得到:

user@computer:~$ myapp --install Documents 

行尾有一个空格,这是一个问题,因为我必须删除它并添加一个/能够重做[TAB][TAB]自动完成子目录。

调查

-o 无空间

随着选项-o nospace应用于complete as:

complete -o nospace -F __my_app_autocomplete my_app

行为是:

user@computer:~$ myapp --i[TAB][TAB]
user@computer:~$ myapp --install

没有空间。

user@computer:~$ myapp --install D[TAB][TAB]
user@computer:~$ myapp --install Documents

没有空间。

问题:

  • 它删除了所有选项的空格,迫使我在那些不是文件路径的选项之后手动添加一个空格(例如--install)
  • 我必须添加/导航到子目录

-o 文件名

随着选项-o filenames应用于complete as:

complete -o filenames -F __my_app_autocomplete my_app

行为是:

user@computer:~$ myapp --i[TAB][TAB]
user@computer:~$ myapp --install

有一个空格

user@computer:~$ myapp --install D[TAB][TAB]
user@computer:~$ myapp --install Documents/

with a /如果是目录则没有空格

user@computer:~$ myapp --install f[TAB][TAB]
user@computer:~$ myapp --install file 

如果是文件则带有空格

它似乎只为未在单词列表中定义的完成设置路径,因此它不会影响其他完成,我认为这是我需要的第一部分。

从特定目录

我将提出另一个问题以避免混淆:如何使用特定目录中的文件路径自动完成 bash 命令行而不显示该目录?


自动完成文件路径

代替

complete -F __my_app_autocomplete my_app

with

complete -o filenames -F __my_app_autocomplete my_app

在这里您可以找到所有 compgen 选项的解释:

https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用文件路径自动完成 bash 命令行? 的相关文章

随机推荐