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 命令行而不显示该目录?