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

时间:2017-06-08 16:36:27

标签: linux bash autocomplete

上下文

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

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

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

my_app_autocomplete档案

__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

问题

我在特定点上挣扎:自动完成文件路径。

我不理解compgen选项以及如何使用它。也许我可以尝试运行子命令,但我不知道语法,除了man of bash - Programmable completion builtins之外我找不到任何有用的信息,这些信息没有提供有关compgen的更多信息。

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

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

我想:

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

我获得:

user@computer:~$ myapp --install Documents 

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

调查

-o nospace

-o nospace选项complete应用于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 filenames以导航到子目录

-o filenames

complete选项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/

行为是:

/

带空格

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

FROM amazonlinux WORKDIR /shared RUN yum -y install gcc ADD http://www.cpan.org/src/5.0/perl-5.22.1.tar.gz /shared RUN tar -xzf perl-5.22.1.tar.gz RUN /shared/perl-5.22.1/Configure -des -Dprefix=/opt/perl-5.22.1/localperl RUN make -C /shared/perl-5.22.1 RUN make -C /shared/perl-5.22.1 test RUN make -C /shared/perl-5.22.1 install ,如果是目录,则没有空格

Step 14/20 : ADD http://www.cpan.org/src/5.0/perl-5.22.1.tar.gz /shared
Downloading 15.92 MB/15.92 MB
 ---> Using cache
 ---> 24f3b38dee5f
Step 15/20 : RUN tar -xzf perl-5.22.1.tar.gz
 ---> Using cache
 ---> 42ecf82ce73d
Step 16/20 : RUN /shared/perl-5.22.1/Configure -des -Dprefix=/opt/perl-5.22.1/localperl
 ---> Using cache
 ---> dfe8d71f5ff1
Step 17/20 : RUN make -C /shared/perl-5.22.1/
 ---> Running in 2766b0c8e9a5
make: Entering directory `/shared/perl-5.22.1'
make: Leaving directory `/shared/perl-5.22.1'
make: *** No targets specified and no makefile found.  Stop.
The command '/bin/sh -c make -C /shared/perl-5.22.1/' returned a non-zero code: 2
ish-mac:testanalyse ish$ ls -l

如果是文件,请使用空格

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

来自特定目录

我会打开另一个问题以避免混淆:How to autocomplete a bash commandline with file paths from a specific directory without displaying this directory?

1 个答案:

答案 0 :(得分:1)

自动完成文件路径

替代

complete -F __my_app_autocomplete my_app

complete -o filenames -F __my_app_autocomplete my_app

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

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